SHA-256
Pure Raku
The following implementation takes all data as input. Ideally, input should be given lazily or something.
say sha256 "Rosetta code";
our proto sha256($) returns blob8 {*}
multi sha256(Str $str) { samewith $str.encode }
multi sha256(blob8 $data) {
sub rotr { $^a +> $^b +| $a +< (32 - $b) }
sub init { ^Inf .grep(&is-prime).map: { (($_ - .Int)*2**32).Int } o &^f }
sub Ch { $^x +& $^y +^ +^$x +& $^z }
sub Maj { $^x +& $^y +^ $x +& $^z +^ $y +& $z }
sub Σ0 { rotr($^x, 2) +^ rotr($x, 13) +^ rotr($x, 22) }
sub Σ1 { rotr($^x, 6) +^ rotr($x, 11) +^ rotr($x, 25) }
sub σ0 { rotr($^x, 7) +^ rotr($x, 18) +^ $x +> 3 }
sub σ1 { rotr($^x, 17) +^ rotr($x, 19) +^ $x +> 10 }
return blob8.new:
map |*.polymod(256 xx 3).reverse,
|reduce -> $H, $block {
blob32.new: $H[] Z+
reduce -> $h, $j {
my uint32 ($T1, $T2) =
$h[7] + Σ1($h[4]) + Ch(|$h[4..6])
+ (BEGIN init(* **(1/3))[^64])[$j] +
(
(state buf32 $w .= new)[$j] = $j < 16 ?? $block[$j] !!
σ0($w[$j-15]) + $w[$j-7] + σ1($w[$j-2]) + $w[$j-16]
),
Σ0($h[0]) + Maj(|$h[0..2]);
blob32.new: $T1 + $T2, |$h[0..2], $h[3] + $T1, |$h[4..6];
}, $H, |^64;
},
(BEGIN init(&sqrt)[^8]),
|blob32.new(
blob8.new(
@$data,
0x80,
0 xx (-($data + 1 + 8) mod 64),
(8*$data).polymod(256 xx 7).reverse
).rotor(4)
.map: { :256[@$_] }
).rotor(16)
}
Output:
Blob[uint8]:0x<76 4F AF 5C 61 AC 31 5F 14 97 F9 DF A5 42 71 39 65 B7 85 E5 CC 2F 70 7D 64 68 D7 D1 12 4C DF CF>
Native implementation
use Digest::SHA256::Native;
# If you want a string
say sha256-hex 'Rosetta code';
# If you want a binary Blob
say sha256 'Rosetta code';
Output:
764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf
Blob:0x<76 4F AF 5C 61 AC 31 5F 14 97 F9 DF A5 42 71 39 65 B7 85 E5 CC 2F 70 7D 64 68 D7 D1 12 4C DF CF>
Last updated