Parallel brute force: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|C sharp|C#}}: added zkl header)
(added elixir solution)
 
(118 intermediate revisions by 32 users not shown)
Line 1: Line 1:
{{draft task|Parallel Brute Force}}
{{task|Parallel Brute Force}}


;Task:
;Task:


Find, through brute force, the five-letter passwords corresponding with the following [[SHA256]] hashes:
Find, through brute force, the five-letter passwords corresponding with the following [[wp:SHA-256|SHA-256]] hashes:


1. 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
1. 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
Line 9: Line 9:
3. 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
3. 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f


Your program should naively iterate through all possible passwords consisting only of five lower-case ASCII English letters. It should use concurrent or parallel processing, if your language supports that feature. You may calculate SHA256 hashes by calling a library or through a custom implementation. Print each matching password, along with its SHA256 value. Optionally, measure how long your program takes to run, and print that time.
Your program should naively iterate through all possible passwords consisting only of five lower-case ASCII English letters. It should use concurrent or parallel processing, if your language supports that feature. You may calculate SHA-256 hashes by calling a library or through a custom implementation. Print each matching password, along with its SHA-256 hash.

Related task: [[SHA-256]]

=={{header|Ada}}==
{{libheader|CryptAda}}
<syntaxhighlight lang="ada">with Ada.Text_IO;

with CryptAda.Digests.Message_Digests.SHA_256;
with CryptAda.Digests.Hashes;
with CryptAda.Pragmatics;

procedure Brute_Force is
use CryptAda.Digests.Message_Digests;
use CryptAda.Digests.Hashes;
use CryptAda.Digests;
use CryptAda.Pragmatics;

