SHA-256: Difference between revisions

11,991 bytes added ,  3 months ago
m
(Adds slope example)
m (→‎{{header|Wren}}: Minor tidy)
 
(13 intermediate revisions by 7 users not shown)
Line 910:
<pre>764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf</pre>
 
=={{header|BaConBASIC}}==
==={{header|BaCon}}===
<syntaxhighlight lang="qbasic">PRAGMA INCLUDE <openssl/sha.h>
PRAGMA LDFLAGS -lcrypto
Line 936 ⟶ 937:
</pre>
 
==={{header|BBC BASIC}}===
====Library====
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> PRINT FNsha256("Rosetta code")
Line 964 ⟶ 965:
NEXT
= hash$</syntaxhighlight>
{{out}}
'''Output:'''
<pre>
764FAF5C61AC315F1497F9DFA542713965B785E5CC2F707D6468D7D1124CDFCF
</pre>
 
====Native====
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> REM SHA-256 calculation by Richard Russell in BBC BASIC for Windows
Line 1,095 ⟶ 1,096:
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
= n#</syntaxhighlight>
{{out}}
'''Output:'''
<pre>
764FAF5C 61AC315F 1497F9DF A5427139 65B785E5 CC2F707D 6468D7D1 124CDFCF
Line 1,168 ⟶ 1,169:
}
</syntaxhighlight>
 
===Implementation===
<syntaxhighlight lang="c++">
#include <bit>
#include <cstdint>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
 
class SHA256 {
public:
std::string message_digest(const std::string& message) {
std::vector<int64_t> hash = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
 
const std::vector<int8_t> bytes = add_padding(message);
for ( uint64_t i = 0; i < bytes.size() / BLOCK_LENGTH; ++i ) {
std::vector<int32_t> words(BLOCK_LENGTH, 0);
for ( int32_t j = 0; j < BLOCK_LENGTH; ++j ) {
words[j / 4] |= ( bytes[i * BLOCK_LENGTH + j] & 0xff ) << ( ( 3 - j % 4 ) * 8 );
}
for ( int32_t j = 16; j < BLOCK_LENGTH; j++ ) {
words[j] = sigma(3, words[j - 2]) + words[j - 7] + sigma(2, words[j - 15]) + words[j - 16];
}
 
int32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3],
e = hash[4], f = hash[5], g = hash[6], h = hash[7];
 
for ( int32_t j = 0; j < BLOCK_LENGTH; ++j ) {
int32_t t = h + sigma(1, e) + ch(e, f, g) + kk[j] + words[j];
int32_t tt = sigma(0, a) + maj(a, b, c);
h = g; g = f; f = e;
e = d + t;
d = c; c = b; b = a;
a = t + tt;
}
 
hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d;
hash[4] += e; hash[5] += f; hash[6] += g; hash[7] += h;
}
 
std::stringstream stream;
for ( int32_t i = 0; i < BLOCK_LENGTH; ++i ) {
int8_t byte_value = static_cast<int8_t>(hash[i / 8] >> ( 7 - i % 8 ) * 4);
stream << std::hex << ( byte_value & 0xf );
}
return stream.str();
}
 
private:
std::vector<int8_t> add_padding(const std::string& message) {
std::vector<int8_t> bytes(message.begin(), message.end());
bytes.emplace_back(static_cast<uint8_t>(0x80));
 
uint32_t padding = BLOCK_LENGTH - ( bytes.size() % BLOCK_LENGTH );
if ( padding < 8 ) {
padding += BLOCK_LENGTH;
}
bytes.resize(bytes.size() + padding - 8, static_cast<int8_t>(0x0));
 
const uint64_t bit_length = 8 * message.length();
for ( int32_t i = 7; i >= 0; --i ) {
bytes.emplace_back(static_cast<int8_t>(bit_length >> ( 8 * i )));
}
return bytes;
}
 
int32_t sigma(const uint32_t& group, const uint32_t& x) {
int32_t result;
switch ( group ) {
case 0 : result = std::rotr(x, 2) ^ std::rotr(x, 13) ^ std::rotr(x, 22); break;
case 1 : result = std::rotr(x, 6) ^ std::rotr(x, 11) ^ std::rotr(x, 25); break;
case 2 : result = std::rotr(x, 7) ^ std::rotr(x, 18) ^ ( x >> 3 ); break;
case 3 : result = std::rotr(x, 17) ^ std::rotr(x, 19) ^ ( x >> 10 ); break;
default : throw std::invalid_argument("Unexpected argument for sigma: " + std::to_string(group));
}
return result;
}
 