Wanted_Sums : constant array (1 .. 3) of String (1 .. 64) :=
(1 => "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
2 => "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
3 => "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
Wanted_Hash : constant array (1 .. 3) of Hashes.Hash :=
(1 => Hashes.To_Hash (Wanted_Sums (1)),
2 => Hashes.To_Hash (Wanted_Sums (2)),
3 => Hashes.To_Hash (Wanted_Sums (3)));

subtype Ciffer is Byte range Character'Pos ('a') .. Character'Pos ('z');
subtype Code is Byte_Array (1 .. 5);

task type Worker (First : Byte) is
end Worker;

procedure Compare (Hash : in Hashes.Hash; Bytes : in Code) is
begin
for I in Wanted_Hash'Range loop
if Hash = Wanted_Hash (I) then
Ada.Text_IO.Put (Wanted_Sums (I) & " ");
for C of Bytes loop
Ada.Text_IO.Put (Character'Val (C));
end loop;
Ada.Text_IO.New_Line;
end if;
end loop;
end Compare;

task body Worker is
Handle : constant Message_Digest_Handle := SHA_256.Get_Message_Digest_Handle;
Digest : constant Message_Digest_Ptr := Get_Message_Digest_Ptr (Handle);
Bytes : Code;
Hash : Hashes.Hash;
begin
Bytes (Bytes'First) := First;

for B2 in Ciffer'Range loop
for B3 in Ciffer'Range loop
for B4 in Ciffer'Range loop
Bytes (2 .. 4) := B2 & B3 & B4;
for B5 in Ciffer'Range loop
Bytes (5) := B5;
Digest_Start (Digest);
Digest_Update (Digest, Bytes);
Digest_End (Digest, Hash);
Compare (Hash, Bytes);
end loop;
end loop;
end loop;
end loop;
end Worker;

type Worker_Access is access Worker;
Work : Worker_Access;
pragma Unreferenced (Work);
begin
for C in Ciffer'Range loop
Work := new Worker (First => C);
end loop;
end Brute_Force;</syntaxhighlight>

=={{header|BaCon}}==
<syntaxhighlight lang="qbasic">PRAGMA INCLUDE <openssl/sha.h>
PRAGMA LDFLAGS -lcrypto

OPTION MEMTYPE unsigned char

LOCAL buffer[32], passwd[5] TYPE unsigned char
LOCAL result TYPE unsigned char*
LOCAL a,b,c,d,e TYPE NUMBER

DATA "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b", "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f", "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"

WHILE TRUE

READ secret$
IF NOT(LEN(secret$)) THEN BREAK

FOR i = 0 TO 31
buffer[i] = DEC(MID$(secret$, i*2+1, 2))
NEXT

FOR a = 97 TO 122
FOR b = 97 TO 122
FOR c = 97 TO 122
FOR d = 97 TO 122
FOR e = 97 TO 122
passwd[0] = a
passwd[1] = b
passwd[2] = c
passwd[3] = d
passwd[4] = e

result = SHA256(passwd, 5, 0)

FOR i = 0 TO SHA256_DIGEST_LENGTH-1
IF PEEK(result+i) != buffer[i] THEN BREAK
NEXT
IF i = SHA256_DIGEST_LENGTH THEN
PRINT a,b,c,d,e,secret$ FORMAT "%c%c%c%c%c:%s\n"
BREAK 5
END IF
NEXT
NEXT
NEXT
NEXT
NEXT
WEND</syntaxhighlight>
{{out}}
<pre>
apple:3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm:74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx:1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>

=={{header|C}}==
{{trans|C#}}
<syntaxhighlight lang="c">// $ gcc -o parabrutfor parabrutfor.c -fopenmp -lssl -lcrypto
// $ export OMP_NUM_THREADS=4
// $ ./parabrutfor

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include <openssl/sha.h>

typedef unsigned char byte;

int matches(byte *a, byte* b) {
for (int i = 0; i < 32; i++)
if (a[i] != b[i])
return 0;
return 1;
}


byte* StringHashToByteArray(const char* s) {
byte* hash = (byte*) malloc(32);
char two[3];
two[2] = 0;
for (int i = 0; i < 32; i++) {
two[0] = s[i * 2];
two[1] = s[i * 2 + 1];
hash[i] = (byte)strtol(two, 0, 16);
}
return hash;
}

void printResult(byte* password, byte* hash) {
char sPass[6];
memcpy(sPass, password, 5);
sPass[5] = 0;
printf("%s => ", sPass);
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
printf("%02x", hash[i]);
printf("\n");
}

int main(int argc, char **argv)
{

#pragma omp parallel
{

#pragma omp for
for (int a = 0; a < 26; a++)
{
byte password[5] = { 97 + a };
byte* one = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
byte* two = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b");
byte* three = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
for (password[1] = 97; password[1] < 123; password[1]++)
for (password[2] = 97; password[2] < 123; password[2]++)
for (password[3] = 97; password[3] < 123; password[3]++)
for (password[4] = 97; password[4] < 123; password[4]++) {
byte *hash = SHA256(password, 5, 0);
if (matches(one, hash) || matches(two, hash) || matches(three, hash))
printResult(password, hash);
}
free(one);
free(two);
free(three);
}
}

return 0;
}</syntaxhighlight>
{{out}}
<pre>apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
 
 
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Linq;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
Line 23: Line 231:
static void Main(string[] args)
static void Main(string[] args)
{
{
Parallel.For(0, 26, a => {
byte[] one = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
byte[] password = new byte[5];
byte[] two = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b");
byte[] hash;
byte[] three = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
byte[] one = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
var prey = new byte[][] { one, two, three };
byte[] two = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b");
var dt = DateTime.Now;
byte[] three = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
int chunksize = 26 * 26 * 26 * 26 * 26 / Environment.ProcessorCount;
Task[] tasks = (
password[0] = (byte)(97 + a);
var sha = System.Security.Cryptography.SHA256.Create();
from i in Enumerable.Range(0, Environment.ProcessorCount)
for (password[1] = 97; password[1] < 123; password[1]++)
select Task.Run(() => MatchesInRange(i * chunksize, (i + 1) * chunksize - 1, prey))
).ToArray();
for (password[2] = 97; password[2] < 123; password[2]++)
for (password[3] = 97; password[3] < 123; password[3]++)
Task.WaitAll(tasks);
for (password[4] = 97; password[4] < 123; password[4]++)
Console.WriteLine((DateTime.Now - dt).TotalMilliseconds + " milliseconds elapsed.");
{
hash = sha.ComputeHash(password);
if (matches(one, hash) || matches(two, hash) || matches(three, hash))
Console.WriteLine(Encoding.ASCII.GetString(password) + " => "
+ BitConverter.ToString(hash).ToLower().Replace("-", ""));
}
});
}
}
static byte[] StringHashToByteArray(string s)
static byte[] StringHashToByteArray(string s)
Line 40: Line 255:
return Enumerable.Range(0, s.Length / 2).Select(i => (byte)Convert.ToInt16(s.Substring(i * 2, 2), 16)).ToArray();
return Enumerable.Range(0, s.Length / 2).Select(i => (byte)Convert.ToInt16(s.Substring(i * 2, 2), 16)).ToArray();
}
}
static bool matches(byte[] a, byte[] b)

static void MatchesInRange(int start, int stop, byte[][] prey)
{
{
byte[] letters = new byte[5];
for (int i = 0; i < 32; i++)
byte[] hash;
if (a[i] != b[i])
int serial;
return false;
var shaFactory = new SHA256Managed();
return true;
}
for (int seriali = start; seriali <= stop; seriali++)
}</syntaxhighlight>
{

serial = seriali;
{{out}}
int divisor = 456976; // 26 * 26 * 26 * 26;
<pre>apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
for (int i = 0; i < 5; i++)
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
{
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>
letters[i] = (byte)(97 + Math.DivRem(serial, divisor, out serial));

divisor /= 26;
=={{header|C++}}==
{{libheader|OpenSSL}}
<syntaxhighlight lang="cpp">#include <atomic>
#include <cstdio>
#include <cstring>
#include <future>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <openssl/sha.h>

struct sha256 {
unsigned char digest[SHA256_DIGEST_LENGTH];
void compute(const char* str, int len) {
SHA256((const unsigned char*)str, len, digest);
}
bool parse(const std::string& hash) {
if (hash.length() != 2 * SHA256_DIGEST_LENGTH) {
std::cerr << "Invalid SHA-256 hash\n";
return false;
}
const char* p = hash.c_str();
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i, p += 2) {
unsigned int x;
if (sscanf(p, "%2x", &x) != 1) {
std::cerr << "Cannot parse SHA-256 hash\n";
return false;
}
}
hash = shaFactory.ComputeHash(letters);
digest[i] = x;
}
if (hash[0] == prey[0][0] || hash[0] == prey[1][0] || hash[0] == prey[2][0])
{
return true;
}
if (Enumerable.SequenceEqual(hash, prey[0]) || Enumerable.SequenceEqual(hash, prey[1]) || Enumerable.SequenceEqual(hash, prey[2]))
};
{

Console.WriteLine(Encoding.ASCII.GetString(letters) + " => " + BitConverter.ToString(hash).ToLower().Replace("-", ""));
bool operator==(const sha256& a, const sha256& b) {
return memcmp(a.digest, b.digest, SHA256_DIGEST_LENGTH) == 0;
}

bool next_password(std::string& passwd, size_t start) {
size_t len = passwd.length();
for (size_t i = len - 1; i >= start; --i) {
char c = passwd[i];
if (c < 'z') {
++passwd[i];
return true;
}
passwd[i] = 'a';
}
return false;
}

class password_finder {
public:
password_finder(int);
void find_passwords(const std::vector<std::string>&);

private:
int length;
void find_passwords(char);
std::vector<std::string> hashes;
std::vector<sha256> digests;
std::atomic<size_t> count;
};

password_finder::password_finder(int len) : length(len) {}

void password_finder::find_passwords(char ch) {
std::string passwd(length, 'a');
passwd[0] = ch;
sha256 digest;
while (count > 0) {
digest.compute(passwd.c_str(), length);
for (int m = 0; m < hashes.size(); ++m) {
if (digest == digests[m]) {
--count;
std::ostringstream out;
out << "password: " << passwd << ", hash: " << hashes[m]
<< '\n';
std::cout << out.str();
break;
}
}
if (!next_password(passwd, 1))
break;
}
}

void password_finder::find_passwords(const std::vector<std::string>& h) {
hashes = h;
digests.resize(hashes.size());
for (int i = 0; i < hashes.size(); ++i) {
if (!digests[i].parse(hashes[i]))
return;
}
count = hashes.size();
std::vector<std::future<void>> futures;
const int n = 26;
for (int i = 0; i < n; ++i) {
char c = 'a' + i;
futures.push_back(
std::async(std::launch::async, [this, c]() { find_passwords(c); }));
}
}

int main() {
std::vector<std::string> hashes{
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};
password_finder pf(5);
pf.find_passwords(hashes);
return 0;
}</syntaxhighlight>

{{out}}
Execution time is about 0.7 seconds on my system (3.2 GHz Quad-Core Intel Core i5, macOS 10.15.3).
<pre>
password: mmmmm, hash: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
password: apple, hash: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
password: zyzzx, hash: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>

=={{header|Clojure}}==
{{libheader|clojure.math.combinatorics}}
<syntaxhighlight lang="clojure">(ns rosetta.brute-force
(:require [clojure.math.combinatorics :refer [selections]]) ;; https://github.com/clojure/math.combinatorics
(:import [java.util Arrays]
[java.security MessageDigest]))

;;https://rosettacode.org/wiki/Parallel_Brute_Force

(def targets ;; length = 5
["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"])

;; HELPER/UTIL fns
;;=================

(defn digest
"Given a byte-array <bs> returns its hash (also a byte-array)."
^bytes [^MessageDigest md ^bytes bs]
(.digest md bs))

(defn char-range
"Helper fn for easily producing character ranges."
[start end]
(map char (range (int start)
(inc (int end)))))

(def low-case-eng-bytes
"Our search-space (all lower case english characters converted to bytes)."
(map byte (char-range \a \z)))

(defn hex->bytes
"Converts a hex string to a byte-array."
^bytes [^String hex]
(let [len (.length hex)
ret (byte-array (/ len 2))]
(run! (fn [i]
(aset ret
(/ i 2)
^byte (unchecked-add-int
(bit-shift-left
(Character/digit (.charAt hex i) 16)
4)
(Character/digit (.charAt hex (inc i)) 16))))
(range 0 len 2))
ret))

(defn bytes->hex
"Converts a byte-array to a hex string."
[^bytes bs]
(.toString
^StringBuilder
(areduce bs idx ret (StringBuilder.)
(doto ret (.append (format "%02x" (aget bs idx)))))))

;; MAIN LOGIC
;;===========

(defn check-candidate
"Checks whether the SHA256 hash of <candidate> (a list of 5 bytes),
matches <target>. If it does, returns that hash as a hex-encoded String.
Otherwise returns nil."
[^bytes target sha256 candidate]
(let [candidate-bytes (byte-array candidate)
^bytes candidate-hash (sha256 candidate-bytes)]
(when (Arrays/equals target candidate-hash)
(let [answer (String. candidate-bytes)]
(println "Answer found for:" (bytes->hex candidate-hash) "=>" answer)
answer))))

(defn sha256-brute-force
"Top level function. Returns a list with the 3 answers."
[space hex-hashes]
(->> hex-hashes
(map hex->bytes) ;; convert the hex strings to bytes
(pmap ;; parallel map the checker-fn
(fn [target-bytes]
(let [message-digest (MessageDigest/getInstance "SHA-256") ;; new digest instance per thread
sha256 (partial digest message-digest)]
(some (partial check-candidate target-bytes sha256)
(selections space 5)))))))
</syntaxhighlight>
{{out}}
<pre>Answer found for: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b => apple
Answer found for: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f => mmmmm
Answer found for: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad => zyzzx</pre>

=={{header|Common Lisp}}==
{{libheader|lparallel}}
{{libheader|ironclad}}
<syntaxhighlight lang="lisp">(defpackage #:parallel-brute-force
(:use #:cl
#:lparallel))

(in-package #:parallel-brute-force)

(defparameter *alphabet* "abcdefghijklmnopqrstuvwxyz")
(defparameter *hash0* "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
(defparameter *hash1* "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
(defparameter *hash2* "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
(defparameter *kernel-size* 7)

(defun sha-256 (input)
(ironclad:byte-array-to-hex-string
(ironclad:digest-sequence :sha256 (ironclad:ascii-string-to-byte-array input))))

(defun call-with-5-char-string (fun first-char)
(loop with str = (make-array 5 :element-type 'character :initial-element first-char)
for c1 across *alphabet*
do (setf (char str 1) c1)
(loop for c2 across *alphabet*
do (setf (char str 2) c2)
(loop for c3 across *alphabet*
do (setf (char str 3) c3)
(loop for c4 across *alphabet*
do (setf (char str 4) c4)
(funcall fun (copy-seq str)))))))

(defmacro with-5-char-string ((str first-char) &body body)
`(call-with-5-char-string (lambda (,str) ,@body) ,first-char))

(defun find-passwords-with (first-char)
(let (results)
(with-5-char-string (str first-char)
(let ((hash (sha-256 str)))
(when (or (string= hash *hash0*) (string= hash *hash1*) (string= hash *hash2*))
(push (list str hash) results))))
(nreverse results)))

(defun find-passwords ()
(setf *kernel* (make-kernel *kernel-size*))
(let ((results (unwind-protect
(pmapcan #'find-passwords-with *alphabet*)
(end-kernel))))
(dolist (r results)
(format t "~A: ~A~%" (first r) (second r)))))</syntaxhighlight>
{{out}}
<pre>apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>

=={{header|D}}==
There is at least one more method not shown for doing the task in parallel, which uses the std.concurrency module instead.
<syntaxhighlight lang="d">import std.digest.sha;
import std.parallelism;
import std.range;
import std.stdio;

// Find the five lower-case letter strings representing the following sha256 hashes
immutable p1 = cast(ubyte[32]) x"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad";
immutable p2 = cast(ubyte[32]) x"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b";
immutable p3 = cast(ubyte[32]) x"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f";

void main() {
import std.datetime.stopwatch;

auto sw = StopWatch(AutoStart.yes);
// Switch these top loops to toggle between non-parallel and parrallel solutions.
// foreach(char a; 'a'..'z'+1) {
foreach(i, a; taskPool.parallel(iota('a', 'z'+1))) {
char[5] psw;
psw[0] = cast(char) a;
foreach(char b; 'a'..'z'+1) {
psw[1] = b;
foreach(char c; 'a'..'z'+1) {
psw[2] = c;
foreach(char d; 'a'..'z'+1) {
psw[3] = d;
foreach(char e; 'a'..'z'+1) {
psw[4] = e;
auto hash = psw.sha256Of;
if (equal(hash, p1) || equal(hash, p2) || equal(hash, p3)) {
writefln("%s <=> %(%x%)", psw, hash);
}
}
}
}
}
}
}
}
}
}
sw.stop;
}</lang>
writeln(sw.peek);
}

//Specialization that supports static arrays too
bool equal(T)(const T[] p, const T[] q) {
if (p.length != q.length) {
return false;
}

for(int i=0; i<p.length; i++) {
if (p[i] != q[i]) {
return false;
}
}

return true;
}</syntaxhighlight>

{{out}}
Parallel run time: 9 secs, 684 ms, 678 ╬╝s, and 6 hnsecs<br>
Sequential run time: 29 secs, 298 ms, and 837 ╬╝s
<pre>apple <=> 3a7bd3e236a3d29eea436fcfb7e44c735d117c42d1c183542b6b9942dd4f1b
mmmmm <=> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx <=> 1115dd80feaacefdf481f1f9070374a2a81e27880f187396db67958b27cbad</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.Threading}}
{{libheader| DCPsha256}}[[https://github.com/StephenGenusa/DCPCrypt]]
<syntaxhighlight lang="delphi">
program Parallel_Brute_Force;

{$APPTYPE CONSOLE}

uses
System.SysUtils,
System.Threading,
DCPsha256;

function Sha256(W: string): string;
var
HashDigest: array[0..31] of byte;
d, i: Byte;
begin
Result := '';
with TDCP_sha256.Create(nil) do
begin
Init;
UpdateStr(W);
final(HashDigest[0]);
for i := 0 to High(HashDigest) do
Result := Result + lowercase(HashDigest[i].ToHexString(2));
end;
end;

procedure Force(a: int64);
var
password: string;
hash: string;
i, j, k, l: integer;
w: string;
const
Words: TArray<string> = ['1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad',
'3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b',
'74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f'];
begin
password := ' ';
password[1] := chr(97 + a);

for i := 97 to 122 do
begin
password[2] := chr(i);
for j := 97 to 122 do
begin
password[3] := chr(j);
for k := 97 to 122 do
begin
password[4] := chr(k);
for l := 97 to 122 do
begin
password[5] := chr(l);
hash := Sha256(password);

for w in Words do
begin
if SameText(hash, w) then
begin
Writeln('>>', password, ' => ', hash);
end;
end;
end;
end;
end;
end;
end;

var
s: string;
begin

TParallel.&For(0, 25, Force);

Writeln('Enter to exit');
readln;
end.</syntaxhighlight>

=={{header|Elixir}}==
<syntaxhighlight lang="elixir">
defmodule RosettacodeBruteForce do
require Logger

@spec start() :: :ok
def start() do
children = [
{Task.Supervisor, name: Bf.TaskSupervisor}
]
Supervisor.start_link(children, strategy: :one_for_one)
start_bf("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
start_bf("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
start_bf("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
:ok
end

@spec start_bf(String.t()) :: :ok
def start_bf(target) do
Enum.each(0..25, fn a ->
Enum.each(0..25, fn b ->
Task.Supervisor.async(Bf.TaskSupervisor, fn ->
solve_bf(a, b, target)
end)
end)
end)
:ok
end

defp solve_bf(a, b, target) do
Enum.each(0..25, fn x ->
Enum.each(0..25, fn y ->
Enum.each(0..25, fn z ->
candidate = List.to_string([?a + a, ?a + b, ?a + x, ?a + y, ?a + z])
if (check_hash?(candidate, target)) do
Logger.info("SOLVED: #{candidate} = #{target}")
end
end)
end)
end)
:ok
end

defp check_hash?(candidate, target) do
target == :crypto.hash(:sha256, candidate)
|> Base.encode16()
|> String.downcase()
end
end
</syntaxhighlight>
{{out}}
<pre>
08:19:43.178 [info] SOLVED: apple = 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
08:19:43.489 [info] SOLVED: zyzzx = 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
08:19:50.224 [info] SOLVED: mmmmm = 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
</pre>

=={{header|Erlang}}==
There are a total of 8 tasks, each handling a different set of prefixes (abc, def, ghi, jkl, mno, pqr, stuv, wxyz)
<syntaxhighlight lang="erlang">
#! /usr/bin/escript
-mode(compile).
-export([cracker/4, supervisor/3]).

hexdigit(N) when (N >= 0) and (N =< 9) -> N + $0;
hexdigit(N) when (N >= 10) and (N < 16) -> N - 10 + $a.

hexbyte(N) -> [hexdigit(N bsr 4), hexdigit(N band 15)].

match(Key, Hash) ->
B = crypto:hash(sha256, Key),
Hash == lists:append([hexbyte(X) || <<X:8/integer>> <= B]).

cracker(Prefixes, Rest, Hashes, Boss) ->
Results = [[[P|Q], Hash]
|| P <- Prefixes, Q <- Rest, Hash <- Hashes, match([P|Q], Hash)],
Boss ! {done, Results}.

supervisor(0, Results, Caller) -> Caller ! {done, Results};
supervisor(Tasks, Results, Caller) ->
receive
{done, Cracked} -> supervisor(Tasks - 1, Cracked ++ Results, Caller)
end.

main(_) ->
Tasks = ["abc", "def", "ghi", "jkl", "mno", "pqr", "stuv", "wxyz"],
Letter = lists:seq($a, $z),
Rest = [[B, C, D, E] || B <- Letter, C <- Letter, D <- Letter, E <- Letter],
Hashes = [
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
],
Boss = spawn(?MODULE, supervisor, [length(Tasks), [], self()]),
[spawn(?MODULE, cracker, [Prefixes, Rest, Hashes, Boss])
|| Prefixes <- Tasks],

receive
{done, Results} -> Results
end,

[io:format("~s: ~s~n", Result) || Result <- Results].
</syntaxhighlight>
{{Out}}
<pre>
$ ./par-brute.erl
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
</pre>

=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
(*
Nigel Galloway February 21st., 2017
*)
let N n i g e l =
let G = function
|"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"->Some(string n+string i+string g+string e+string l)
|"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"->Some(string n+string i+string g+string e+string l)
|"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"->Some(string n+string i+string g+string e+string l)
|_->None
G ([|byte n;byte i;byte g;byte e;byte l|]|>System.Security.Cryptography.SHA256.Create().ComputeHash|>Array.map(fun (x:byte)->System.String.Format("{0:x2}",x))|>String.concat "")
open System.Threading.Tasks
let n1 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n2 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n3 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n4 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n5 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n6 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n7 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n8 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))

for r in n1.Result@n2.Result@n3.Result@n4.Result@n5.Result@n6.Result@n7.Result@n8.Result do printfn "%s" r
</syntaxhighlight>
{{out}}
<pre>

mmmmm
apple
zyzzx
</pre>

=={{header|FreeBASIC}}==
{{trans|Visual_Basic_.NET}}
{{trans|BaCon}}
<syntaxhighlight lang="freebasic">Function SHA_256(Byval message As String) As String
#Macro Ch (x, y, z)
(((x) And (y)) Xor ((Not (x)) And z))
#EndMacro
#Macro Maj (x, y, z)
(((x) And (y)) Xor ((x) And (z)) Xor ((y) And (z)))
#EndMacro
#Macro sigma0 (x)
(((x) Shr 2 Or (x) Shl 30) Xor ((x) Shr 13 Or (x) Shl 19) Xor ((x) Shr 22 Or (x) Shl 10))
#EndMacro
#Macro sigma1 (x)
(((x) Shr 6 Or (x) Shl 26) Xor ((x) Shr 11 Or (x) Shl 21) Xor ((x) Shr 25 Or (x) Shl 7))
#EndMacro
#Macro sigma2 (x)
(((x) Shr 7 Or (x) Shl 25) Xor ((x) Shr 18 Or (x) Shl 14) Xor ((x) Shr 3))
#EndMacro
#Macro sigma3 (x)
(((x) Shr 17 Or (x) Shl 15) Xor ((x) Shr 19 Or (x) Shl 13) Xor ((x) Shr 10))
#EndMacro
Dim As Long i, j
Dim As Ubyte Ptr ww1
Dim As Uinteger<32> Ptr ww4
Dim As Ulongint l = Len(message)
' set the first bit after the message to 1
message = message + Chr(1 Shl 7)
' add one char to the length
Dim As Ulong padding = 64 - ((l + 1) Mod (512 \ 8))
' check if we have enough room for inserting the length
If padding < 8 Then padding += 64
message += String(padding, Chr(0)) ' adjust length
Dim As Ulong l1 = Len(message) ' new length
l = l * 8 ' orignal length in bits
' create ubyte ptr to point to l ( = length in bits)
Dim As Ubyte Ptr ub_ptr = Cast(Ubyte Ptr, @l)
For i = 0 To 7 'copy length of message to the last 8 bytes
message[l1 -1 - i] = ub_ptr[i]
Next
'table of constants
Dim As Uinteger<32> K(0 To ...) = { _
&H428a2f98, &H71374491, &Hb5c0fbcf, &He9b5dba5, &H3956c25b, &H59f111f1, _
&H923f82a4, &Hab1c5ed5, &Hd807aa98, &H12835b01, &H243185be, &H550c7dc3, _
&H72be5d74, &H80deb1fe, &H9bdc06a7, &Hc19bf174, &He49b69c1, &Hefbe4786, _
&H0fc19dc6, &H240ca1cc, &H2de92c6f, &H4a7484aa, &H5cb0a9dc, &H76f988da, _
&H983e5152, &Ha831c66d, &Hb00327c8, &Hbf597fc7, &Hc6e00bf3, &Hd5a79147, _
&H06ca6351, &H14292967, &H27b70a85, &H2e1b2138, &H4d2c6dfc, &H53380d13, _
&H650a7354, &H766a0abb, &H81c2c92e, &H92722c85, &Ha2bfe8a1, &Ha81a664b, _
&Hc24b8b70, &Hc76c51a3, &Hd192e819, &Hd6990624, &Hf40e3585, &H106aa070, _
&H19a4c116, &H1e376c08, &H2748774c, &H34b0bcb5, &H391c0cb3, &H4ed8aa4a, _
&H5b9cca4f, &H682e6ff3, &H748f82ee, &H78a5636f, &H84c87814, &H8cc70208, _
&H90befffa, &Ha4506ceb, &Hbef9a3f7, &Hc67178f2 }
Dim As Uinteger<32> h0 = &H6a09e667
Dim As Uinteger<32> h1 = &Hbb67ae85
Dim As Uinteger<32> h2 = &H3c6ef372
Dim As Uinteger<32> h3 = &Ha54ff53a
Dim As Uinteger<32> h4 = &H510e527f
Dim As Uinteger<32> h5 = &H9b05688c
Dim As Uinteger<32> h6 = &H1f83d9ab
Dim As Uinteger<32> h7 = &H5be0cd19
Dim As Uinteger<32> a, b, c, d, e, f, g, h
Dim As Uinteger<32> t1, t2, w(0 To 63)
For j = 0 To (l1 -1) \ 64 ' split into block of 64 bytes
ww1 = Cast(Ubyte Ptr, @message[j * 64])
ww4 = Cast(Uinteger<32> Ptr, @message[j * 64])
For i = 0 To 60 Step 4 'little endian -> big endian
Swap ww1[i ], ww1[i +3]
Swap ww1[i +1], ww1[i +2]
Next i
For i = 0 To 15 ' copy the 16 32bit block into the array
W(i) = ww4[i]
Next i
For i = 16 To 63 ' fill the rest of the array
w(i) = sigma3(W(i -2)) + W(i -7) + sigma2(W(i -15)) + W(i -16)
Next i
a = h0 : b = h1 : c = h2 : d = h3 : e = h4 : f = h5 : g = h6 : h = h7
For i = 0 To 63
t1 = h + sigma1(e) + Ch(e, f, g) + K(i) + W(i)
t2 = sigma0(a) + Maj(a, b, c)
h = g : g = f : f = e
e = d + t1
d = c : c = b : b = a
a = t1 + t2
Next i
h0 += a : h1 += b : h2 += c : h3 += d
h4 += e : h5 += f : h6 += g : h7 += h
Next j
Dim As String answer = Hex(h0, 8) + Hex(h1, 8) + Hex(h2, 8) + Hex(h3, 8)
answer += Hex(h4, 8) + Hex(h5, 8) + Hex(h6, 8) + Hex(h7, 8)
Return Lcase(answer)
End Function

Dim t0 As Double = Timer
Dim Shared sha256fp(0 To 2) As String
sha256fp(0) = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
sha256fp(1) = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
sha256fp(2) = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"

Sub PrintCode(n As Integer)
Dim As String fp = sha256fp(n)
Dim As Integer c1, c2, c3, c4, c5
For c1 = 97 To 122
For c2 = 97 To 122
For c3 = 97 To 122
For c4 = 97 To 122
For c5 = 97 To 122
If fp = SHA_256(Chr(c1)+Chr(c2)+Chr(c3)+Chr(c4)+Chr(c5)) Then
Print Chr(c1)+Chr(c2)+Chr(c3)+Chr(c4)+Chr(c5); " => "; fp
Exit For, For, For, For, For
End If
Next c5
Next c4
Next c3
Next c2
Next c1
End Sub

For i As Byte= 0 to 2
PrintCode(i)
Next i
Sleep</syntaxhighlight>

=={{header|Frink}}==
This does not use any parallel processing but just demonstrates Frink's built-in password hashing.
<syntaxhighlight lang="frink">hashes = new set["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]

r = new range["a", "z"]
multifor array = [r,r,r,r,r]
{
str = join["", array]
hash = messageDigest[str, "SHA-256"]
if hashes.contains[hash]
println["$str: $hash"]
}</syntaxhighlight>
{{out}}
<pre>
apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>

=={{header|Go}}==
This solution runs 26 goroutines, one for each possible password first letter.
Goroutines run in parallel on a multicore system.
<syntaxhighlight lang="go">package main

import (
"crypto/sha256"
"encoding/hex"
"log"
"sync"
)

var hh = []string{
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f",
}

func main() {
log.SetFlags(0)
hd := make([][sha256.Size]byte, len(hh))
for i, h := range hh {
hex.Decode(hd[i][:], []byte(h))
}
var wg sync.WaitGroup
wg.Add(26)
for c := byte('a'); c <= 'z'; c++ {
go bf4(c, hd, &wg)
}
wg.Wait()
}

func bf4(c byte, hd [][sha256.Size]byte, wg *sync.WaitGroup) {
p := []byte("aaaaa")
p[0] = c
p1 := p[1:]
p:
for {
ph := sha256.Sum256(p)
for i, h := range hd {
if h == ph {
log.Println(string(p), hh[i])
}
}
for i, v := range p1 {
if v < 'z' {
p1[i]++
continue p
}
p1[i] = 'a'
}
wg.Done()
return
}
}</syntaxhighlight>
{{out}}
<pre>
zyzzx 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
apple 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
</pre>
=={{header|Haskell}}==
Uses libraries:
<ul>
<li>cryptonite</li>
<li>monad-par</li>
<li>bytestring</li>
<li>split</li>
</ul>
<br/>
Compile with "-O2 -threaded"<br/>
7.391s elapsed on a 2.5 GHz Dual-Core Intel Core i7 Macbook Pro.
<syntaxhighlight lang="haskell">import Control.Concurrent (setNumCapabilities)
import Crypto.Hash (hashWith, SHA256 (..), Digest)
import Control.Monad (replicateM, join, (>=>))
import Control.Monad.Par (runPar, get, spawnP)
import Data.ByteString (pack)
import Data.List.Split (chunksOf)
import GHC.Conc (getNumProcessors)
import Text.Printf (printf)

hashedValues :: [Digest SHA256]
hashedValues = read <$>
[ "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
, "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
, "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad" ]

bruteForce :: Int -> [(String, String)]
bruteForce n = runPar $ join <$>
(mapM (spawnP . foldr findMatch []) >=> mapM get) chunks
where
chunks = chunksOf (26^5 `div` n) $ replicateM 5 [97..122]
findMatch s accum
| hashed `elem` hashedValues = (show hashed, show bStr) : accum
| otherwise = accum
where
bStr = pack s
hashed = hashWith SHA256 bStr

main :: IO ()
main = do
cpus <- getNumProcessors
setNumCapabilities cpus
printf "Using %d cores\n" cpus
mapM_ (uncurry (printf "%s -> %s\n")) (bruteForce cpus)</syntaxhighlight>
{{out}}
<pre>brute
Using 4 cores
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b -> apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f -> mmmmm
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad -> zyzzx
</pre>
Or using worker threads with buffered read/write channels.

<p>Here all the possible test strings are batched as a stream that is fed to worker threads via a single read channel (batchChan). Each worker thread listens to the read channel (batchChan) and will write to the write channel (resultChan) when it finds a match. The worker threads loop indefinitely returning to read the next message on the read channel (batchChan). The main thread listens to the write channel (resultChan) and terminates once all three messages have been received.</p>
<syntaxhighlight lang="haskell">import Control.Concurrent (forkIO, setNumCapabilities)
import Control.Concurrent.Chan (Chan, newChan, readChan, writeList2Chan)
import Control.Monad (replicateM, replicateM_, forever)
import Crypto.Hash (SHA256(..), Digest, hashWith)
import Data.Bifunctor (first)
import Data.ByteString (ByteString, pack)
import Data.Char (isDigit)
import Data.List.Split (chunksOf)
import Data.Word (Word8)
import GHC.Conc (getNumProcessors)
import System.Environment (getArgs)
import Text.Printf (printf)

type Decrypted = String
type Encrypted = Digest SHA256
type TestString = [Word8]

hashedValues :: [Encrypted]
hashedValues = read <$>
[ "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
, "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
, "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad" ]

chunks :: [[TestString]]
chunks = chunksOf (10^3) $ replicateM 5 [97..122]

findMatch :: TestString -> [(Encrypted, Decrypted)] -> [(Encrypted, Decrypted)]
findMatch w acc
| hashed `elem` hashedValues = (hashed, show bStr):acc
| otherwise = acc
where
bStr = pack w
hashed = hashWith SHA256 bStr

searchWorker :: Chan [TestString] -> Chan (Encrypted, Decrypted) -> IO ()
searchWorker batchChan resultChan = forever (readChan batchChan >>= writeList2Chan resultChan . foldr findMatch [])

parseInput :: [String] -> Int -> Int
parseInput [] n = n
parseInput (s:_) n = if all isDigit s then read s else n

main :: IO ()
main = do
workers <- getArgs
cpus <- getNumProcessors
let wCount = parseInput workers cpus
setNumCapabilities wCount
printf "Using %d workers on %d cpus.\n" wCount cpus
resultChan <- newChan
batchChan <- newChan
replicateM_ wCount (forkIO $ searchWorker batchChan resultChan)
writeList2Chan batchChan chunks
replicateM_ (length hashedValues) (readChan resultChan >>= uncurry (printf "%s -> %s\n") . first show)</syntaxhighlight>
{{out}}
<pre>brute2
Using 4 workers on 4 cpus.
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b -> "apple"
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f -> "mmmmm"
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad -> "zyzzx"</pre>

=={{header|Java}}==
{{works with |Java| 1.5}}
This example uses Java's multithreading capabilities. Note that the Java Virtual Machine will use native Threads if the underlying platform supprts them. If there is no native thread support, the Java VM will emulate threads.
This implementation runs 3 threads (one per hash to crack), and short-stops when a match for a hash is found.

<syntaxhighlight lang="java">import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* "Main Program" that does the parallel processing
*/
public class ParallelBruteForce {

public static void main(String[] args) throws NoSuchAlgorithmException {

//the hashes to be cracked
String[] hashes = {"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};

//An ExecutorService is a high-level parallel programming facility, that can execute a number of tasks
//the FixedThreadPool is an ExecutorService that uses a configurable number of parallel threads
ExecutorService executorService = Executors.newFixedThreadPool(3);

//Submit one Task per hash to the thread po
for (String hash : hashes) {
executorService.submit(new Forcer(hash));
}

//An ExecutorSerice must be shut down properly (this also causes the program to await termination of
// all pending tasks in the thread pool)
executorService.shutdown();
}
}

/**
* The Class that contains the actual brute-forcing task.
* <p>
* It implements the build-in Interface "Runnable", so it can be run on a Thread or a Thread-Execution-Facility
* (such as an ExecutorService).
*/
class Forcer implements Runnable {

private static final int LENGTH = 5;

//These will sore the hash to be cracked in both bytes (required for comparison) and String representation
// (required for output)
private final byte[] crackMe;
private final String crackMeString;

//The MessageDigest does the SHA-256 caclulation. Note that this may throw a NoSuchAlgorithmException when there
// is no SHA-256 implementation in the local standard libraries (but that algorithm is mandatory, so this code
// probably will never throw that Excpetion
private final MessageDigest digest = MessageDigest.getInstance("SHA-256");

public Forcer(String crackMe) throws NoSuchAlgorithmException {
this.crackMeString = crackMe;
this.crackMe = DatatypeConverter.parseHexBinary(crackMe);
}

@Override
public void run() {

String match = "";

//all loops use this array for their counters. This is very dirty and should never be done in production!
char[] chars = new char[LENGTH];

//used for short-stopping when a match is found - one could abuse the match-variable for this, but this is
// much clearer
boolean done = false;

for (chars[0] = 'a'; chars[0] <= 'z' && !done; chars[0]++) {
for (chars[1] = 'a'; chars[1] <= 'z' && !done; chars[1]++) {
for (chars[2] = 'a'; chars[2] <= 'z' && !done; chars[2]++) {
for (chars[3] = 'a'; chars[3] <= 'z' && !done; chars[3]++) {
for (chars[4] = 'a'; chars[4] <= 'z' && !done; chars[4]++) {
//the String creation is necessary to get the encoding right
String canidate = new String(chars);
//genenrate SHA-256 hash using Java's standard facilities
byte[] hash = digest.digest(canidate.getBytes());
if (Arrays.equals(hash, crackMe)) {
match = canidate;
done = true;
}

}
}
}
}
}
System.out.println(String.format("Hash %s has the following match : %s", crackMeString, match));
}
}


</syntaxhighlight>
{{out}}<pre>Hash 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b has the following match : apple
Hash 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f has the following match : mmmmm
Hash 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad has the following match : zyzzx</pre>

===Faster Alternative Version===
Combines ideas from the C++ solution and the above Java version. Execution time is about 1.6 seconds on my system (3.2 GHz Quad-Core Intel Core i5, macOS 10.15.3).
<syntaxhighlight lang="java">import javax.xml.bind.DatatypeConverter;
import java.security.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

public class ParallelBruteForce {
public static void main(String[] args) {
try {
String[] hashes = {
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};
ParallelBruteForce pbf = new ParallelBruteForce(5, hashes);
pbf.findPasswords();
} catch (Exception e) {
e.printStackTrace();
}
}

private ParallelBruteForce(int length, String[] hashes) {
this.length = length;
this.hashes = hashes;
digests = new byte[hashes.length][];
for (int i = 0; i < hashes.length; ++i)
digests[i] = DatatypeConverter.parseHexBinary(hashes[i]);
}

private void findPasswords() throws Exception {
count.set(length);
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService svc = Executors.newFixedThreadPool(processors);
List<Future<?>> tasks = new ArrayList<>();
for (int i = 0; i < 26; ++i)
tasks.add(svc.submit(new PasswordFinder((byte)(97 + i))));
for (Future<?> task : tasks)
task.get();
svc.shutdown();
}

private static boolean nextPassword(byte[] passwd, int start) {
int len = passwd.length;
for (int i = len - 1; i >= start; --i) {
if (passwd[i] < 122) {
++passwd[i];
return true;
}
passwd[i] = 97;
}
return false;
}

private class PasswordFinder implements Runnable {
private byte ch;
private MessageDigest md = MessageDigest.getInstance("SHA-256");
private PasswordFinder(byte c) throws NoSuchAlgorithmException {
ch = c;
}
public void run() {
byte[] passwd = new byte[length];
Arrays.fill(passwd, (byte)97);
passwd[0] = ch;
while (count.get() > 0) {
byte[] digest = md.digest(passwd);
for (int m = 0; m < hashes.length; ++m) {
if (Arrays.equals(digest, digests[m])) {
count.decrementAndGet();
System.out.println("password: " + new String(passwd) + ", hash: " + hashes[m]);
break;
}
}
if (!nextPassword(passwd, 1))
break;
}
}
}

private int length;
private String[] hashes;
private byte[][] digests;
private AtomicInteger count = new AtomicInteger();
}</syntaxhighlight>
{{out}}
<pre>
password: apple, hash: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
password: mmmmm, hash: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
password: zyzzx, hash: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>

=={{header|Julia}}==
<syntaxhighlight lang="julia">@everywhere using SHA

@everywhere function bruteForceRange(startSerial, numberToDo)
targets = ["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]
targets = map(hex2bytes, targets)
for count = 1 : numberToDo
password = [UInt8(97 + x) for x in digits(UInt8, startSerial + count, 26, 5)]
hashbytes = sha256(password)
if (hashbytes[1] == 0x11 || hashbytes[1] == 0x3a || hashbytes[1] == 0x74) && findfirst(targets, hashbytes) > 0
hexstring = join(hex(x,2) for x in hashbytes)
passwordstring = join(map(Char, password))
println("$passwordstring --> $hexstring")
end
end
return 0
end

@everywhere perThread = div(26^5, Sys.CPU_CORES)
pmap(x -> bruteForceRange(x * perThread, perThread), 0:Sys.CPU_CORES-1)
</syntaxhighlight>
{{out}}<pre>From worker 2: apple --> 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
From worker 3: zyzzx --> 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
From worker 4: mmmmm --> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f</pre>

=={{header|Kotlin}}==
{{trans|C#}}
<syntaxhighlight lang="scala">// version 1.1.51

import java.security.MessageDigest

fun stringHashToByteHash(hash: String): ByteArray {
val ba = ByteArray(32)
for (i in 0 until 64 step 2) ba[i / 2] = hash.substring(i, i + 2).toInt(16).toByte()
return ba
}

fun ByteArray.matches(other: ByteArray): Boolean {
for (i in 0 until 32) {
if (this[i] != other[i]) return false
}
return true
}

fun main(args: Array<String>) {
val stringHashes = listOf(
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
)
val byteHashes = List(3) { stringHashToByteHash(stringHashes[it]) }
val letters = List(26) { (97 + it).toByte() }

letters.stream().parallel().forEach {
val md = MessageDigest.getInstance("SHA-256")
val range = 97..122
val pwd = ByteArray(5)
pwd[0] = it
for (i1 in range) {
pwd[1] = i1.toByte()
for (i2 in range) {
pwd[2] = i2.toByte()
for (i3 in range) {
pwd[3] = i3.toByte()
for (i4 in range) {
pwd[4] = i4.toByte()
val ba = md.digest(pwd)
for (j in 0..2) {
if (ba.matches(byteHashes[j])) {
val password = pwd.toString(Charsets.US_ASCII)
println("$password => ${stringHashes[j]}")
break
}
}
}
}
}
}
}
}</syntaxhighlight>

{{out}}
<pre>
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>

=={{header|Mathematica}}/{{header|Wolfram Language}}==

<syntaxhighlight lang="mathematica">testPassword[pass_String] :=
If[MemberQ[{16^^1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad,
16^^3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b,
16^^74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f},
Hash[pass, "SHA256"]], Print[pass]];

chars=CharacterRange["a","z"];

ParallelDo[
testPassword[StringJoin[a, b, c, d, e]],
{a, chars}, {b, chars}, {c, chars}, {d, chars}, {e, chars}]</syntaxhighlight>

=={{header|Modula-2}}==
<syntaxhighlight lang="modula2">MODULE PBF;
FROM FormatString IMPORT FormatString;
FROM SHA256 IMPORT SHA256,Create,Destroy,HashBytes,Finalize,GetHash;
FROM SYSTEM IMPORT ADR,ADDRESS,BYTE;
FROM Terminal IMPORT Write,WriteString,WriteLn,ReadChar;
FROM Threads IMPORT Thread,CreateThread,WaitForThreadTermination;

PROCEDURE PrintHexBytes(str : ARRAY OF BYTE; limit : INTEGER);
VAR
buf : ARRAY[0..7] OF CHAR;
i,v : INTEGER;
BEGIN
i := 0;
WHILE i<limit DO
v := ORD(str[i]);
IF v < 16 THEN
WriteString("0")
END;
FormatString("%h", buf, v);
WriteString(buf);
INC(i);
END
END PrintHexBytes;

PROCEDURE Check(str : ARRAY OF CHAR);
TYPE
HA = ARRAY[0..31] OF BYTE;
CONST
h1 = HA{3aH, 7bH, 0d3H, 0e2H, 36H, 0aH, 3dH, 29H, 0eeH, 0a4H, 36H, 0fcH, 0fbH, 7eH, 44H, 0c7H, 35H, 0d1H, 17H, 0c4H, 2dH, 1cH, 18H, 35H, 42H, 0bH, 6bH, 99H, 42H, 0ddH, 4fH, 1bH};
h2 = HA{74H, 0e1H, 0bbH, 62H, 0f8H, 0daH, 0bbH, 81H, 25H, 0a5H, 88H, 52H, 0b6H, 3bH, 0dfH, 6eH, 0aeH, 0f6H, 67H, 0cbH, 56H, 0acH, 7fH, 7cH, 0dbH, 0a6H, 0d7H, 30H, 5cH, 50H, 0a2H, 2fH};
h3 = HA{11H, 15H, 0ddH, 80H, 0fH, 0eaH, 0acH, 0efH, 0dfH, 48H, 1fH, 1fH, 90H, 70H, 37H, 4aH, 2aH, 81H, 0e2H, 78H, 80H, 0f1H, 87H, 39H, 6dH, 0b6H, 79H, 58H, 0b2H, 07H, 0cbH, 0adH};
VAR
hash : SHA256;
out : ARRAY[0..31] OF BYTE;
i : CARDINAL;
match : BOOLEAN;
BEGIN
hash := Create();

HashBytes(hash, ADR(str), HIGH(str)+1);
Finalize(hash);

GetHash(hash, out);
Destroy(hash);

match := TRUE;
FOR i:=0 TO HIGH(out) DO
IF out[i] # h1[i] THEN
match := FALSE;
BREAK
END
END;
IF match THEN
WriteString(str);
WriteString(" ");
PrintHexBytes(out, 32);
WriteLn;
RETURN
END;

match := TRUE;
FOR i:=0 TO HIGH(out) DO
IF out[i] # h2[i] THEN
match := FALSE;
BREAK
END
END;
IF match THEN
WriteString(str);
WriteString(" ");
PrintHexBytes(out, 32);
WriteLn;
RETURN
END;

match := TRUE;
FOR i:=0 TO HIGH(out) DO
IF out[i] # h3[i] THEN
match := FALSE;
BREAK
END
END;
IF match THEN
WriteString(str);
WriteString(" ");
PrintHexBytes(out, 32);
WriteLn
END
END Check;

PROCEDURE CheckWords(a : CHAR);
VAR
word : ARRAY[0..4] OF CHAR;
b,c,d,e : CHAR;
BEGIN
word[0] := a;
FOR b:='a' TO 'z' DO
word[1] := b;
FOR c:='a' TO 'z' DO
word[2] := c;
FOR d:='a' TO 'z' DO
word[3] := d;
FOR e:='a' TO 'z' DO
word[4] := e;
Check(word)
END
END
END
END
END CheckWords;

PROCEDURE CheckAF(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
FOR a:='a' TO 'f' DO
CheckWords(a)
END;
RETURN 0
END CheckAF;

PROCEDURE CheckGM(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
FOR a:='g' TO 'm' DO
CheckWords(a)
END;
RETURN 0
END CheckGM;

PROCEDURE CheckNS(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
FOR a:='n' TO 's' DO
CheckWords(a)
END;
RETURN 0
END CheckNS;

PROCEDURE CheckTZ(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
FOR a:='t' TO 'z' DO
CheckWords(a)
END;
RETURN 0
END CheckTZ;

VAR
t1,t2,t3,t4 : Thread;
s1,s2,s3,s4 : CARDINAL;
BEGIN
CreateThread(t1,CheckAF,NIL,0,TRUE);
CreateThread(t2,CheckGM,NIL,0,TRUE);
CreateThread(t3,CheckNS,NIL,0,TRUE);
CreateThread(t4,CheckTZ,NIL,0,TRUE);

WaitForThreadTermination(t1,-1,s1);
WaitForThreadTermination(t2,-1,s2);
WaitForThreadTermination(t3,-1,s3);
WaitForThreadTermination(t4,-1,s4);

WriteString("Done");
WriteLn;
ReadChar
END PBF.</syntaxhighlight>
{{out}}
<pre>apple 3A7BD3E2360A3D29EEA436FCFB7E44C735D117C42D1C1835420B6B9942DD4F1B
mmmmm 74E1BB62F8DABB8125A58852B63BDF6EAEF667CB56AC7F7CDBA6D7305C50A22F
zyzzx 1115DD800FEAACEFDF481F1F9070374A2A81E27880F187396DB67958B207CBAD
Done</pre>

=={{header|Nim}}==
{{libheader|Nimcrypto}}
Using a thread for each starting character.
Note that the program must be compiled with option --threads:on.
<syntaxhighlight lang="nim">import strutils, threadpool
import nimcrypto

const

# List of hexadecimal representation of target hashes.
HexHashes = ["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]

# List of target hashes.
Hashes = [MDigest[256].fromHex(HexHashes[0]),
MDigest[256].fromHex(HexHashes[1]),
MDigest[256].fromHex(HexHashes[2])]

Letters = 'a'..'z'


proc findHashes(a: char) =
## Build the arrays of five characters starting with the value
## of "a" and check if their hash matches one of the targets.
## Print the string and the hash value if a match is found.
for b in Letters:
for c in Letters:
for d in Letters:
for e in Letters:
let s = [a, b, c, d, e]
let h = sha256.digest(s)
for i, target in Hashes:
if h == target: # Match.
echo s.join(), " → ", HexHashes[i]


# Launch a thread for each starting character.
for a in Letters:
spawn findHashes(a)

sync()</syntaxhighlight>

{{out}}
<pre>apple → 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm → 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx → 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>

=={{header|Perl}}==
Uses threads library to do naive search using 26 threads ("aaaaa" .. "azzzz", "baaaa" .. "bzzzz", etc.). No effort is made to early exit.
<syntaxhighlight lang="perl">use Digest::SHA qw/sha256_hex/;
use threads;
use threads::shared;
my @results :shared;

print "$_ : ",join(" ",search($_)), "\n" for (qw/
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
/);


sub search {
my $hash = shift;
@results = ();
$_->join() for map { threads->create('tsearch', $_, $hash) } 0..25;
return @results;
}

sub tsearch {
my($tnum, $hash) = @_;
my $s = chr(ord("a")+$tnum) . "aaaa";

for (1..456976) { # 26^4
push @results, $s if sha256_hex($s) eq $hash;
$s++;
}
}</syntaxhighlight>
{{out}}
<pre>
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad : zyzzx
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b : apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f : mmmmm
</pre>

=={{header|Phix}}==
Each thread processes one start letter at a time, until they are all done.
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">sha256</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">VM</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pThreadN</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- (shd not be rqd on 0.8.1+)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">asHex</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%02X"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">starts</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">start_cs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">(),</span> <span style="color: #000080;font-style:italic;">-- critical section</span>
<span style="color: #000000;">hashes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #008000;">"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">x</span><span style="color: #008000;">"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">x</span><span style="color: #008000;">"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">find_passwords</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">thrashes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- thread-safe copy of hashes</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">start_cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hashes</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">thrashes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">thrashes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">thread_safe_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hashes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">start_cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">pwd</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">start_cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">starts</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">start_cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">pwd</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">starts</span><span style="color: #0000FF;">[$]&</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">starts</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">starts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">start_cs</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pwd</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">hash</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sha256</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pwd</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hash</span><span style="color: #0000FF;">,</span><span style="color: #000000;">thrashes</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?{</span><span style="color: #000000;">pwd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">asHex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hash</span><span style="color: #0000FF;">)}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pwd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'z'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">pwd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">pwd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'a'</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #000000;">pwd</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">exit_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">nthreads</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">starts</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'z'</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">threads</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nthreads</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">threads</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">,</span><span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"find_passwords"</span><span style="color: #0000FF;">),{}))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"completed with %d threads in %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">nthreads</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}} (with nthreads loop from 1 to 4, and for that case CPU use in Task Manager shows a very clear step pattern.)
<pre>
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 1 threads in 29.1s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 2 threads in 16.1s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 3 threads in 13.8s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 4 threads in 12.7s
</pre>

=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">UseSHA2Fingerprint()

NewList sha256fp.s()
AddElement(sha256fp()) : sha256fp() = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
AddElement(sha256fp()) : sha256fp() = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
AddElement(sha256fp()) : sha256fp() = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
Procedure PrintCode(n.i)
Shared sha256fp()
SelectElement(sha256fp(), n) : fp$ = sha256fp()
For c1 = 'a' To 'z'
For c2 = 'a' To 'z'
For c3 = 'a' To 'z'
For c4 = 'a' To 'z'
For c5 = 'a' To 'z'
If fp$ = StringFingerprint(Chr(c1) + Chr(c2) + Chr(c3) + Chr(c4) + Chr(c5), #PB_Cipher_SHA2, 256); maybe set enconding
PrintN(Chr(c1) + Chr(c2) + Chr(c3) + Chr(c4) + Chr(c5) + " => " + fp$)
Break(5)
EndIf
Next c5
Next c4
Next c3
Next c2
Next c1
EndProcedure

Dim mythread(ListSize(sha256fp()))

If OpenConsole("")
StartTime.q = ElapsedMilliseconds()
For i=0 To ListSize(sha256fp()) - 1
mythread(i)=CreateThread(@PrintCode(), i)
Next
For i=0 To ListSize(sha256fp()) - 1
WaitThread(mythread(i))
Next

PrintN("-----------")
PrintN(Str(ElapsedMilliseconds() - StartTime)+" Milliseconds needed")
Input()
EndIf
End
; EnableThread</syntaxhighlight>
{{out}}
<pre>apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
-----------
36955 Milliseconds needed</pre>

=={{header|Python}}==

<syntaxhighlight lang="python">import multiprocessing
from hashlib import sha256

h1 = bytes().fromhex("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
h2 = bytes().fromhex("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
h3 = bytes().fromhex("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")

def brute(firstletterascii: int):
global h1, h2, h3
letters = bytearray(5)
letters[0] = firstletterascii
for letters[1] in range(97, 97 + 26):
for letters[2] in range(97, 97 + 26):
for letters[3] in range(97, 97 + 26):
for letters[4] in range(97, 97 + 26):
digest = sha256(letters).digest()
if digest == h1 or digest == h2 or digest == h3:
password = "".join(chr(x) for x in letters)
print(password + " => " + digest.hex())
return 0

def main():
with multiprocessing.Pool() as p:
p.map(brute, range(97, 97 + 26))

if __name__ == "__main__":
main()</syntaxhighlight>


{{out}}
{{out}}
Line 72: Line 1,891:
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>

=={{header|Racket}}==

Tests are included firstly to check it works, but they also provide an opportunity to time
the single threaded version.

<syntaxhighlight lang="racket">#lang racket/base
(require racket/place
racket/list
racket/match
;; requires sha package. install it in DrRacket's "File/Install Package..."
;; or with raco:
;; % raco pkg install sha
sha
(only-in openssl/sha1 hex-string->bytes))

(define (brute css targs)
(define (sub-work i) (let ((cs (list-ref css i))) (in-range (car cs) (cdr cs))))
(define-values (as bs cs ds es) (apply values (map sub-work (range 5))))
(define s (make-bytes 5))
(for*/list ((a as) #:when (bytes-set! s 0 a)
(b bs) #:when (bytes-set! s 1 b)
(c cs) #:when (bytes-set! s 2 c)
(d ds) #:when (bytes-set! s 3 d)
(e es) #:when (bytes-set! s 4 e)
(h (in-value (sha256 s)))
(t (in-list targs))
#:when (bytes=? t h))
(eprintf "found ~s -> ~s~%" t s)
(cons (bytes-copy s) t)))

;; ---------------------------------------------------------------------------------------------------
(unless (place-enabled?) (error "We're using places... they're not enabled!"))

(define target-list
(map hex-string->bytes
(list "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")))

(define (run-place/assign-task sub-task)
(define there (place here
(match-define (cons work targs) (place-channel-get here))
(place-channel-put here (brute work targs))))
(place-channel-put there (cons sub-task target-list))
there)

(define (task->subtasks css n-tasks)
(match css
[(list (and initial-range (cons A Z+)) common-tail ...)
(define step (quotient (+ n-tasks (- Z+ A)) n-tasks))
(for/list ((a (in-range A Z+ step)))
;; replace the head with a sub-task head
(cons (cons a (min (+ a step) Z+)) common-tail))]))

(define readable-pair (match-lambda [(cons x (app bytes->hex-string s)) (cons x s)]))

(define (parallel-brute css (n-tasks (processor-count)))
(define the-places (map run-place/assign-task (task->subtasks css n-tasks)))
(define collected-results (append* (map place-channel-get the-places)))
(map readable-pair collected-results))

(define 5-char-lowercase-work
(make-list 5 (cons (char->integer #\a) (add1 (char->integer #\z)))))

;; ---------------------------------------------------------------------------------------------------
(module+ main
(time (parallel-brute 5-char-lowercase-work)))

;; ---------------------------------------------------------------------------------------------------
(module+ test
(require rackunit)
(check-equal?
(bytes->hex-string (sha256 #"mmmmm"))
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
"SHA-256 works as expected")

(check-equal?
(hex-string->bytes "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
#"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/"
"This is the raw value we'll be hashing to")
(define m-idx (char->integer #\m))
(define m-idx+ (add1 m-idx))
(check-equal?
(brute (make-list 5 (cons m-idx m-idx+)) target-list)
(list
(cons
#"mmmmm"
#"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/")))

;; Brute works without parallelism
;; check when you have the time... it takes a minute (literally)
(check-equal?
(time
(brute 5-char-lowercase-work target-list))
'((#"apple"
. #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e")
(#"mmmmm"
.
#"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/")
(#"zyzzx"
.
#"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255"))
"without parallelism, it works"))</syntaxhighlight>

{{out}}

Test phase of run:
<pre>found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
found #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e" -> #"apple"
found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
found #"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255" -> #"zyzzx"
cpu time: 19593 real time: 19581 gc time: 2247
</pre>

Main phase of run:
<pre>found #"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255" -> #"zyzzx"
found #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e" -> #"apple"
found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
cpu time: 30641 real time: 4681 gc time: 0
'((#"apple" . "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
(#"mmmmm" . "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
(#"zyzzx" . "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"))</pre>

=={{header|Raku}}==
(formerly Perl 6)
This solution can be changed from parallel to serial by removing the <code>.race</code> method.
<syntaxhighlight lang="raku" line>use Digest::SHA256::Native;
constant @alpha2 = [X~] <a m p y z> xx 2;
constant @alpha3 = [X~] <e l m p x z> xx 3;

my %WANTED = set <
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
>;

sub find_it ( $first_two ) {
for $first_two «~« @alpha3 -> \password {
my \digest_hex = sha256-hex(password);
return "{password} => {digest_hex}" if %WANTED{digest_hex}
}
()
}

.say for flat @alpha2.race(:1batch).map: { find_it($_) };</syntaxhighlight>
{{Out}}
<pre>apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>

Testers can adjust the run speed by replacing the @alpha constants with one of the below:
<syntaxhighlight lang="raku" line>
# True to actual RC task, but slowest
constant @alpha2 = 'aa' .. 'zz';
constant @alpha3 = 'aaa' .. 'zzz';

# Reduced alphabets for speed during development & testing
constant @alpha2 = [X~] <a m p y z> xx 2;
constant @alpha3 = [X~] <e l m p x z> xx 3;
</syntaxhighlight>

=={{header|Rust}}==

In this solution the number of threads is the number of logical processors on the machine. `distribute_work()` distributes the work more or less equally between the threads.

<syntaxhighlight lang="rust">// [dependencies]
// rust-crypto = "0.2.36"
// num_cpus = "1.7.0"
// hex = "0.2.0"

extern crate crypto;
extern crate num_cpus;
extern crate hex;

use std::thread;
use std::cmp::min;
use crypto::sha2::Sha256;
use crypto::digest::Digest;
use hex::{FromHex, ToHex};

fn main() {
let hashes = vec![
decode("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"),
decode("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"),
decode("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"),
];

let mut threads = Vec::new();
let mut ranges = distribute_work();

while let Some(range) = ranges.pop() {
let hashes = hashes.clone();
threads.push(thread::spawn(
move || search(range.0, range.1, hashes.clone()),
));
}

while let Some(t) = threads.pop() {
t.join().ok();
}
}

fn search(from: [u8; 5], to: [u8; 5], hashes: Vec<[u8; 256 / 8]>) {

let mut password = from.clone();

while password <= to {
let mut sha256 = Sha256::new();
sha256.input(&password);
let mut result = [0u8; 256 / 8];
sha256.result(&mut result);

for hash in hashes.iter() {
if *hash == result {
println!(
"{}{}{}{}{} {}",
password[0] as char,
password[1] as char,
password[2] as char,
password[3] as char,
password[4] as char,
hash.to_hex()
);
}
}

password = next(&password);
}

}

fn next(password: &[u8; 5]) -> [u8; 5] {
let mut result = password.clone();
for i in (0..result.len()).rev() {
if result[i] == b'z' {
if i == 0 {
result[i] = b'z' + 1;
} else {
result[i] = b'a';
}
} else {
result[i] += 1;
break;
}
}
result.clone()
}

fn distribute_work() -> Vec<([u8; 5], [u8; 5])> {
let mut ranges = Vec::new();
let num_cpus = min(num_cpus::get(), 26) as u8;

let div = 25 / num_cpus;
let mut remainder = 25 % num_cpus;
let mut from = b'a';
while from < b'z' {

let to = from + div +
if remainder > 0 {
remainder -= 1;
1
} else {
0
};

ranges.push((
[from, from, from, from, from + 1].clone(),
[to, to, to, to, to].clone(),
));

from = to;
}
ranges[0].0[4] = b'a';

ranges.clone()
}

fn decode(string: &str) -> [u8; 256 / 8] {
let mut result = [0; 256 / 8];
let vec = Vec::from_hex(string).unwrap();
for i in 0..result.len() {
result[i] = vec[i];
}
result.clone()
}</syntaxhighlight>

{{out}}

<pre>
apple 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
mmmmm 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
</pre>

=={{header|Scala}}==

Scala has an excellent implementation of parallel collections, which allow you to take advantage of parallel processing with only minor modifications to your code.

This example converts the collection of candidate strings into a ParVector as soon as possible, speeding up both the final step to generating the candidates and the search.

<syntaxhighlight lang="scala">import java.security.MessageDigest

import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
def main(args: Array[String]): Unit = {
val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
val charSet = ('a' to 'z').toVector
val num = 5
for(tmp <- List(hash1, hash2, hash3)){
println(tmp)
crack(tmp, charSet, num) match{
case Some(s) => println(s"String: $s\n")
case None => println("Failed\n")
}
}
}
def crack(hash: String, charSet: Vector[Char], num: Int): Option[String] = {
val perms = charSet
.flatMap(c => Vector.fill(num)(c)).combinations(num) //Generate distinct sets of letters
.to(ParVector) //Convert to ParVector
.flatMap(_.permutations.map(_.mkString)) //Finish generating candidates
perms.find(str => getHash(str).equalsIgnoreCase(hash)) //Search for a matching string
}
def getHash(str: String): String = {
val digester = MessageDigest.getInstance("SHA-256")
digester.digest(str.getBytes("UTF-8")).map("%02x".format(_)).mkString
}
}</syntaxhighlight>

An unfortunate side-effect of jumping straight into a ParVector, though, is that the entire list of candidate strings must be computed before attempting to find a match. This means that even modestly large charsets and/or strings can make the memory usage and runtime blow up.

To solve that issue, this next example implements lazy lists. A lazy list is evaluated as needed, meaning you can generate the list of candidates as you check them. In order to still take advantage of parallel processing, this code takes fixed-size chunks off the front of the LazyList and converts them to ParVectors, repeating until either a match is found or the LazyList is empty.

Notice that def is used in place of val when working with the list of candidates. This is because val holds onto the head, which means it would fill up memory over time with the backlog of candidates already checked. Using def lets the program discard candidates after they are checked.

<syntaxhighlight lang="scala">import java.security.MessageDigest

import scala.annotation.tailrec
import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
def main(args: Array[String]): Unit = {
val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
val charSet = ('a' to 'z').toVector
val len = 5
val num = 1000000
for(tmp <- List(hash1, hash2, hash3)){
println(tmp)
crackLazy(tmp, charSet, len, num) match{
case Some(s) => println(s"String: $s\n")
case None => println("Failed\n")
}
}
}
def crackLazy(hash: String, charSet: Vector[Char], len: Int, num: Int): Option[String] = {
@tailrec
def getMatch(lst: LazyList[String]): Option[String] = {
def hit = lst.take(num).to(ParVector).find(str => getHash(str).equalsIgnoreCase(hash))
def nxt = lst.drop(num)
hit match{
case Some(str) => Some(str)
case None if nxt.nonEmpty => getMatch(nxt)
case None => None
}
}
def perms = charSet
.flatMap(Vector.fill(len)(_))
.combinations(len)
.flatMap(_.permutations.map(_.mkString)).to(LazyList)
getMatch(perms)
}
def getHash(str: String): String = {
val digester = MessageDigest.getInstance("SHA-256")
digester.digest(str.getBytes("UTF-8")).map("%02x".format(_)).mkString
}
}</syntaxhighlight>

As a final example, we can clean this code up with some method chaining and currying to get this:

<syntaxhighlight lang="scala">import java.security.MessageDigest

import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
def main(args: Array[String]): Unit = {
val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
val cracker: String => Option[String] = crackLazy('a' to 'z', 5, 1000000)
for(tmp <- Seq(hash2, hash1, hash3)){
println(s"$tmp")
cracker(tmp) match{
case Some(s) => println(s"String: $s\n")
case None => println("Failed\n")
}
}
}
def getHash(str: String): String = MessageDigest
.getInstance("SHA-256")
.digest(str.getBytes("UTF-8"))
.map("%02x".format(_)).mkString
def crackLazy(charSet: Seq[Char], len: Int, num: Int)(hash: String): Option[String] = charSet
.flatMap(Vector.fill(len)(_)) //Duplicate characters so they can be used any number of times
.combinations(len) //Generate distinct sets of characters
.flatMap(_.permutations.map(_.mkString)) //Generate all permutations for each character set
.grouped(num) //Partition into bite-size chunks
.map(_.to(ParVector).find(str => getHash(str) == hash)) //Convert each chunk into a ParVector and search it
.collectFirst{case Some(res) => res} //Get the first hit if one is found
}</syntaxhighlight>

{{out}}
<pre>
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
String: zyzzx

3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
String: apple

74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
String: mmmmm
</pre>

=={{header|Sidef}}==
{{trans|Perl}}
<syntaxhighlight lang="ruby">func invert_sha256(hash) {

var letters = @('a'..'z')

var job = func (prefix, hash) {
variations_with_repetition(letters, 4, {|*a|
var s = join('', prefix, a...)
return s if (s.sha256 == hash)
})
return nil
}

letters.map {|prefix|
job.ffork(prefix, hash)
}.each {|f|
with (f.wait) { return _ }
}
}

var tests = %w(
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
)

tests.each {|t|
var phrase = invert_sha256(t)
say "#{t} : #{phrase}"
}</syntaxhighlight>
{{out}}
<pre>
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad : zyzzx
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b : apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f : mmmmm
</pre>

=={{header|Swift}}==
<syntaxhighlight lang="swift">import Foundation
import CryptoKit

extension String {
func hexdata() -> Data {
Data(stride(from: 0, to: count, by: 2).map {
let a = index(startIndex, offsetBy: $0)
let b = index(after: a)
return UInt8(self[a ... b], radix: 16)!
})
}
}

DispatchQueue.concurrentPerform(iterations: 26) { (a) in
let goal1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad".hexdata()
let goal2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b".hexdata()
let goal3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f".hexdata()
var letters: [UInt8] = [(UInt8)(a + 97), 0, 0, 0, 0]
for b: UInt8 in 97...122 {
letters[1] = b
for c: UInt8 in 97...122 {
letters[2] = c
for d: UInt8 in 97...122 {
letters[3] = d
for e: UInt8 in 97...122 {
letters[4] = e
let digest = SHA256.hash(data: letters)
if digest == goal1 || digest == goal2 || digest == goal3 {
let password = String(bytes: letters, encoding: .ascii)!
let hexhash = digest.map { String(format: "%02x", $0) }.joined()
print("\(password) => \(hexhash)")
}
}
}
}
}
}</syntaxhighlight>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Text

Module Module1

Function Matches(a As Byte(), b As Byte()) As Boolean
For i = 0 To 31
If a(i) <> b(i) Then
Return False
End If
Next
Return True
End Function

Function StringHashToByteArray(s As String) As Byte()
Return Enumerable.Range(0, s.Length / 2).Select(Function(i) CType(Convert.ToInt16(s.Substring(i * 2, 2), 16), Byte)).ToArray
End Function

Sub Main()
Dim h1 = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
Dim h2 = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
Dim h3 = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")

Parallel.For(0, 26, Sub(a As Integer)
Dim sha = Security.Cryptography.SHA256.Create()
Dim password(4) As Byte
Dim hash As Byte()

password(0) = 97 + a

password(1) = 97
While password(1) < 123
password(2) = 97
While password(2) < 123
password(3) = 97
While password(3) < 123
password(4) = 97
While password(4) < 123
hash = sha.ComputeHash(password)
If Matches(h1, hash) OrElse Matches(h2, hash) OrElse Matches(h3, hash) Then
Console.WriteLine(Encoding.ASCII.GetString(password) + " => " + BitConverter.ToString(hash).ToLower().Replace("-", ""))
End If
password(4) += 1
End While
password(3) += 1
End While
password(2) += 1
End While
password(1) += 1
End While
End Sub)
End Sub

End Module</syntaxhighlight>
{{out}}
<pre>mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad</pre>

=={{header|Wren}}==
{{libheader|Wren-crypto}}
{{libheader|Wren-fmt}}
Wren supports concurrency by way of co-operatively scheduled fibers and, as required by the task description, the work has been divided up between 26 fibers with each fiber taking a different initial letter.

However, from an execution speed viewpoint, there is no point in doing so because Wren's VM is single threaded and can only run one fiber at a time. As it takes around 50 seconds on my machine to process a single initial letter (456,976 calls to sha256) this means that an overall runtime of about 22 minutes is needed to find the passwords corresponding to the 3 hashes.

Currently, parallel calculations are impossible in Wren-cli. However, if Wren is being embedded, it might be possible for a suitable host to run several Wren VM's in parallel and divide a task up between them to improve execution time.
<syntaxhighlight lang="wren">import "./crypto" for Sha256

var hashes = [
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
]

var findHash = Fn.new { |i|
var bytes = List.filled(5, 0)
var r = 97..122
bytes[0] = i
for (j in r) {
bytes[1] = j
for (k in r) {
bytes[2] = k
for (l in r) {
bytes[3] = l
for (m in r) {
bytes[4] = m
var d = Sha256.digest(bytes)
for (hash in hashes) {
if (hash == d) {
var s = bytes.map { |b| String.fromByte(b) }.join()
System.print("%(s) => %(d)")
hashes.remove(hash)
if (hashes.count == 0) return
}
}
}
}
}
}
}

for (i in 0..25) {
var fib = Fiber.new(findHash)
fib.call(97+i)
}</syntaxhighlight>

{{out}}
<pre>
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
</pre>


=={{header|zkl}}==
=={{header|zkl}}==
The built in thread message passing object uses the OS to do the heavy
<lang zkl></lang>
lifting and, as a result, isn't suited to high through put (ie passing
<lang zkl></lang>
passwords to cracking threads, equally distributing passwords to each
cracking thread). Instead, each thread gets a range of passwords to
crack and use signals to coordinate. Way more code with the drawback
that one thread may have to do all the work.

This was run on a Intel i7 4 core 8 thread Linux box.

Uses the message hashing extension library (DLL).
{{trans|==C sharp|C#}}
<syntaxhighlight lang="zkl">var [const] MsgHash=Import.lib("zklMsgHash");
var [const] gotEm=Atomic.Int(); // global signal for all threads

const THREADS=9, // how we will split task, THREADS<=26
CHR_a="a".toAsc();

fcn crack(c,n,hashes){ // thread
sha256:=MsgHash.SHA256; // the SHA-256 hash method, byte bucket
bytes,hash := Data(),Data().howza(0); // byte buckets to reduce garbage production
firstLtrs:=(c+CHR_a).walker(n);
ltrs:=CHR_a.walker; // iterator starting at 97/"a"
foreach a,b,c,d,e in (firstLtrs,ltrs(26),ltrs(26),ltrs(26),ltrs(26)){
if(not hashes2go) return(); // all cracked, stop, not really needed
bytes.clear(a,b,c,d,e); // recycle Data, faster than creating Strings
sha256(bytes,1,hash); // put hash in hash
if(hashes.holds(hash)){
println(bytes.text," --> ",hash.pump(String,"%02x".fmt));
hashes2go.dec(); // I cracked one, let mom thread know
}
}
}</syntaxhighlight>
<syntaxhighlight lang="zkl">hashes:=T("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f",
"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
// convert hex strings to binary; cuts down conversions during crack
fcn hex2binary(s){ s.pump(Data,Void.Read,fcn(a,b){ (a+b).toInt(16) }) }
hashes:=hashes.apply(hex2binary);

hashes2go.set(hashes.len()); // number of codes to crack
num,xtra := 26/THREADS, 26%THREADS; // try for the most even spread over threads
s:=0; do(THREADS){ // start threads
n:=num + ((xtra-=1)>=0);
crack.launch(s.toInt(),n,hashes);
s+=n;
}
hashes2go.waitFor(0); // wait until all cracked, just exit, OS kills threads</syntaxhighlight>
<pre>
<pre>
mmmmm --> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple --> 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx --> 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

real 0m3.261s
user 0m22.160s
sys 0m0.140s
</pre>
</pre>

Latest revision as of 05:34, 2 May 2024

Task
Parallel brute force
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Find, through brute force, the five-letter passwords corresponding with the following SHA-256 hashes:

1. 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
2. 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
3. 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f

Your program should naively iterate through all possible passwords consisting only of five lower-case ASCII English letters. It should use concurrent or parallel processing, if your language supports that feature. You may calculate SHA-256 hashes by calling a library or through a custom implementation. Print each matching password, along with its SHA-256 hash.

Related task: SHA-256

Ada

Library: CryptAda
with Ada.Text_IO;

with CryptAda.Digests.Message_Digests.SHA_256;
with CryptAda.Digests.Hashes;
with CryptAda.Pragmatics;

procedure Brute_Force is
   use CryptAda.Digests.Message_Digests;
   use CryptAda.Digests.Hashes;
   use CryptAda.Digests;
   use CryptAda.Pragmatics;

   Wanted_Sums : constant array (1 .. 3) of String (1 .. 64) :=
     (1 => "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
      2 => "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
      3 => "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
   Wanted_Hash : constant array (1 .. 3) of Hashes.Hash :=
     (1 => Hashes.To_Hash (Wanted_Sums (1)),
      2 => Hashes.To_Hash (Wanted_Sums (2)),
      3 => Hashes.To_Hash (Wanted_Sums (3)));

   subtype Ciffer is Byte range Character'Pos ('a') .. Character'Pos ('z');
   subtype Code   is Byte_Array (1 .. 5);

   task type Worker (First : Byte) is
   end Worker;

   procedure Compare (Hash : in Hashes.Hash; Bytes : in Code) is
   begin
      for I in Wanted_Hash'Range loop
         if Hash = Wanted_Hash (I) then
            Ada.Text_IO.Put (Wanted_Sums (I) & "  ");
            for C of Bytes loop
               Ada.Text_IO.Put (Character'Val (C));
            end loop;
            Ada.Text_IO.New_Line;
         end if;
      end loop;
   end Compare;

   task body Worker is
      Handle : constant Message_Digest_Handle := SHA_256.Get_Message_Digest_Handle;
      Digest : constant Message_Digest_Ptr    := Get_Message_Digest_Ptr (Handle);
      Bytes  : Code;
      Hash   : Hashes.Hash;
   begin
      Bytes (Bytes'First) := First;

      for B2 in Ciffer'Range loop
         for B3 in Ciffer'Range loop
            for B4 in Ciffer'Range loop
               Bytes (2 .. 4) := B2 & B3 & B4;
               for B5 in Ciffer'Range loop
                  Bytes (5) := B5;
                  Digest_Start  (Digest);
                  Digest_Update (Digest, Bytes);
                  Digest_End    (Digest, Hash);
                  Compare (Hash, Bytes);
               end loop;
            end loop;
         end loop;
      end loop;
   end Worker;

   type Worker_Access is access Worker;
   Work : Worker_Access;
   pragma Unreferenced (Work);
begin
   for C in Ciffer'Range loop
      Work := new Worker (First => C);
   end loop;
end Brute_Force;

BaCon

PRAGMA INCLUDE <openssl/sha.h>
PRAGMA LDFLAGS -lcrypto

OPTION MEMTYPE unsigned char

LOCAL buffer[32], passwd[5] TYPE unsigned char
LOCAL result TYPE unsigned char*
LOCAL a,b,c,d,e TYPE NUMBER

DATA "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b", "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f", "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"

WHILE TRUE

    READ secret$
    IF NOT(LEN(secret$)) THEN BREAK

    FOR i = 0 TO 31
        buffer[i] = DEC(MID$(secret$, i*2+1, 2))
    NEXT

    FOR a = 97 TO 122
        FOR b = 97 TO 122
            FOR c = 97 TO 122
                FOR d = 97 TO 122
                    FOR e = 97 TO 122
                        passwd[0] = a
                        passwd[1] = b
                        passwd[2] = c
                        passwd[3] = d
                        passwd[4] = e

                        result = SHA256(passwd, 5, 0)

                        FOR i = 0 TO SHA256_DIGEST_LENGTH-1
                            IF PEEK(result+i) != buffer[i] THEN BREAK
                        NEXT
                        IF i = SHA256_DIGEST_LENGTH THEN
                            PRINT a,b,c,d,e,secret$ FORMAT "%c%c%c%c%c:%s\n"
                            BREAK 5
                        END IF
                    NEXT
                NEXT
            NEXT
        NEXT
    NEXT
WEND
Output:
apple:3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm:74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx:1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

C

Translation of: C#
// $ gcc -o parabrutfor parabrutfor.c -fopenmp -lssl -lcrypto
// $ export OMP_NUM_THREADS=4
// $ ./parabrutfor

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include <openssl/sha.h>

typedef unsigned char byte;

int matches(byte *a, byte* b) {
	for (int i = 0; i < 32; i++)
		if (a[i] != b[i])
			return 0;
	return 1;
}


byte* StringHashToByteArray(const char* s) {
	byte* hash = (byte*) malloc(32);
	char two[3];
	two[2] = 0;
	for (int i = 0; i < 32; i++) {
		two[0] = s[i * 2];
		two[1] = s[i * 2 + 1];
		hash[i] = (byte)strtol(two, 0, 16);
	}
	return hash;
}

void printResult(byte* password, byte* hash) {
	char sPass[6];
	memcpy(sPass, password, 5);
	sPass[5] = 0;
	printf("%s => ", sPass);
	for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
		printf("%02x", hash[i]);
	printf("\n");
}

int main(int argc, char **argv)
{

#pragma omp parallel
	{

#pragma omp for
		for (int a = 0; a < 26; a++)
		{
			byte password[5] = { 97 + a };
			byte* one =   StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
			byte* two =   StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b");
			byte* three = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
			for (password[1] = 97; password[1] < 123; password[1]++)
				for (password[2] = 97; password[2] < 123; password[2]++)
					for (password[3] = 97; password[3] < 123; password[3]++)
						for (password[4] = 97; password[4] < 123; password[4]++) {
							byte *hash = SHA256(password, 5, 0);
							if (matches(one, hash) || matches(two, hash) || matches(three, hash))
								printResult(password, hash);
						}
			free(one);
			free(two);
			free(three);
		}
	}

	return 0;
}
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

C#

 

using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Parallel.For(0, 26, a => {
            byte[] password = new byte[5];
            byte[] hash;
            byte[] one = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
            byte[] two = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b");
            byte[] three = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f");
            password[0] = (byte)(97 + a);
            var sha = System.Security.Cryptography.SHA256.Create();
            for (password[1] = 97; password[1] < 123; password[1]++)
                for (password[2] = 97; password[2] < 123; password[2]++)
                    for (password[3] = 97; password[3] < 123; password[3]++)
                        for (password[4] = 97; password[4] < 123; password[4]++)
                        {
                            hash = sha.ComputeHash(password);
                            if (matches(one, hash) || matches(two, hash) || matches(three, hash))
                                Console.WriteLine(Encoding.ASCII.GetString(password) + " => "
                                    + BitConverter.ToString(hash).ToLower().Replace("-", ""));
                        }
        });
    }
    static byte[] StringHashToByteArray(string s)
    {
        return Enumerable.Range(0, s.Length / 2).Select(i => (byte)Convert.ToInt16(s.Substring(i * 2, 2), 16)).ToArray();
    }
    static bool matches(byte[] a, byte[] b)
    {
        for (int i = 0; i < 32; i++)
            if (a[i] != b[i])
                return false;
        return true;
    }
}
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

C++

Library: OpenSSL
#include <atomic>
#include <cstdio>
#include <cstring>
#include <future>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <openssl/sha.h>

struct sha256 {
    unsigned char digest[SHA256_DIGEST_LENGTH];
    void compute(const char* str, int len) {
        SHA256((const unsigned char*)str, len, digest);
    }
    bool parse(const std::string& hash) {
        if (hash.length() != 2 * SHA256_DIGEST_LENGTH) {
            std::cerr << "Invalid SHA-256 hash\n";
            return false;
        }
        const char* p = hash.c_str();
        for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i, p += 2) {
            unsigned int x;
            if (sscanf(p, "%2x", &x) != 1) {
                std::cerr << "Cannot parse SHA-256 hash\n";
                return false;
            }
            digest[i] = x;
        }
        return true;
    }
};

bool operator==(const sha256& a, const sha256& b) {
    return memcmp(a.digest, b.digest, SHA256_DIGEST_LENGTH) == 0;
}

bool next_password(std::string& passwd, size_t start) {
    size_t len = passwd.length();
    for (size_t i = len - 1; i >= start; --i) {
        char c = passwd[i];
        if (c < 'z') {
            ++passwd[i];
            return true;
        }
        passwd[i] = 'a';
    }
    return false;
}

class password_finder {
public:
    password_finder(int);
    void find_passwords(const std::vector<std::string>&);

private:
    int length;
    void find_passwords(char);
    std::vector<std::string> hashes;
    std::vector<sha256> digests;
    std::atomic<size_t> count;
};

password_finder::password_finder(int len) : length(len) {}

void password_finder::find_passwords(char ch) {
    std::string passwd(length, 'a');
    passwd[0] = ch;
    sha256 digest;
    while (count > 0) {
        digest.compute(passwd.c_str(), length);
        for (int m = 0; m < hashes.size(); ++m) {
            if (digest == digests[m]) {
                --count;
                std::ostringstream out;
                out << "password: " << passwd << ", hash: " << hashes[m]
                    << '\n';
                std::cout << out.str();
                break;
            }
        }
        if (!next_password(passwd, 1))
            break;
    }
}

void password_finder::find_passwords(const std::vector<std::string>& h) {
    hashes = h;
    digests.resize(hashes.size());
    for (int i = 0; i < hashes.size(); ++i) {
        if (!digests[i].parse(hashes[i]))
            return;
    }
    count = hashes.size();
    std::vector<std::future<void>> futures;
    const int n = 26;
    for (int i = 0; i < n; ++i) {
        char c = 'a' + i;
        futures.push_back(
            std::async(std::launch::async, [this, c]() { find_passwords(c); }));
    }
}

int main() {
    std::vector<std::string> hashes{
        "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
        "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
        "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};
    password_finder pf(5);
    pf.find_passwords(hashes);
    return 0;
}
Output:

Execution time is about 0.7 seconds on my system (3.2 GHz Quad-Core Intel Core i5, macOS 10.15.3).

password: mmmmm, hash: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
password: apple, hash: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
password: zyzzx, hash: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Clojure

(ns rosetta.brute-force
  (:require [clojure.math.combinatorics :refer [selections]]) ;; https://github.com/clojure/math.combinatorics
  (:import  [java.util Arrays]
            [java.security MessageDigest]))

;;https://rosettacode.org/wiki/Parallel_Brute_Force

(def targets ;; length = 5
  ["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
   "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
   "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"])

;; HELPER/UTIL fns
;;=================

(defn digest
  "Given a byte-array <bs> returns its hash (also a byte-array)."
  ^bytes [^MessageDigest md ^bytes bs]
  (.digest md bs))

(defn char-range
  "Helper fn for easily producing character ranges."
  [start end]
  (map char (range (int start)
                   (inc (int end)))))

(def low-case-eng-bytes
  "Our search-space (all lower case english characters converted to bytes)."
  (map byte (char-range \a \z)))

(defn hex->bytes
  "Converts a hex string to a byte-array."
  ^bytes [^String hex]
  (let [len (.length hex)
        ret (byte-array (/ len 2))]
    (run! (fn [i]
            (aset ret
                  (/ i 2)
                  ^byte (unchecked-add-int
                          (bit-shift-left
                            (Character/digit (.charAt hex i) 16)
                            4)
                          (Character/digit (.charAt hex (inc i)) 16))))
          (range 0 len 2))
    ret))

(defn bytes->hex
  "Converts a byte-array to a hex string."
  [^bytes bs]
  (.toString
    ^StringBuilder
    (areduce bs idx ret (StringBuilder.)
      (doto ret (.append (format "%02x" (aget bs idx)))))))

;; MAIN LOGIC
;;===========

(defn check-candidate
  "Checks whether the SHA256 hash of <candidate> (a list of 5 bytes),
   matches <target>. If it does, returns that hash as a hex-encoded String.
   Otherwise returns nil."
  [^bytes target sha256 candidate]
  (let [candidate-bytes (byte-array candidate)
        ^bytes candidate-hash (sha256 candidate-bytes)]
    (when (Arrays/equals target candidate-hash)
      (let [answer (String. candidate-bytes)]
        (println "Answer found for:" (bytes->hex candidate-hash) "=>" answer)
        answer))))

(defn sha256-brute-force
  "Top level function. Returns a list with the 3 answers."
  [space hex-hashes]
  (->> hex-hashes
       (map hex->bytes) ;; convert the hex strings to bytes
       (pmap            ;; parallel map the checker-fn
         (fn [target-bytes]
           (let [message-digest (MessageDigest/getInstance "SHA-256") ;; new digest instance per thread
                 sha256 (partial digest message-digest)]
             (some (partial check-candidate target-bytes sha256)
                   (selections space 5)))))))
Output:
Answer found for: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b => apple
Answer found for: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f => mmmmm
Answer found for: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad => zyzzx

Common Lisp

Library: lparallel
Library: ironclad
(defpackage #:parallel-brute-force
  (:use #:cl
        #:lparallel))

(in-package #:parallel-brute-force)

(defparameter *alphabet* "abcdefghijklmnopqrstuvwxyz")
(defparameter *hash0* "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
(defparameter *hash1* "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
(defparameter *hash2* "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
(defparameter *kernel-size* 7)

(defun sha-256 (input)
  (ironclad:byte-array-to-hex-string
   (ironclad:digest-sequence :sha256 (ironclad:ascii-string-to-byte-array input))))

(defun call-with-5-char-string (fun first-char)
  (loop with str = (make-array 5 :element-type 'character :initial-element first-char)
        for c1 across *alphabet*
        do (setf (char str 1) c1)
           (loop for c2 across *alphabet*
                 do (setf (char str 2) c2)
                    (loop for c3 across *alphabet*
                          do (setf (char str 3) c3)
                             (loop for c4 across *alphabet*
                                   do (setf (char str 4) c4)
                                      (funcall fun (copy-seq str)))))))

(defmacro with-5-char-string ((str first-char) &body body)
  `(call-with-5-char-string (lambda (,str) ,@body) ,first-char))

(defun find-passwords-with (first-char)
  (let (results)
    (with-5-char-string (str first-char)
      (let ((hash (sha-256 str)))
        (when (or (string= hash *hash0*) (string= hash *hash1*) (string= hash *hash2*))
          (push (list str hash) results))))
    (nreverse results)))

(defun find-passwords ()
  (setf *kernel* (make-kernel *kernel-size*))
  (let ((results (unwind-protect
                      (pmapcan #'find-passwords-with *alphabet*)
                   (end-kernel))))
    (dolist (r results)
      (format t "~A: ~A~%" (first r) (second r)))))
Output:
apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

D

There is at least one more method not shown for doing the task in parallel, which uses the std.concurrency module instead.

import std.digest.sha;
import std.parallelism;
import std.range;
import std.stdio;

// Find the five lower-case letter strings representing the following sha256 hashes
immutable p1 = cast(ubyte[32]) x"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad";
immutable p2 = cast(ubyte[32]) x"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b";
immutable p3 = cast(ubyte[32]) x"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f";

void main() {
    import std.datetime.stopwatch;

    auto sw = StopWatch(AutoStart.yes);
    // Switch these top loops to toggle between non-parallel and parrallel solutions.
    // foreach(char a; 'a'..'z'+1) {
    foreach(i, a; taskPool.parallel(iota('a', 'z'+1))) {
        char[5] psw;
        psw[0] = cast(char) a;
        foreach(char b; 'a'..'z'+1) {
            psw[1] = b;
            foreach(char c; 'a'..'z'+1) {
                psw[2] = c;
                foreach(char d; 'a'..'z'+1) {
                    psw[3] = d;
                    foreach(char e; 'a'..'z'+1) {
                        psw[4] = e;
                        auto hash = psw.sha256Of;
                        if (equal(hash, p1) || equal(hash, p2) || equal(hash, p3)) {
                            writefln("%s <=> %(%x%)", psw, hash);
                        }
                    }
                }
            }
        }
    }
    sw.stop;
    writeln(sw.peek);
}

//Specialization that supports static arrays too
bool equal(T)(const T[] p, const T[] q) {
    if (p.length != q.length) {
        return false;
    }

    for(int i=0; i<p.length; i++) {
        if (p[i] != q[i]) {
            return false;
        }
    }

    return true;
}
Output:

Parallel run time: 9 secs, 684 ms, 678 ╬╝s, and 6 hnsecs
Sequential run time: 29 secs, 298 ms, and 837 ╬╝s

apple <=> 3a7bd3e236a3d29eea436fcfb7e44c735d117c42d1c183542b6b9942dd4f1b
mmmmm <=> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx <=> 1115dd80feaacefdf481f1f9070374a2a81e27880f187396db67958b27cbad

Delphi

Library: DCPsha256

[[1]]

program Parallel_Brute_Force;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Threading,
  DCPsha256;

function Sha256(W: string): string;
var
  HashDigest: array[0..31] of byte;
  d, i: Byte;
begin
  Result := '';
  with TDCP_sha256.Create(nil) do
  begin
    Init;
    UpdateStr(W);
    final(HashDigest[0]);
    for i := 0 to High(HashDigest) do
      Result := Result + lowercase(HashDigest[i].ToHexString(2));
  end;
end;

procedure Force(a: int64);
var
  password: string;
  hash: string;
  i, j, k, l: integer;
  w: string;
const
  Words: TArray<string> = ['1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad',
    '3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b',
    '74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f'];
begin
  password := '     ';
  password[1] := chr(97 + a);

  for i := 97 to 122 do
  begin
    password[2] := chr(i);
    for j := 97 to 122 do
    begin
      password[3] := chr(j);
      for k := 97 to 122 do
      begin
        password[4] := chr(k);
        for l := 97 to 122 do
        begin
          password[5] := chr(l);
          hash := Sha256(password);

          for w in Words do
          begin
            if SameText(hash, w) then
            begin
              Writeln('>>', password, ' => ', hash);
            end;
          end;
        end;
      end;
    end;
  end;
end;

var
  s: string;
begin

  TParallel.&For(0, 25, Force);

  Writeln('Enter to exit');
  readln;
end.

Elixir

defmodule RosettacodeBruteForce do
  require Logger

  @spec start() :: :ok
  def start() do
    children = [
      {Task.Supervisor, name: Bf.TaskSupervisor}
    ]
    Supervisor.start_link(children, strategy: :one_for_one)
    start_bf("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
    start_bf("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
    start_bf("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
    :ok
  end

  @spec start_bf(String.t()) :: :ok
  def start_bf(target) do
    Enum.each(0..25, fn a ->
      Enum.each(0..25, fn b ->
        Task.Supervisor.async(Bf.TaskSupervisor, fn ->
          solve_bf(a, b, target)
        end)
      end)
    end)
    :ok
  end

  defp solve_bf(a, b, target) do
    Enum.each(0..25, fn x ->
      Enum.each(0..25, fn y ->
        Enum.each(0..25, fn z ->
          candidate = List.to_string([?a + a, ?a + b, ?a + x, ?a + y, ?a + z])
          if (check_hash?(candidate, target)) do
            Logger.info("SOLVED: #{candidate} = #{target}")
          end
        end)
      end)
    end)
    :ok
  end

  defp check_hash?(candidate, target) do
    target == :crypto.hash(:sha256, candidate)
    |> Base.encode16()
    |> String.downcase()
  end
end
Output:
08:19:43.178 [info] SOLVED: apple = 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
08:19:43.489 [info] SOLVED: zyzzx = 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
08:19:50.224 [info] SOLVED: mmmmm = 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f

Erlang

There are a total of 8 tasks, each handling a different set of prefixes (abc, def, ghi, jkl, mno, pqr, stuv, wxyz)

#! /usr/bin/escript
-mode(compile).
-export([cracker/4, supervisor/3]).

hexdigit(N) when (N >= 0) and (N =< 9) -> N + $0;
hexdigit(N) when (N >= 10) and (N < 16) -> N - 10 + $a.

hexbyte(N) -> [hexdigit(N bsr 4), hexdigit(N band 15)].

match(Key, Hash) ->
    B = crypto:hash(sha256, Key),
    Hash == lists:append([hexbyte(X) || <<X:8/integer>> <= B]).

cracker(Prefixes, Rest, Hashes, Boss) ->
    Results = [[[P|Q], Hash]
        || P <- Prefixes, Q <- Rest, Hash <- Hashes, match([P|Q], Hash)],
    Boss ! {done, Results}.

supervisor(0, Results, Caller) -> Caller ! {done, Results};
supervisor(Tasks, Results, Caller) ->
    receive
        {done, Cracked} -> supervisor(Tasks - 1, Cracked ++ Results, Caller)
    end.

main(_) ->
    Tasks = ["abc", "def", "ghi", "jkl", "mno", "pqr", "stuv", "wxyz"],
    Letter = lists:seq($a, $z),
    Rest = [[B, C, D, E] || B <- Letter, C <- Letter, D <- Letter, E <- Letter],
    Hashes = [
        "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
        "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
        "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
    ],
    Boss = spawn(?MODULE, supervisor, [length(Tasks), [], self()]),
    [spawn(?MODULE, cracker, [Prefixes, Rest, Hashes, Boss])
        || Prefixes <- Tasks],

    receive
        {done, Results} -> Results
    end,

    [io:format("~s: ~s~n", Result) || Result <- Results].
Output:
$ ./par-brute.erl 
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b

F#

(*
Nigel Galloway February 21st., 2017
*)
let N n i g e l = 
  let G = function
    |"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"->Some(string n+string i+string g+string e+string l)
    |"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"->Some(string n+string i+string g+string e+string l)
    |"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"->Some(string n+string i+string g+string e+string l)
    |_->None
  G ([|byte n;byte i;byte g;byte e;byte l|]|>System.Security.Cryptography.SHA256.Create().ComputeHash|>Array.map(fun (x:byte)->System.String.Format("{0:x2}",x))|>String.concat "")
open System.Threading.Tasks
let n1 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n2 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n3 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n4 = Task.Factory.StartNew(fun ()->['a'..'m']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n5 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n6 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['a'..'m']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n7 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['a'..'m']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))
let n8 = Task.Factory.StartNew(fun ()->['n'..'z']|>List.collect(fun n->['n'..'z']|>List.collect(fun i->['n'..'z']|>List.collect(fun g->['a'..'z']|>List.collect(fun e->['a'..'z']|>List.choose(fun l->N n i g e l))))))

for r in n1.Result@n2.Result@n3.Result@n4.Result@n5.Result@n6.Result@n7.Result@n8.Result do printfn "%s" r
Output:

mmmmm
apple
zyzzx

FreeBASIC

Translation of: Visual_Basic_.NET
Translation of: BaCon
Function SHA_256(Byval message As String) As String 
    #Macro Ch (x, y, z)
    (((x) And (y)) Xor ((Not (x)) And z))
    #EndMacro
    
    #Macro Maj (x, y, z)
    (((x) And (y)) Xor ((x) And (z)) Xor ((y) And (z)))
    #EndMacro
    
    #Macro sigma0 (x)
    (((x) Shr 2 Or (x) Shl 30) Xor ((x) Shr 13 Or (x) Shl 19) Xor ((x) Shr 22 Or (x) Shl 10))
    #EndMacro
    
    #Macro sigma1 (x)
    (((x) Shr 6 Or (x) Shl 26) Xor ((x) Shr 11 Or (x) Shl 21) Xor ((x) Shr 25 Or (x) Shl 7))
    #EndMacro
    
    #Macro sigma2 (x)
    (((x) Shr 7 Or (x) Shl 25) Xor ((x) Shr 18 Or (x) Shl 14) Xor ((x) Shr 3))
    #EndMacro
    
    #Macro sigma3 (x)
    (((x) Shr 17 Or (x) Shl 15) Xor ((x) Shr 19 Or (x) Shl 13) Xor ((x) Shr 10))
    #EndMacro
    
    Dim As Long i, j
    Dim As Ubyte Ptr ww1
    Dim As Uinteger<32> Ptr ww4
    
    Dim As Ulongint l = Len(message)
    ' set the first bit after the message to 1
    message = message + Chr(1 Shl 7)
    ' add one char to the length
    Dim As Ulong padding = 64 - ((l + 1) Mod (512 \ 8))
    
    ' check if we have enough room for inserting the length
    If padding < 8 Then padding += 64
    
    message += String(padding, Chr(0))   ' adjust length
    Dim As Ulong l1 = Len(message)       ' new length
    
    l = l * 8    ' orignal length in bits
    ' create ubyte ptr to point to l ( = length in bits)
    Dim As Ubyte Ptr ub_ptr = Cast(Ubyte Ptr, @l)
    
    For i = 0 To 7  'copy length of message to the last 8 bytes
        message[l1 -1 - i] = ub_ptr[i]
    Next
    
    'table of constants
    Dim As Uinteger<32> K(0 To ...) = { _
    &H428a2f98, &H71374491, &Hb5c0fbcf, &He9b5dba5, &H3956c25b, &H59f111f1, _
    &H923f82a4, &Hab1c5ed5, &Hd807aa98, &H12835b01, &H243185be, &H550c7dc3, _
    &H72be5d74, &H80deb1fe, &H9bdc06a7, &Hc19bf174, &He49b69c1, &Hefbe4786, _
    &H0fc19dc6, &H240ca1cc, &H2de92c6f, &H4a7484aa, &H5cb0a9dc, &H76f988da, _
    &H983e5152, &Ha831c66d, &Hb00327c8, &Hbf597fc7, &Hc6e00bf3, &Hd5a79147, _
    &H06ca6351, &H14292967, &H27b70a85, &H2e1b2138, &H4d2c6dfc, &H53380d13, _
    &H650a7354, &H766a0abb, &H81c2c92e, &H92722c85, &Ha2bfe8a1, &Ha81a664b, _
    &Hc24b8b70, &Hc76c51a3, &Hd192e819, &Hd6990624, &Hf40e3585, &H106aa070, _
    &H19a4c116, &H1e376c08, &H2748774c, &H34b0bcb5, &H391c0cb3, &H4ed8aa4a, _
    &H5b9cca4f, &H682e6ff3, &H748f82ee, &H78a5636f, &H84c87814, &H8cc70208, _
    &H90befffa, &Ha4506ceb, &Hbef9a3f7, &Hc67178f2 }
    
    Dim As Uinteger<32> h0 = &H6a09e667
    Dim As Uinteger<32> h1 = &Hbb67ae85
    Dim As Uinteger<32> h2 = &H3c6ef372
    Dim As Uinteger<32> h3 = &Ha54ff53a
    Dim As Uinteger<32> h4 = &H510e527f
    Dim As Uinteger<32> h5 = &H9b05688c
    Dim As Uinteger<32> h6 = &H1f83d9ab
    Dim As Uinteger<32> h7 = &H5be0cd19
    Dim As Uinteger<32> a, b, c, d, e, f, g, h
    Dim As Uinteger<32> t1, t2, w(0 To 63)
    
    
    For j = 0 To (l1 -1) \ 64 ' split into block of 64 bytes
        ww1 = Cast(Ubyte Ptr, @message[j * 64])
        ww4 = Cast(Uinteger<32> Ptr, @message[j * 64])
        
        For i = 0 To 60 Step 4  'little endian -> big endian
            Swap ww1[i   ], ww1[i +3]
            Swap ww1[i +1], ww1[i +2]
        Next i
        
        For i = 0 To 15    ' copy the 16 32bit block into the array
            W(i) = ww4[i]
        Next i
        
        For i = 16 To 63   ' fill the rest of the array
            w(i) = sigma3(W(i -2)) + W(i -7) + sigma2(W(i -15)) + W(i -16)
        Next i
        
        a = h0 : b = h1 : c = h2 : d = h3 : e = h4 : f = h5 : g = h6 : h = h7
        
        For i = 0 To 63
            t1 = h + sigma1(e) + Ch(e, f, g) + K(i) + W(i)
            t2 = sigma0(a) + Maj(a, b, c)
            h = g : g = f : f = e
            e = d + t1
            d = c : c = b : b = a
            a = t1 + t2
        Next i
        
        h0 += a : h1 += b : h2 += c : h3 += d
        h4 += e : h5 += f : h6 += g : h7 += h
    Next j
    
    Dim As String answer = Hex(h0, 8) + Hex(h1, 8) + Hex(h2, 8) + Hex(h3, 8)
    answer += Hex(h4, 8) + Hex(h5, 8) + Hex(h6, 8) + Hex(h7, 8) 
    Return Lcase(answer)
End Function

Dim t0 As Double = Timer
Dim Shared sha256fp(0 To 2) As String
sha256fp(0) = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
sha256fp(1) = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
sha256fp(2) = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"

Sub PrintCode(n As Integer)  
    Dim As String fp = sha256fp(n)
    Dim As Integer c1, c2, c3, c4, c5
    For c1 = 97 To 122
        For c2 = 97 To 122
            For c3 = 97 To 122
                For c4 = 97 To 122
                    For c5 = 97 To 122
                        If fp = SHA_256(Chr(c1)+Chr(c2)+Chr(c3)+Chr(c4)+Chr(c5)) Then
                            Print Chr(c1)+Chr(c2)+Chr(c3)+Chr(c4)+Chr(c5); " => "; fp
                            Exit For, For, For, For, For
                        End If
                    Next c5
                Next c4
            Next c3
        Next c2
    Next c1  
End Sub

For i As Byte= 0 to 2
    PrintCode(i)
Next i
Sleep

Frink

This does not use any parallel processing but just demonstrates Frink's built-in password hashing.

hashes = new set["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
 "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
 "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]

r = new range["a", "z"]
multifor array = [r,r,r,r,r]
{
   str = join["", array]
   hash = messageDigest[str, "SHA-256"]
   if hashes.contains[hash]
      println["$str: $hash"]
}
Output:
apple: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Go

This solution runs 26 goroutines, one for each possible password first letter. Goroutines run in parallel on a multicore system.

package main

import (
    "crypto/sha256"
    "encoding/hex"
    "log"
    "sync"
)

var hh = []string{
    "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
    "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
    "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f",
}

func main() {
    log.SetFlags(0)
    hd := make([][sha256.Size]byte, len(hh))
    for i, h := range hh {
        hex.Decode(hd[i][:], []byte(h))
    }
    var wg sync.WaitGroup
    wg.Add(26)
    for c := byte('a'); c <= 'z'; c++ {
        go bf4(c, hd, &wg)
    }
    wg.Wait()
}

func bf4(c byte, hd [][sha256.Size]byte, wg *sync.WaitGroup) {
    p := []byte("aaaaa")
    p[0] = c
    p1 := p[1:]
p:
    for {
        ph := sha256.Sum256(p)
        for i, h := range hd {
            if h == ph {
                log.Println(string(p), hh[i])
            }
        }
        for i, v := range p1 {
            if v < 'z' {
                p1[i]++
                continue p
            }
            p1[i] = 'a'
        }
        wg.Done()
        return
    }
}
Output:
zyzzx 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
apple 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f

Haskell

Uses libraries:

  • cryptonite
  • monad-par
  • bytestring
  • split


Compile with "-O2 -threaded"
7.391s elapsed on a 2.5 GHz Dual-Core Intel Core i7 Macbook Pro.

import           Control.Concurrent (setNumCapabilities)
import           Crypto.Hash        (hashWith, SHA256 (..), Digest)
import           Control.Monad      (replicateM, join, (>=>))
import           Control.Monad.Par  (runPar, get, spawnP)
import           Data.ByteString    (pack)
import           Data.List.Split    (chunksOf)
import           GHC.Conc           (getNumProcessors)
import           Text.Printf        (printf)

hashedValues :: [Digest SHA256]
hashedValues = read <$>
  [ "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
  , "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
  , "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad" ]

bruteForce :: Int -> [(String, String)]
bruteForce n = runPar $ join <$> 
  (mapM (spawnP . foldr findMatch []) >=> mapM get) chunks
  where
    chunks = chunksOf (26^5 `div` n) $ replicateM 5 [97..122]
    findMatch s accum
      | hashed `elem` hashedValues = (show hashed, show bStr) : accum
      | otherwise = accum
      where
        bStr = pack s
        hashed = hashWith SHA256 bStr

main :: IO ()
main = do
  cpus <- getNumProcessors
  setNumCapabilities cpus
  printf "Using %d cores\n" cpus
  mapM_ (uncurry (printf "%s -> %s\n")) (bruteForce cpus)
Output:
brute
Using 4 cores
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b -> apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f -> mmmmm
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad -> zyzzx

Or using worker threads with buffered read/write channels.

Here all the possible test strings are batched as a stream that is fed to worker threads via a single read channel (batchChan). Each worker thread listens to the read channel (batchChan) and will write to the write channel (resultChan) when it finds a match. The worker threads loop indefinitely returning to read the next message on the read channel (batchChan). The main thread listens to the write channel (resultChan) and terminates once all three messages have been received.

import           Control.Concurrent      (forkIO, setNumCapabilities)
import           Control.Concurrent.Chan (Chan, newChan, readChan, writeList2Chan)
import           Control.Monad           (replicateM, replicateM_, forever)
import           Crypto.Hash             (SHA256(..), Digest, hashWith)
import           Data.Bifunctor          (first)
import           Data.ByteString         (ByteString, pack)
import           Data.Char               (isDigit)
import           Data.List.Split         (chunksOf)
import           Data.Word               (Word8)
import           GHC.Conc                (getNumProcessors)
import           System.Environment      (getArgs)
import           Text.Printf             (printf)

type Decrypted = String
type Encrypted = Digest SHA256
type TestString = [Word8]

hashedValues :: [Encrypted]
hashedValues = read <$>
  [ "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
  , "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
  , "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad" ]

chunks :: [[TestString]]
chunks = chunksOf (10^3) $ replicateM 5 [97..122]

findMatch :: TestString -> [(Encrypted, Decrypted)] -> [(Encrypted, Decrypted)]
findMatch w acc
  | hashed `elem` hashedValues = (hashed, show bStr):acc
  | otherwise = acc
  where
    bStr = pack w
    hashed = hashWith SHA256 bStr

searchWorker :: Chan [TestString] -> Chan (Encrypted, Decrypted) -> IO ()
searchWorker batchChan resultChan = forever (readChan batchChan >>= writeList2Chan resultChan . foldr findMatch [])

parseInput :: [String] -> Int -> Int
parseInput [] n    = n
parseInput (s:_) n = if all isDigit s then read s else n

main :: IO ()
main = do
  workers <- getArgs
  cpus <- getNumProcessors
  let wCount = parseInput workers cpus
  setNumCapabilities wCount
  printf "Using %d workers on %d cpus.\n" wCount cpus
  resultChan <- newChan
  batchChan <- newChan
  replicateM_ wCount (forkIO $ searchWorker batchChan resultChan)
  writeList2Chan batchChan chunks
  replicateM_ (length hashedValues) (readChan resultChan >>= uncurry (printf "%s -> %s\n") . first show)
Output:
brute2                     
Using 4 workers on 4 cpus.
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b -> "apple"
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f -> "mmmmm"
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad -> "zyzzx"

Java

Works with: Java version 1.5

This example uses Java's multithreading capabilities. Note that the Java Virtual Machine will use native Threads if the underlying platform supprts them. If there is no native thread support, the Java VM will emulate threads. This implementation runs 3 threads (one per hash to crack), and short-stops when a match for a hash is found.

import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * "Main Program" that does the parallel processing
 */
public class ParallelBruteForce {

    public static void main(String[] args) throws NoSuchAlgorithmException {

        //the hashes to be cracked
        String[] hashes = {"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
                "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
                "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};

        //An ExecutorService is a high-level parallel programming facility, that can execute a number of tasks
        //the FixedThreadPool is an ExecutorService that uses a configurable number of parallel threads
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        //Submit one Task per hash to the thread po
        for (String hash : hashes) {
            executorService.submit(new Forcer(hash));
        }

        //An ExecutorSerice must be shut down properly (this also causes the program to await termination of
        // all pending tasks in the thread pool)
        executorService.shutdown();
    }
}

/**
 * The Class that contains the actual brute-forcing task.
 * <p>
 * It implements the build-in Interface "Runnable", so it can be run on a Thread or a Thread-Execution-Facility
 * (such as an ExecutorService).
 */
class Forcer implements Runnable {

    private static final int LENGTH = 5;

    //These will sore the hash to be cracked in both bytes (required for comparison) and String representation
    // (required for output)
    private final byte[] crackMe;
    private final String crackMeString;

    //The MessageDigest does the SHA-256 caclulation. Note that this may throw a NoSuchAlgorithmException when there
    // is no SHA-256 implementation in the local standard libraries (but that algorithm is mandatory, so this code
    // probably will never throw that Excpetion
    private final MessageDigest digest = MessageDigest.getInstance("SHA-256");

    public Forcer(String crackMe) throws NoSuchAlgorithmException {
        this.crackMeString = crackMe;
        this.crackMe = DatatypeConverter.parseHexBinary(crackMe);
    }

    @Override
    public void run() {

        String match = "";

        //all loops use this array for their counters. This is very dirty and should never be done in production!
        char[] chars = new char[LENGTH];

        //used for short-stopping when a match is found - one could abuse the match-variable for this, but this is
        // much clearer
        boolean done = false;

        for (chars[0] = 'a'; chars[0] <= 'z' && !done; chars[0]++) {
            for (chars[1] = 'a'; chars[1] <= 'z' && !done; chars[1]++) {
                for (chars[2] = 'a'; chars[2] <= 'z' && !done; chars[2]++) {
                    for (chars[3] = 'a'; chars[3] <= 'z' && !done; chars[3]++) {
                        for (chars[4] = 'a'; chars[4] <= 'z' && !done; chars[4]++) {
                            //the String creation is necessary to get the encoding right
                            String canidate = new String(chars);
                            //genenrate SHA-256 hash using Java's standard facilities
                            byte[] hash = digest.digest(canidate.getBytes());
                            if (Arrays.equals(hash, crackMe)) {
                                match = canidate;
                                done = true;
                            }

                        }
                    }
                }
            }
        }
        System.out.println(String.format("Hash %s has the following match : %s", crackMeString, match));
    }
}
Output:
Hash 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b has the following match : apple

Hash 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f has the following match : mmmmm

Hash 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad has the following match : zyzzx

Faster Alternative Version

Combines ideas from the C++ solution and the above Java version. Execution time is about 1.6 seconds on my system (3.2 GHz Quad-Core Intel Core i5, macOS 10.15.3).

import javax.xml.bind.DatatypeConverter;
import java.security.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

public class ParallelBruteForce {
    public static void main(String[] args) {
        try {
            String[] hashes = {
                "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
                "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
                "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"};
            ParallelBruteForce pbf = new ParallelBruteForce(5, hashes);
            pbf.findPasswords();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private ParallelBruteForce(int length, String[] hashes) {
        this.length = length;
        this.hashes = hashes;
        digests = new byte[hashes.length][];
        for (int i = 0; i < hashes.length; ++i)
            digests[i] = DatatypeConverter.parseHexBinary(hashes[i]);
    }

    private void findPasswords() throws Exception {
        count.set(length);
        int processors = Runtime.getRuntime().availableProcessors();
        ExecutorService svc = Executors.newFixedThreadPool(processors);
        List<Future<?>> tasks = new ArrayList<>();
        for (int i = 0; i < 26; ++i)
            tasks.add(svc.submit(new PasswordFinder((byte)(97 + i))));
        for (Future<?> task : tasks)
            task.get();
        svc.shutdown();
    }

    private static boolean nextPassword(byte[] passwd, int start) {
        int len = passwd.length;
        for (int i = len - 1; i >= start; --i) {
            if (passwd[i] < 122) {
                ++passwd[i];
                return true;
            }
            passwd[i] = 97;
        }
        return false;
    }

    private class PasswordFinder implements Runnable {
        private byte ch;
        private MessageDigest md = MessageDigest.getInstance("SHA-256");
        private PasswordFinder(byte c) throws NoSuchAlgorithmException {
            ch = c;
        }
        public void run() {
            byte[] passwd = new byte[length];
            Arrays.fill(passwd, (byte)97);
            passwd[0] = ch;
            while (count.get() > 0) {
                byte[] digest = md.digest(passwd);
                for (int m = 0; m < hashes.length; ++m) {
                    if (Arrays.equals(digest, digests[m])) {
                        count.decrementAndGet();
                        System.out.println("password: " + new String(passwd) + ", hash: " + hashes[m]);
                        break;
                    }
                }
                if (!nextPassword(passwd, 1))
                    break;
            }
        }
    }

    private int length;
    private String[] hashes;
    private byte[][] digests;
    private AtomicInteger count = new AtomicInteger();
}
Output:
password: apple, hash: 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
password: mmmmm, hash: 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
password: zyzzx, hash: 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Julia

@everywhere using SHA

@everywhere function bruteForceRange(startSerial, numberToDo)
  targets = ["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
             "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
             "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]
  targets = map(hex2bytes, targets)
  for count = 1 : numberToDo
    password = [UInt8(97 + x) for x in digits(UInt8, startSerial + count, 26, 5)]
    hashbytes = sha256(password)
    if (hashbytes[1] == 0x11 || hashbytes[1] == 0x3a || hashbytes[1] == 0x74) && findfirst(targets, hashbytes) > 0
      hexstring = join(hex(x,2) for x in hashbytes)
      passwordstring = join(map(Char, password))
      println("$passwordstring --> $hexstring")
    end
  end
  return 0
end

@everywhere perThread = div(26^5, Sys.CPU_CORES)
pmap(x -> bruteForceRange(x * perThread, perThread), 0:Sys.CPU_CORES-1)
Output:
From worker 2:  apple --> 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b

From worker 3: zyzzx --> 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

From worker 4: mmmmm --> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f

Kotlin

Translation of: C#
// version 1.1.51

import java.security.MessageDigest

fun stringHashToByteHash(hash: String): ByteArray {
    val ba = ByteArray(32)
    for (i in 0 until 64 step 2) ba[i / 2] = hash.substring(i, i + 2).toInt(16).toByte()
    return ba
}

fun ByteArray.matches(other: ByteArray): Boolean {
    for (i in 0 until 32) {
        if (this[i] != other[i]) return false
    }
    return true
}

fun main(args: Array<String>) {
    val stringHashes = listOf(
        "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
        "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
        "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
    )
    val byteHashes = List(3) { stringHashToByteHash(stringHashes[it]) }
    val letters = List(26) { (97 + it).toByte() }

    letters.stream().parallel().forEach {
        val md = MessageDigest.getInstance("SHA-256")
        val range = 97..122
        val pwd = ByteArray(5)
        pwd[0] = it
        for (i1 in range) {
            pwd[1] = i1.toByte()    
            for (i2 in range) {
                pwd[2] = i2.toByte()
                for (i3 in range) {
                    pwd[3] = i3.toByte()
                    for (i4 in range) {
                        pwd[4] = i4.toByte()
                        val ba = md.digest(pwd)
                        for (j in 0..2) {
                            if (ba.matches(byteHashes[j])) {          
                                val password = pwd.toString(Charsets.US_ASCII)
                                println("$password => ${stringHashes[j]}")
                                break
                            }
                        }
                    }
                }
            }
        }
    }
}
Output:
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Mathematica/Wolfram Language

testPassword[pass_String] := 
 If[MemberQ[{16^^1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad,
    16^^3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b,
    16^^74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f},
   Hash[pass, "SHA256"]], Print[pass]];

chars=CharacterRange["a","z"];

ParallelDo[
    testPassword[StringJoin[a, b, c, d, e]],
 {a, chars}, {b, chars}, {c, chars}, {d, chars}, {e, chars}]

Modula-2

MODULE PBF;
FROM FormatString IMPORT FormatString;
FROM SHA256 IMPORT SHA256,Create,Destroy,HashBytes,Finalize,GetHash;
FROM SYSTEM IMPORT ADR,ADDRESS,BYTE;
FROM Terminal IMPORT Write,WriteString,WriteLn,ReadChar;
FROM Threads IMPORT Thread,CreateThread,WaitForThreadTermination;

PROCEDURE PrintHexBytes(str : ARRAY OF BYTE; limit : INTEGER);
VAR
    buf : ARRAY[0..7] OF CHAR;
    i,v : INTEGER;
BEGIN
    i := 0;
    WHILE i<limit DO
        v := ORD(str[i]);
        IF v < 16 THEN
            WriteString("0")
        END;
        FormatString("%h", buf, v);
        WriteString(buf);
        INC(i);
    END
END PrintHexBytes;

PROCEDURE Check(str : ARRAY OF CHAR);
TYPE
    HA = ARRAY[0..31] OF BYTE;
CONST
    h1 = HA{3aH, 7bH, 0d3H, 0e2H, 36H, 0aH, 3dH, 29H, 0eeH, 0a4H, 36H, 0fcH, 0fbH, 7eH, 44H, 0c7H, 35H, 0d1H, 17H, 0c4H, 2dH, 1cH, 18H, 35H, 42H, 0bH, 6bH, 99H, 42H, 0ddH, 4fH, 1bH};
    h2 = HA{74H, 0e1H, 0bbH, 62H, 0f8H, 0daH, 0bbH, 81H, 25H, 0a5H, 88H, 52H, 0b6H, 3bH, 0dfH, 6eH, 0aeH, 0f6H, 67H, 0cbH, 56H, 0acH, 7fH, 7cH, 0dbH, 0a6H, 0d7H, 30H, 5cH, 50H, 0a2H, 2fH};
    h3 = HA{11H, 15H, 0ddH, 80H, 0fH, 0eaH, 0acH, 0efH, 0dfH, 48H, 1fH, 1fH, 90H, 70H, 37H, 4aH, 2aH, 81H, 0e2H, 78H, 80H, 0f1H, 87H, 39H, 6dH, 0b6H, 79H, 58H, 0b2H, 07H, 0cbH, 0adH};
VAR
    hash : SHA256;
    out : ARRAY[0..31] OF BYTE;
    i : CARDINAL;
    match : BOOLEAN;
BEGIN
    hash := Create();

    HashBytes(hash, ADR(str), HIGH(str)+1);
    Finalize(hash);

    GetHash(hash, out);
    Destroy(hash);

    match := TRUE;
    FOR i:=0 TO HIGH(out) DO
        IF out[i] # h1[i] THEN
            match := FALSE;
            BREAK
        END
    END;
    IF match THEN
        WriteString(str);
        WriteString(" ");
        PrintHexBytes(out, 32);
        WriteLn;
        RETURN
    END;

    match := TRUE;
    FOR i:=0 TO HIGH(out) DO
        IF out[i] # h2[i] THEN
            match := FALSE;
            BREAK
        END
    END;
    IF match THEN
        WriteString(str);
        WriteString(" ");
        PrintHexBytes(out, 32);
        WriteLn;
        RETURN
    END;

    match := TRUE;
    FOR i:=0 TO HIGH(out) DO
        IF out[i] # h3[i] THEN
            match := FALSE;
            BREAK
        END
    END;
    IF match THEN
        WriteString(str);
        WriteString(" ");
        PrintHexBytes(out, 32);
        WriteLn
    END
END Check;

PROCEDURE CheckWords(a : CHAR);
VAR
    word : ARRAY[0..4] OF CHAR;
    b,c,d,e : CHAR;
BEGIN
    word[0] := a;
    FOR b:='a' TO 'z' DO
        word[1] := b;
        FOR c:='a' TO 'z' DO
            word[2] := c;
            FOR d:='a' TO 'z' DO
                word[3] := d;
                FOR e:='a' TO 'z' DO
                    word[4] := e;
                    Check(word)
                END
            END
        END
    END
END CheckWords;

PROCEDURE CheckAF(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
    FOR a:='a' TO 'f' DO
        CheckWords(a)
    END;
    RETURN 0
END CheckAF;

PROCEDURE CheckGM(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
    FOR a:='g' TO 'm' DO
        CheckWords(a)
    END;
    RETURN 0
END CheckGM;

PROCEDURE CheckNS(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
    FOR a:='n' TO 's' DO
        CheckWords(a)
    END;
    RETURN 0
END CheckNS;

PROCEDURE CheckTZ(ptr : ADDRESS) : CARDINAL;
VAR a : CHAR;
BEGIN
    FOR a:='t' TO 'z' DO
        CheckWords(a)
    END;
    RETURN 0
END CheckTZ;

VAR
    t1,t2,t3,t4 : Thread;
    s1,s2,s3,s4 : CARDINAL;
BEGIN
    CreateThread(t1,CheckAF,NIL,0,TRUE);
    CreateThread(t2,CheckGM,NIL,0,TRUE);
    CreateThread(t3,CheckNS,NIL,0,TRUE);
    CreateThread(t4,CheckTZ,NIL,0,TRUE);

    WaitForThreadTermination(t1,-1,s1);
    WaitForThreadTermination(t2,-1,s2);
    WaitForThreadTermination(t3,-1,s3);
    WaitForThreadTermination(t4,-1,s4);

    WriteString("Done");
    WriteLn;
    ReadChar
END PBF.
Output:
apple 3A7BD3E2360A3D29EEA436FCFB7E44C735D117C42D1C1835420B6B9942DD4F1B
mmmmm 74E1BB62F8DABB8125A58852B63BDF6EAEF667CB56AC7F7CDBA6D7305C50A22F
zyzzx 1115DD800FEAACEFDF481F1F9070374A2A81E27880F187396DB67958B207CBAD
Done

Nim

Library: Nimcrypto

Using a thread for each starting character. Note that the program must be compiled with option --threads:on.

import strutils, threadpool
import nimcrypto

const

  # List of hexadecimal representation of target hashes.
  HexHashes = ["1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
               "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
               "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"]

  # List of target hashes.
  Hashes = [MDigest[256].fromHex(HexHashes[0]),
            MDigest[256].fromHex(HexHashes[1]),
            MDigest[256].fromHex(HexHashes[2])]

  Letters = 'a'..'z'


proc findHashes(a: char) =
  ## Build the arrays of five characters starting with the value
  ## of "a" and check if their hash matches one of the targets.
  ## Print the string and the hash value if a match is found.
  for b in Letters:
    for c in Letters:
      for d in Letters:
        for e in Letters:
          let s = [a, b, c, d, e]
          let h = sha256.digest(s)
          for i, target in Hashes:
            if h == target:   # Match.
              echo s.join(), " → ", HexHashes[i]


# Launch a thread for each starting character.
for a in Letters:
  spawn findHashes(a)

sync()
Output:
apple → 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm → 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx → 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Perl

Uses threads library to do naive search using 26 threads ("aaaaa" .. "azzzz", "baaaa" .. "bzzzz", etc.). No effort is made to early exit.

use Digest::SHA qw/sha256_hex/;
use threads;
use threads::shared;
my @results :shared;

print "$_ : ",join(" ",search($_)), "\n" for (qw/
  1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
  3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
  74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
/);


sub search {
  my $hash = shift;
  @results = ();
  $_->join() for map { threads->create('tsearch', $_, $hash) } 0..25;
  return @results;
}

sub tsearch {
  my($tnum, $hash) = @_;
  my $s = chr(ord("a")+$tnum) . "aaaa";

  for (1..456976) { # 26^4
    push @results, $s if sha256_hex($s) eq $hash;
    $s++;
  }
}
Output:
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad : zyzzx
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b : apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f : mmmmm

Phix

Each thread processes one start letter at a time, until they are all done.

include builtins\sha256.e
include builtins\VM\pThreadN.e -- (shd not be rqd on 0.8.1+)
 
function asHex(string s)
string res = ""
    for i=1 to length(s) do
        res &= sprintf("%02X",s[i])
    end for
    return res
end function
 
sequence starts
constant start_cs = init_cs(),      -- critical section
         hashes = {x"1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
                   x"3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
                   x"74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
 
procedure find_passwords()
    sequence thrashes = {}  -- thread-safe copy of hashes
    enter_cs(start_cs)
    for i=1 to length(hashes) do
        thrashes = append(thrashes,thread_safe_string(hashes[i]))
    end for
    leave_cs(start_cs)
    while true do
        string pwd
        enter_cs(start_cs)
        if length(starts)=0 then
            leave_cs(start_cs)
            exit
        end if
        pwd = starts[$]&repeat('a',4)
        starts = starts[1..$-1]
        leave_cs(start_cs)
        while length(pwd) do
            string hash = sha256(pwd)
            if find(hash,thrashes) then ?{pwd,asHex(hash)} end if
            for i=5 to 2 by -1 do
                if pwd[i]!='z' then
                    pwd[i] += 1
                    exit
                end if
                pwd[i] = 'a'
                if i=2 then pwd = "" exit end if
            end for
        end while
    end while
    exit_thread(0)
end procedure
 
for nthreads=4 to 4 do
    atom t0 = time()
    starts = tagset('a','z',-1)
    sequence threads = {}
    for i=1 to nthreads do
        threads = append(threads,create_thread(routine_id("find_passwords"),{}))
    end for
    wait_thread(threads)
    string e = elapsed(time()-t0)
    printf(1,"completed with %d threads in %s\n",{nthreads,e})
end for
Output:

(with nthreads loop from 1 to 4, and for that case CPU use in Task Manager shows a very clear step pattern.)

{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 1 threads in 29.1s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 2 threads in 16.1s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 3 threads in 13.8s
{"apple","3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"}
{"mmmmm","74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"}
{"zyzzx","1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"}
completed with 4 threads in 12.7s

PureBasic

UseSHA2Fingerprint()

NewList sha256fp.s()
AddElement(sha256fp()) : sha256fp() = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
AddElement(sha256fp()) : sha256fp() = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
AddElement(sha256fp()) : sha256fp() = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
 
Procedure PrintCode(n.i)
  Shared sha256fp()  
  SelectElement(sha256fp(), n) : fp$ = sha256fp()
  For c1 = 'a' To 'z'
    For c2 = 'a' To 'z'
      For c3 = 'a' To 'z'
        For c4 = 'a' To 'z'
          For c5 = 'a' To 'z'                        
            If fp$ = StringFingerprint(Chr(c1) + Chr(c2) + Chr(c3) + Chr(c4) + Chr(c5), #PB_Cipher_SHA2, 256); maybe set enconding
              PrintN(Chr(c1) + Chr(c2) + Chr(c3) + Chr(c4) + Chr(c5) + " => " + fp$)
              Break(5)
            EndIf            
          Next c5
        Next c4
      Next c3
    Next c2
  Next c1    
EndProcedure

Dim mythread(ListSize(sha256fp()))

If OpenConsole("")  
  StartTime.q = ElapsedMilliseconds()
  
  For i=0 To ListSize(sha256fp()) - 1
    mythread(i)=CreateThread(@PrintCode(), i)
  Next 
  For i=0 To ListSize(sha256fp()) - 1
    WaitThread(mythread(i))
  Next

  PrintN("-----------")
  PrintN(Str(ElapsedMilliseconds() - StartTime)+" Milliseconds needed")
  Input()
EndIf
End
; EnableThread
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
-----------
36955 Milliseconds needed

Python

import multiprocessing
from hashlib import sha256

h1 = bytes().fromhex("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
h2 = bytes().fromhex("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
h3 = bytes().fromhex("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")

def brute(firstletterascii: int):
    global h1, h2, h3
    letters = bytearray(5)
    letters[0] = firstletterascii
    for letters[1] in range(97, 97 + 26):
        for letters[2] in range(97, 97 + 26):
            for letters[3] in range(97, 97 + 26):
                for letters[4] in range(97, 97 + 26):
                    digest = sha256(letters).digest()
                    if digest == h1 or digest == h2 or digest == h3:
                        password = "".join(chr(x) for x in letters)
                        print(password + " => " + digest.hex())
    return 0

def main():
    with multiprocessing.Pool() as p:
        p.map(brute, range(97, 97 + 26))

if __name__ == "__main__":
    main()
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Racket

Tests are included firstly to check it works, but they also provide an opportunity to time the single threaded version.

#lang racket/base
(require racket/place
         racket/list
         racket/match
         ;; requires sha package. install it in DrRacket's "File/Install Package..."
         ;; or with raco:
         ;; % raco pkg install sha
         sha
         (only-in openssl/sha1 hex-string->bytes))

(define (brute css targs)
  (define (sub-work i) (let ((cs (list-ref css i))) (in-range (car cs) (cdr cs))))
  (define-values (as bs cs ds es) (apply values (map sub-work (range 5))))
  (define s (make-bytes 5))
  (for*/list ((a as) #:when (bytes-set! s 0 a)
                     (b bs) #:when (bytes-set! s 1 b)
                     (c cs) #:when (bytes-set! s 2 c)
                     (d ds) #:when (bytes-set! s 3 d)
                     (e es) #:when (bytes-set! s 4 e)
                     (h (in-value (sha256 s)))
                     (t (in-list targs))
                     #:when (bytes=? t h))
    (eprintf "found ~s -> ~s~%" t s)
    (cons (bytes-copy s) t)))

;; ---------------------------------------------------------------------------------------------------
(unless (place-enabled?) (error "We're using places... they're not enabled!"))

(define target-list
  (map hex-string->bytes
       (list "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
             "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
             "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")))

(define (run-place/assign-task sub-task)
  (define there (place here
                       (match-define (cons work targs) (place-channel-get here))
                       (place-channel-put here (brute work targs))))
  (place-channel-put there (cons sub-task target-list))
  there)

(define (task->subtasks css n-tasks)
  (match css
    [(list (and initial-range (cons A Z+)) common-tail ...)
     (define step (quotient (+ n-tasks (- Z+ A)) n-tasks))
     (for/list ((a (in-range A Z+ step)))
       ;; replace the head with a sub-task head
       (cons (cons a (min (+ a step) Z+)) common-tail))]))

(define readable-pair (match-lambda [(cons x (app bytes->hex-string s)) (cons x s)]))

(define (parallel-brute css (n-tasks (processor-count)))
  (define the-places (map run-place/assign-task (task->subtasks css n-tasks)))
  (define collected-results (append* (map place-channel-get the-places)))
  (map readable-pair collected-results))

(define 5-char-lowercase-work
  (make-list 5 (cons (char->integer #\a) (add1 (char->integer #\z)))))

;; ---------------------------------------------------------------------------------------------------
(module+ main
  (time (parallel-brute 5-char-lowercase-work)))

;; ---------------------------------------------------------------------------------------------------
(module+ test
  (require rackunit)
  (check-equal?
   (bytes->hex-string (sha256 #"mmmmm"))
   "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
   "SHA-256 works as expected")

  (check-equal?
   (hex-string->bytes "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
   #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/"
   "This is the raw value we'll be hashing to")
  
  (define m-idx (char->integer #\m))
  (define m-idx+ (add1 m-idx))
  (check-equal?
   (brute (make-list 5 (cons m-idx m-idx+)) target-list)
   (list
    (cons
     #"mmmmm"
     #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/")))

  ;; Brute works without parallelism
  ;; check when you have the time... it takes a minute (literally)
  (check-equal?
   (time
    (brute 5-char-lowercase-work target-list))
   '((#"apple"
      . #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e")
     (#"mmmmm"
      .
      #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/")
     (#"zyzzx"
      .
      #"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255"))
   "without parallelism, it works"))
Output:

Test phase of run:

found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
found #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e" -> #"apple"
found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
found #"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255" -> #"zyzzx"
cpu time: 19593 real time: 19581 gc time: 2247

Main phase of run:

found #"\21\25\335\200\17\352\254\357\337H\37\37\220p7J*\201\342x\200\361\2079m\266yX\262\a\313\255" -> #"zyzzx"
found #":{\323\3426\n=)\356\2446\374\373~D\3075\321\27\304-\34\0305B\vk\231B\335O\e" -> #"apple"
found #"t\341\273b\370\332\273\201%\245\210R\266;\337n\256\366g\313V\254\177|\333\246\3270\\P\242/" -> #"mmmmm"
cpu time: 30641 real time: 4681 gc time: 0
'((#"apple" . "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
  (#"mmmmm" . "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")
  (#"zyzzx" . "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"))

Raku

(formerly Perl 6) This solution can be changed from parallel to serial by removing the .race method.

use Digest::SHA256::Native;
constant @alpha2 = [X~] <a   m p y z> xx 2;
constant @alpha3 = [X~] <e l m p x z> xx 3;

my %WANTED = set <
    3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
    74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
    1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
>;

sub find_it ( $first_two ) {
    for $first_two «~« @alpha3 -> \password {
        my \digest_hex = sha256-hex(password);
        return "{password} => {digest_hex}" if %WANTED{digest_hex}
    }
    ()
}

.say for flat @alpha2.race(:1batch).map: { find_it($_) };
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Testers can adjust the run speed by replacing the @alpha constants with one of the below:

# True to actual RC task, but slowest
constant @alpha2 = 'aa'  ..  'zz';
constant @alpha3 = 'aaa' .. 'zzz';

# Reduced alphabets for speed during development & testing
constant @alpha2 = [X~] <a   m p y z> xx 2;
constant @alpha3 = [X~] <e l m p x z> xx 3;

Rust

In this solution the number of threads is the number of logical processors on the machine. `distribute_work()` distributes the work more or less equally between the threads.

// [dependencies]
// rust-crypto = "0.2.36"
// num_cpus = "1.7.0"
// hex = "0.2.0"

extern crate crypto;
extern crate num_cpus;
extern crate hex;

use std::thread;
use std::cmp::min;
use crypto::sha2::Sha256;
use crypto::digest::Digest;
use hex::{FromHex, ToHex};

fn main() {
    let hashes = vec![
        decode("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"),
        decode("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"),
        decode("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"),
    ];

    let mut threads = Vec::new();
    let mut ranges = distribute_work();

    while let Some(range) = ranges.pop() {
        let hashes = hashes.clone();
        threads.push(thread::spawn(
            move || search(range.0, range.1, hashes.clone()),
        ));
    }

    while let Some(t) = threads.pop() {
        t.join().ok();
    }
}

fn search(from: [u8; 5], to: [u8; 5], hashes: Vec<[u8; 256 / 8]>) {

    let mut password = from.clone();

    while password <= to {
        let mut sha256 = Sha256::new();
        sha256.input(&password);
        let mut result = [0u8; 256 / 8];
        sha256.result(&mut result);

        for hash in hashes.iter() {
            if *hash == result {
                println!(
                    "{}{}{}{}{} {}",
                    password[0] as char,
                    password[1] as char,
                    password[2] as char,
                    password[3] as char,
                    password[4] as char,
                    hash.to_hex()
                );
            }
        }

        password = next(&password);
    }

}

fn next(password: &[u8; 5]) -> [u8; 5] {
    let mut result = password.clone();
    for i in (0..result.len()).rev() {
        if result[i] == b'z' {
            if i == 0 {
                result[i] = b'z' + 1;
            } else {
                result[i] = b'a';
            }
        } else {
            result[i] += 1;
            break;
        }
    }
    result.clone()
}

fn distribute_work() -> Vec<([u8; 5], [u8; 5])> {
    let mut ranges = Vec::new();
    let num_cpus = min(num_cpus::get(), 26) as u8;

    let div = 25 / num_cpus;
    let mut remainder = 25 % num_cpus;
    let mut from = b'a';
    while from < b'z' {

        let to = from + div +
            if remainder > 0 {
                remainder -= 1;
                1
            } else {
                0
            };

        ranges.push((
            [from, from, from, from, from + 1].clone(),
            [to, to, to, to, to].clone(),
        ));

        from = to;
    }
    ranges[0].0[4] = b'a';

    ranges.clone()
}

fn decode(string: &str) -> [u8; 256 / 8] {
    let mut result = [0; 256 / 8];
    let vec = Vec::from_hex(string).unwrap();
    for i in 0..result.len() {
        result[i] = vec[i];
    }
    result.clone()
}
Output:
apple 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
mmmmm 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f

Scala

Scala has an excellent implementation of parallel collections, which allow you to take advantage of parallel processing with only minor modifications to your code.

This example converts the collection of candidate strings into a ParVector as soon as possible, speeding up both the final step to generating the candidates and the search.

import java.security.MessageDigest

import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
  def main(args: Array[String]): Unit = {
    val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
    val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
    val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
    
    val charSet = ('a' to 'z').toVector
    val num = 5
    
    for(tmp <- List(hash1, hash2, hash3)){
      println(tmp)
      crack(tmp, charSet, num) match{
        case Some(s) => println(s"String: $s\n")
        case None => println("Failed\n")
      }
    }
  }
  
  def crack(hash: String, charSet: Vector[Char], num: Int): Option[String] = {
    val perms = charSet
      .flatMap(c => Vector.fill(num)(c)).combinations(num)  //Generate distinct sets of letters
      .to(ParVector)                                        //Convert to ParVector
      .flatMap(_.permutations.map(_.mkString))              //Finish generating candidates
    
    perms.find(str => getHash(str).equalsIgnoreCase(hash))  //Search for a matching string
  }
  
  def getHash(str: String): String = {
    val digester = MessageDigest.getInstance("SHA-256")
    digester.digest(str.getBytes("UTF-8")).map("%02x".format(_)).mkString
  }
}

An unfortunate side-effect of jumping straight into a ParVector, though, is that the entire list of candidate strings must be computed before attempting to find a match. This means that even modestly large charsets and/or strings can make the memory usage and runtime blow up.

To solve that issue, this next example implements lazy lists. A lazy list is evaluated as needed, meaning you can generate the list of candidates as you check them. In order to still take advantage of parallel processing, this code takes fixed-size chunks off the front of the LazyList and converts them to ParVectors, repeating until either a match is found or the LazyList is empty.

Notice that def is used in place of val when working with the list of candidates. This is because val holds onto the head, which means it would fill up memory over time with the backlog of candidates already checked. Using def lets the program discard candidates after they are checked.

import java.security.MessageDigest

import scala.annotation.tailrec
import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
  def main(args: Array[String]): Unit = {
    val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
    val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
    val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
    
    val charSet = ('a' to 'z').toVector
    val len = 5
    val num = 1000000
    
    for(tmp <- List(hash1, hash2, hash3)){
      println(tmp)
      crackLazy(tmp, charSet, len, num) match{
        case Some(s) => println(s"String: $s\n")
        case None => println("Failed\n")
      }
    }
  }
  
  def crackLazy(hash: String, charSet: Vector[Char], len: Int, num: Int): Option[String] = {
    @tailrec
    def getMatch(lst: LazyList[String]): Option[String] = {
      def hit = lst.take(num).to(ParVector).find(str => getHash(str).equalsIgnoreCase(hash))
      def nxt = lst.drop(num)
      hit match{
        case Some(str) => Some(str)
        case None if nxt.nonEmpty => getMatch(nxt)
        case None => None
      }
    }
    
    def perms = charSet
      .flatMap(Vector.fill(len)(_))
      .combinations(len)
      .flatMap(_.permutations.map(_.mkString)).to(LazyList)
    
    getMatch(perms)
  }
  
  def getHash(str: String): String = {
    val digester = MessageDigest.getInstance("SHA-256")
    digester.digest(str.getBytes("UTF-8")).map("%02x".format(_)).mkString
  }
}

As a final example, we can clean this code up with some method chaining and currying to get this:

import java.security.MessageDigest

import scala.collection.parallel.immutable.ParVector

object EncryptionCracker {
  def main(args: Array[String]): Unit = {
    val hash1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad"
    val hash2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"
    val hash3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
    
    val cracker: String => Option[String] = crackLazy('a' to 'z', 5, 1000000)
    
    for(tmp <- Seq(hash2, hash1, hash3)){
      println(s"$tmp")
      cracker(tmp) match{
        case Some(s) => println(s"String: $s\n")
        case None => println("Failed\n")
      }
    }
  }
  
  def getHash(str: String): String = MessageDigest
    .getInstance("SHA-256")
    .digest(str.getBytes("UTF-8"))
    .map("%02x".format(_)).mkString
  
  def crackLazy(charSet: Seq[Char], len: Int, num: Int)(hash: String): Option[String] = charSet
    .flatMap(Vector.fill(len)(_))                           //Duplicate characters so they can be used any number of times
    .combinations(len)                                      //Generate distinct sets of characters
    .flatMap(_.permutations.map(_.mkString))                //Generate all permutations for each character set
    .grouped(num)                                           //Partition into bite-size chunks
    .map(_.to(ParVector).find(str => getHash(str) == hash)) //Convert each chunk into a ParVector and search it
    .collectFirst{case Some(res) => res}                    //Get the first hit if one is found
}
Output:
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
String: zyzzx

3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
String: apple

74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
String: mmmmm

Sidef

Translation of: Perl
func invert_sha256(hash) {

    var letters = @('a'..'z')

    var job = func (prefix, hash) {
        variations_with_repetition(letters, 4, {|*a|
            var s = join('', prefix, a...)
            return s if (s.sha256 == hash)
        })
        return nil
    }

    letters.map {|prefix|
        job.ffork(prefix, hash)
    }.each {|f|
        with (f.wait) { return _ }
    }
}

var tests = %w(
  1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad
  3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
  74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
)

tests.each {|t|
    var phrase = invert_sha256(t)
    say "#{t} : #{phrase}"
}
Output:
1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad : zyzzx
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b : apple
74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f : mmmmm

Swift

import Foundation
import CryptoKit

extension String {
    func hexdata() -> Data {
        Data(stride(from: 0, to: count, by: 2).map {
            let a = index(startIndex, offsetBy: $0)
            let b = index(after: a)
            return UInt8(self[a ... b], radix: 16)!
        })
    }
}

DispatchQueue.concurrentPerform(iterations: 26) { (a) in
    let goal1 = "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad".hexdata()
    let goal2 = "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b".hexdata()
    let goal3 = "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f".hexdata()
    var letters: [UInt8] = [(UInt8)(a + 97), 0, 0, 0, 0]
    for b: UInt8 in 97...122 {
        letters[1] = b
        for c: UInt8 in 97...122 {
            letters[2] = c
            for d: UInt8 in 97...122 {
                letters[3] = d
                for e: UInt8 in 97...122 {
                    letters[4] = e
                    let digest = SHA256.hash(data: letters)
                    if digest == goal1 || digest == goal2 || digest == goal3 {
                        let password = String(bytes: letters, encoding: .ascii)!
                        let hexhash = digest.map { String(format: "%02x", $0) }.joined()
                        print("\(password) => \(hexhash)")
                    }
                }
            }
        }
    }
}

Visual Basic .NET

Translation of: C#
Imports System.Text

Module Module1

    Function Matches(a As Byte(), b As Byte()) As Boolean
        For i = 0 To 31
            If a(i) <> b(i) Then
                Return False
            End If
        Next
        Return True
    End Function

    Function StringHashToByteArray(s As String) As Byte()
        Return Enumerable.Range(0, s.Length / 2).Select(Function(i) CType(Convert.ToInt16(s.Substring(i * 2, 2), 16), Byte)).ToArray
    End Function

    Sub Main()
        Dim h1 = StringHashToByteArray("1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad")
        Dim h2 = StringHashToByteArray("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b")
        Dim h3 = StringHashToByteArray("74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f")

        Parallel.For(0, 26, Sub(a As Integer)
                                Dim sha = Security.Cryptography.SHA256.Create()
                                Dim password(4) As Byte
                                Dim hash As Byte()

                                password(0) = 97 + a

                                password(1) = 97
                                While password(1) < 123
                                    password(2) = 97
                                    While password(2) < 123
                                        password(3) = 97
                                        While password(3) < 123
                                            password(4) = 97
                                            While password(4) < 123
                                                hash = sha.ComputeHash(password)
                                                If Matches(h1, hash) OrElse Matches(h2, hash) OrElse Matches(h3, hash) Then
                                                    Console.WriteLine(Encoding.ASCII.GetString(password) + " => " + BitConverter.ToString(hash).ToLower().Replace("-", ""))
                                                End If
                                                password(4) += 1
                                            End While
                                            password(3) += 1
                                        End While
                                        password(2) += 1
                                    End While
                                    password(1) += 1
                                End While
                            End Sub)
    End Sub

End Module
Output:
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

Wren

Library: Wren-crypto
Library: Wren-fmt

Wren supports concurrency by way of co-operatively scheduled fibers and, as required by the task description, the work has been divided up between 26 fibers with each fiber taking a different initial letter.

However, from an execution speed viewpoint, there is no point in doing so because Wren's VM is single threaded and can only run one fiber at a time. As it takes around 50 seconds on my machine to process a single initial letter (456,976 calls to sha256) this means that an overall runtime of about 22 minutes is needed to find the passwords corresponding to the 3 hashes.

Currently, parallel calculations are impossible in Wren-cli. However, if Wren is being embedded, it might be possible for a suitable host to run several Wren VM's in parallel and divide a task up between them to improve execution time.

import "./crypto" for Sha256

var hashes = [
    "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad",
    "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
    "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f"
]

var findHash = Fn.new { |i|
    var bytes = List.filled(5, 0)
    var r = 97..122
    bytes[0] = i
    for (j in r) {
        bytes[1] = j
        for (k in r) {
            bytes[2] = k
            for (l in r) {
                bytes[3] = l
                for (m in r) {
                    bytes[4] = m                    
                    var d = Sha256.digest(bytes)
                    for (hash in hashes) {
                        if (hash == d) {
                            var s = bytes.map { |b| String.fromByte(b) }.join()
                            System.print("%(s) => %(d)")
                            hashes.remove(hash)
                            if (hashes.count == 0) return
                        }
                    }
                }
            }
        }
    }
}

for (i in 0..25) {
    var fib = Fiber.new(findHash)
    fib.call(97+i)
}
Output:
apple => 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
mmmmm => 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
zyzzx => 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

zkl

The built in thread message passing object uses the OS to do the heavy lifting and, as a result, isn't suited to high through put (ie passing passwords to cracking threads, equally distributing passwords to each cracking thread). Instead, each thread gets a range of passwords to crack and use signals to coordinate. Way more code with the drawback that one thread may have to do all the work.

This was run on a Intel i7 4 core 8 thread Linux box.

Uses the message hashing extension library (DLL).

Translation of: C#
var [const] MsgHash=Import.lib("zklMsgHash");
var [const] gotEm=Atomic.Int();	// global signal for all threads

const THREADS=9,   // how we will split task, THREADS<=26
      CHR_a="a".toAsc();

fcn crack(c,n,hashes){	// thread
   sha256:=MsgHash.SHA256; // the SHA-256 hash method, byte bucket
   bytes,hash := Data(),Data().howza(0); // byte buckets to reduce garbage production
   firstLtrs:=(c+CHR_a).walker(n);
   ltrs:=CHR_a.walker;	// iterator starting at 97/"a"
   foreach a,b,c,d,e in (firstLtrs,ltrs(26),ltrs(26),ltrs(26),ltrs(26)){ 
      if(not hashes2go) return(); // all cracked, stop, not really needed
      bytes.clear(a,b,c,d,e);     // recycle Data, faster than creating Strings
      sha256(bytes,1,hash);	  // put hash in hash
      if(hashes.holds(hash)){
         println(bytes.text," --> ",hash.pump(String,"%02x".fmt));
	 hashes2go.dec();	// I cracked one, let mom thread know
      }
   }
}
hashes:=T("3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
          "74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f",
	  "1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad");
// convert hex strings to binary; cuts down conversions during crack
fcn hex2binary(s){ s.pump(Data,Void.Read,fcn(a,b){ (a+b).toInt(16) }) }
hashes:=hashes.apply(hex2binary);

hashes2go.set(hashes.len());	// number of codes to crack
num,xtra := 26/THREADS, 26%THREADS; // try for the most even spread over threads
s:=0; do(THREADS){  // start threads
   n:=num + ((xtra-=1)>=0); 
   crack.launch(s.toInt(),n,hashes); 
   s+=n;
}
hashes2go.waitFor(0);	// wait until all cracked, just exit, OS kills threads
mmmmm --> 74e1bb62f8dabb8125a58852b63bdf6eaef667cb56ac7f7cdba6d7305c50a22f
apple --> 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
zyzzx --> 1115dd800feaacefdf481f1f9070374a2a81e27880f187396db67958b207cbad

real	0m3.261s
user	0m22.160s
sys	0m0.140s