int32_t ch(const int32_t& x, const int32_t y, const int32_t z) {
return ( x & y ) ^ ( ~x & z );
}
 
int32_t maj(const int32_t& x, const int32_t y, const int32_t z) {
return ( x & y ) ^ ( x & z ) ^ ( y & z );
}
 
const std::vector<int64_t> kk = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
 
const int32_t BLOCK_LENGTH = 64;
};
 
int main() {
SHA256 sha256;
std::cout << sha256.message_digest("Rosetta code") << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf
</pre>
 
=={{header|Caché ObjectScript}}==
Line 2,177 ⟶ 2,289:
=={{header|Java}}==
The solution to this task would be a small modification to [[MD5#Java|MD5]] (replacing "MD5" with "SHA-256" as noted [http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest here]).
 
===Implementation===
<syntaxhighlight lang = "java">
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
 
public final class SHA256Task {
 
public static void main(String[] args) {
System.out.println(SHA256.messageDigest("Rosetta code"));
}
 
}
 
final class SHA256 {
public static String messageDigest(String message) {
int[] hash = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
final byte[] bytes = addPadding(message);
for ( int i = 0; i < bytes.length / BLOCK_LENGTH; i++ ) {
int[] words = new int[BLOCK_LENGTH];
for ( int j = 0; j < BLOCK_LENGTH; j++ ) {
words[j / 4] |= ( bytes[i * BLOCK_LENGTH + j] & 0xff ) << ( ( 3 - j % 4 ) * 8 );
}
for ( int j = 16; j < BLOCK_LENGTH; j++ ) {
words[j] = sigma(3, words[j - 2]) + words[j - 7] + sigma(2, words[j - 15]) + words[j - 16];
}
int a = hash[0], b = hash[1], c = hash[2], d = hash[3],
e = hash[4], f = hash[5], g = hash[6], h = hash[7];
for ( int j = 0; j < BLOCK_LENGTH; j++ ) {
int t = h + sigma(1, e) + ch(e, f, g) + kk[j] + words[j];
int tt = sigma(0, a) + maj(a, b, c);
h = g; g = f; f = e;
e = d + t;
d = c; c = b; b = a;
a = t + tt;
}
 
hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d;
hash[4] += e; hash[5] += f; hash[6] += g; hash[7] += h;
}
StringBuilder result = new StringBuilder();
for ( int i = 0; i < BLOCK_LENGTH; i++ ) {
result.append(String.format("%1x", ( hash[i / 8] >>> ( 7 - i % 8 ) * 4 ) & 0xf ));
}
return result.toString();
}
private static byte[] addPadding(String message) {
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
bytes = Arrays.copyOf(bytes, bytes.length + 1);
bytes[bytes.length - 1] = (byte) 0x80;
int padding = BLOCK_LENGTH - ( bytes.length % BLOCK_LENGTH );
if ( padding < 8 ) {
padding += BLOCK_LENGTH;
}
bytes = Arrays.copyOf(bytes, bytes.length + padding);
final long bitLength = message.length() * 8;
for ( int i = 0; i < 8; i++ ) {
bytes[bytes.length - 1 - i] = (byte) ( bitLength >>> ( 8 * i ) );
}
return bytes;
}
private static int sigma(int group, int x) {
return switch ( group ) {
case 0 -> Integer.rotateRight(x, 2) ^ Integer.rotateRight(x, 13) ^ Integer.rotateRight(x, 22);
case 1 -> Integer.rotateRight(x, 6) ^ Integer.rotateRight(x, 11) ^ Integer.rotateRight(x, 25);
case 2 -> Integer.rotateRight(x, 7) ^ Integer.rotateRight(x, 18) ^ ( x >>> 3 );
case 3 -> Integer.rotateRight(x, 17) ^ Integer.rotateRight(x, 19) ^ ( x >>> 10 );
default -> throw new AssertionError("Unexpected argument for sigma: " + group);
};
}
private static int ch(int x, int y, int z) {
return ( x & y ) ^ ( ~x & z );
}
 
private static int maj(int x, int y, int z) {
return ( x & y ) ^ ( x & z ) ^ ( y & z );
}
private static final int[] kk = new int[] {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
private static final int BLOCK_LENGTH = 64;
}
</syntaxhighlight>
{{ out }}
<pre>
764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf
</pre>
 
=={{header|JavaScript}}==
Line 3,066 ⟶ 3,285:
<syntaxhighlight lang="raku" line>say sha256 "Rosetta code";
 
our proto sha256($) returns blob8 {*}
sub init(&f) {
 
map { my $f = $^p.&f; (($f - $f.Int)*2**32).Int },
multi sha256(Str $str) { samewith $str.encode }
state @ = grep *.is-prime, 2 .. *;
multi sha256(blob8 $data) {
}
sub rotr { $^a +> $^b +| $a +< (32 - $b) }
sub infix:<m+>init { ($^aInf +.grep(&is-prime).map: { (($^b)_ %- .Int)*2**32).Int } o &^f }
sub rotr($n, $b) Ch { $n^x +>& $b^y +|^ +^$nx +< (32 -& $b)^z }
sub Maj { $^x +& $^y +^ $x +& $^z +^ $y +& $z }
sub Σ0 { rotr($^x, 2) +^ rotr($x, 13) +^ rotr($x, 22) }
proto sha256($) returns Blob {*}
sub Σ1 { rotr($^x, 6) +^ rotr($x, 11) +^ rotr($x, 25) }
multi sha256(Str $str where all($str.ords) < 128) {
sub σ0 { rotr($^x, 7) +^ rotr($x, 18) +^ $x +> 3 }
sha256 $str.encode: 'ascii'
sub σ1 { rotr($^x, 17) +^ rotr($x, 19) +^ $x +> 10 }
}
 
multi sha256(Blob $data) {
return blob8.new:
constant K = init(* **(1/3))[^64];
map |*.polymod(256 xx 3).reverse,
my @b = flat $data.list, 0x80;
|reduce -> $H, $block {
push @b, 0 until (8 * @b - 448) %% 512;
blob32.new: $H[] Z+
push @b, slip reverse (8 * $data).polymod(256 xx 7);
reduce -> $h, $j {
my @word = :256[@b.shift xx 4] xx @b/4;
my uint32 ($T1, $T2) =
$h[7] + Σ1($h[4]) + Ch(|$h[4..6])
my @H = init(&sqrt)[^8];
+ (BEGIN init(* **(1/3))[^64])[$j] +
my @w;
(
loop (my $i = 0; $i < @word; $i += 16) {
(state buf32 $w .= new)[$j] = $j < 16 ?? $block[$j] !!
my @h = @H;
σ0($w[$j-15]) + $w[$j-7] + σ1($w[$j-2]) + $w[$j-16]
for ^64 -> $j {
),
@w[$j] = $j < 16 ?? @word[$j + $i] // 0 !!
Σ0($h[0]) + Maj(|$h[m+0..2]);
blob32.new: $T1 + $T2, rotr(@w|$h[$j-150..2], 7)$h[3] +^ rotr(@w[$j-15]T1, 18) +^ @w|$h[$j-154..6] +> 3,;
}, @w[$j-7]H, |^64;
},
rotr(@w[$j-2], 17) +^ rotr(@w[$j-2], 19) +^ @w[$j-2] +> 10,
(BEGIN init(&sqrt)[^8]),
@w[$j-16];
|blob32.new(
my $ch = @h[4] +& @h[5] +^ +^@h[4] % 2**32 +& @h[6];
blob8.new(
my $maj = @h[0] +& @h[2] +^ @h[0] +& @h[1] +^ @h[1] +& @h[2];
@$data,
my $σ0 = [+^] map { rotr @h[0], $_ }, 2, 13, 22;
0x80,
my $σ1 = [+^] map { rotr @h[4], $_ }, 6, 11, 25;
0 xx (-($data + 1 my $t1 = [m+] @h[7],8) $σ1,mod $ch64), K[$j], @w[$j];
(8*$data).polymod(256 xx 7).reverse
my $t2 = $σ0 m+ $maj;
).rotor(4)
@h = flat $t1 m+ $t2, @h[^3], @h[3] m+ $t1, @h[4..6];
.map: { :256[@$_] }
).rotor(16)
@H [Z[m+]]= @h;
}
return Blob.new: map { |reverse .polymod(256 xx 3) }, @H;
}</syntaxhighlight>
{{out}}
<pre>BufBlob[uint8]:0x<76 4f4F afAF 5c5C 61 acAC 31 5f5F 14 97 f9F9 dfDF a5A5 42 71 39 65 b7B7 85 e5E5 ccCC 2f2F 70 7d7D 64 68 d7D7 d1D1 12 4c4C dfDF cfCF></pre>
 
=== LibraryNative implementation ===
<syntaxhighlight lang="raku" line>use Digest::SHA256::Native;
 
Line 3,144 ⟶ 3,361:
 
=={{header|Rust}}==
 
=== Library ===
<syntaxhighlight lang="rust">use sha2::{Digest, Sha256};
 
Line 3,168 ⟶ 3,387:
println!("{}", hex);
}
</syntaxhighlight>
 
{{out}}
<pre>
764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf
</pre>
 
=== Pure Rust ===
<syntaxhighlight lang="rust">const HASH_VALUES: [u32; 8] = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];
 
const ROUND_CONSTANTS: [u32; 64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
];
 
const INPUT: &str = "Rosetta code";
 
fn main() {
let mut bytes = INPUT.as_bytes().to_vec();
 
let mut hash_values = HASH_VALUES.to_vec();
 
let input_len = bytes.len(); // Bytes
let input_len_byte = (input_len * 8).to_be_bytes(); // Bits
 
let padding = ((64 * ((input_len + 72) / 64)) - input_len) - 9; // Bytes
 
bytes.push(128);
bytes.append(&mut vec![0; padding]);
bytes.extend(input_len_byte);
 
for byte_chunk in bytes.chunks(64) {
let mut working_hash = hash_values.clone();
 
let mut joined_bytes: Vec<u32> = byte_chunk
.chunks(4)
.map(|chunk| u32::from_be_bytes(chunk.try_into().unwrap()))
.collect();
 
joined_bytes.append(&mut vec![0; 48]);
 
// Message loop
 
for i in 16..64 {
let chunk_index_1 = joined_bytes[i - 15];
let chunk_index_2 = joined_bytes[i - 2];
 
let sigma_1 = chunk_index_1.rotate_right(7)
^ chunk_index_1.rotate_right(18)
^ (chunk_index_1 >> 3);
let sigma_2 = chunk_index_2.rotate_right(17)
^ chunk_index_2.rotate_right(19)
^ (chunk_index_2 >> 10);
 
joined_bytes[i] = joined_bytes[i - 16]
.wrapping_add(sigma_1.wrapping_add(joined_bytes[i - 7].wrapping_add(sigma_2)));
}
 
// Compression loop
 
for i in 0..64 {
let sigma_1 = working_hash[4].rotate_right(6)
^ working_hash[4].rotate_right(11)
^ working_hash[4].rotate_right(25);
let choice =
(working_hash[4] & working_hash[5]) ^ ((!working_hash[4]) & working_hash[6]);
let temp_1 = working_hash[7].wrapping_add(sigma_1.wrapping_add(
choice.wrapping_add(ROUND_CONSTANTS[i].wrapping_add(joined_bytes[i])),
));
 
let sigma_0 = working_hash[0].rotate_right(2)
^ working_hash[0].rotate_right(13)
^ working_hash[0].rotate_right(22);
let majority = (working_hash[0] & working_hash[1])
^ (working_hash[0] & working_hash[2])
^ (working_hash[1] & working_hash[2]);
let temp_2 = sigma_0.wrapping_add(majority);
 
working_hash.pop();
working_hash.insert(0, temp_1.wrapping_add(temp_2));
working_hash[4] = working_hash[4].wrapping_add(temp_1);
}
 
hash_values = hash_values
.iter()
.zip(working_hash)
.map(|(hv1, hv2)| hv1.wrapping_add(hv2))
.collect();
}
 
let output: String = hash_values
.iter()
.map(|val| format!("{:08x}", val))
.collect::<Vec<String>>()
.join("");
 
assert_eq!(
output,
"764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf"
);
 
println!("{}", output);
}
</syntaxhighlight>
Line 3,228 ⟶ 3,558:
<pre>764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf</pre>
 
=={{header|VlangTXR}}==
 
<syntaxhighlight lang="vlang">import crypto.sha256
<pre>1> (sha256 "Rosetta code")
#b'764faf5c61ac315f 1497f9dfa5427139 65b785e5cc2f707d 6468d7d1124cdfcf'</pre>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="v (vlang)">import crypto.sha256
 
fn main() {
Line 3,246 ⟶ 3,581:
{{libheader|Wren-crypto}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./crypto" for Sha256
import "./fmt" for Fmt
var strings = [
9,477

edits