Created
July 29, 2018 16:00
-
-
Save dmage/e70fcccc852441a4b1a7d44da3f876f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eu | |
# Released into the Public Domain. | |
# | |
# Original implementation in C by Brad Conte (brad@bradconte.com) <https://github.com/B-Con/crypto-algorithms> | |
# Ported to Bash (lol) by Josh Junon (josh@junon.me) <https://github.com/qix-> | |
# | |
# Original gist is https://gist.github.com/Qix-/affef08b50686e54e1f2ca18f97a6ff7 | |
# Removed external utilities. | |
# | |
# Yes, it's absolutely as slow as it looks. | |
# | |
export LANG=C | |
od() | |
{ | |
local c x | |
while IFS= read -r -n 1 -d "" c; do | |
printf -v x "%d" "'$c" | |
printf "%d\n" $(($x & 0xff)) | |
done | |
} | |
sha256() | |
{ | |
declare -a k data rhash bitlen state | |
declare -i datalen=0 | |
k=( \ | |
$((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)) \ | |
) | |
state=( \ | |
$((0x6a09e667)) $((0xbb67ae85)) $((0x3c6ef372)) $((0xa54ff53a)) $((0x510e527f)) $((0x9b05688c)) $((0x1f83d9ab)) $((0x5be0cd19)) \ | |
) | |
bitlen=( 0 0 ) | |
dbl_int_add() | |
{ | |
if [ ${bitlen[0]} -gt $(( 0xffffffff - ${1} )) ]; then | |
bitlen[1]=$(( ${bitlen[1]} + 1 )) | |
fi | |
bitlen[0]=$(( ${bitlen[0]} + ${1} )) | |
} | |
genexpr_b32() { | |
eval $1='"($2 & 0xffffffff)"' | |
} | |
genexpr_not32() | |
{ | |
genexpr_b32 $1 "(~$2)" | |
} | |
genexpr_rotr() { | |
genexpr_b32 $1 "($2 >> $3) | ($2 << $((32 - $3)))" | |
} | |
genexpr_ep0() { | |
local a b c | |
genexpr_rotr a "$2" 2 | |
genexpr_rotr b "$2" 13 | |
genexpr_rotr c "$2" 22 | |
eval $1='"($a ^ $b ^ $c)"' | |
} | |
genexpr_ep1() | |
{ | |
local a b c | |
genexpr_rotr a "$2" 6 | |
genexpr_rotr b "$2" 11 | |
genexpr_rotr c "$2" 25 | |
eval $1='"($a ^ $b ^ $c)"' | |
} | |
genexpr_sig0() | |
{ | |
local a b | |
genexpr_rotr a "$2" 7 | |
genexpr_rotr b "$2" 18 | |
eval $1='"($a ^ $b ^ ($2 >> 3))"' | |
} | |
genexpr_sig1() | |
{ | |
local a b | |
genexpr_rotr a "$2" 17 | |
genexpr_rotr b "$2" 19 | |
eval $1='"($a ^ $b ^ ($2 >> 10))"' | |
} | |
genexpr_ch() | |
{ | |
local not_2 | |
genexpr_not32 not_2 "$2" | |
eval $1='"(($2 & $3) ^ ($not_2 & $4))"' | |
} | |
genexpr_maj() { | |
eval $1='"(($2 & $3) ^ ($2 & $4) ^ ($3 & $4))"' | |
} | |
rotright() | |
{ | |
eval $1=$(( (($2 >> $3) | ($2 << (32 - $3))) & 0xFFFFFFFF )) | |
} | |
b32() | |
{ | |
eval $1=$(( $2 & 0xFFFFFFFF )) | |
} | |
not32() | |
{ | |
declare -i a | |
b32 a $(( ~$2 )) | |
eval $1=$a | |
} | |
gen_sig1sig0() { | |
local x1 x2 x | |
genexpr_sig1 x1 '$2' | |
genexpr_sig0 x2 '$3' | |
genexpr_b32 x "($x1 + $x2)" | |
eval "sig1sig0() { eval \$1='\$(($x))'; }" | |
} | |
gen_sig1sig0 | |
gen_m16() { | |
local t2='$2' t7='$3' t15='$4' t16='$5' r | |
genexpr_sig1 t2 "$t2" | |
genexpr_sig0 t15 "$t15" | |
genexpr_b32 r "($t2 + $t7 + $t15 + $t16)" | |
eval "m16() { eval \$1='\$(($r))'; }" | |
} | |
gen_m16 | |
gen_t2() { | |
local x1 x2 t2 | |
genexpr_ep0 x1 '$2' | |
genexpr_maj x2 '$2' '$3' '$4' | |
genexpr_b32 t2 "($x1 + $x2)" | |
eval "t2() { eval \$1='\$(($t2))'; }" | |
} | |
gen_t2 | |
gen_t1part() { | |
local x1 x2 t1part | |
genexpr_ep1 x1 '$2' | |
genexpr_ch x2 '$2' '$3' '$4' | |
t1part="$x1 + $x2" | |
eval "t1part() { eval \$1='\$(($t1part))'; }" | |
} | |
gen_t1part | |
sha256_transform() | |
{ | |
declare -a m | |
declare -i t1 t2 x1 x2 | |
for (( i=0; i < 16; i++ )) do | |
declare -i j=$(($i * 4)) | |
b32 m[$i] $(( (${data[$j]} << 24) | (${data[$(($j + 1))]} << 16) | (${data[$(($j + 2))]} << 8) | ${data[$(($j + 3))]} )) | |
done | |
for (( i=16; i < 64; i++ )) do | |
m16 m[$i] ${m[i-2]} ${m[i-7]} ${m[i-15]} ${m[i-16]} | |
done | |
declare -i \ | |
a=${state[0]} \ | |
b=${state[1]} \ | |
c=${state[2]} \ | |
d=${state[3]} \ | |
e=${state[4]} \ | |
f=${state[5]} \ | |
g=${state[6]} \ | |
h=${state[7]} | |
for (( i=0; i < 64; i++ )) do | |
t1part t1 $e $f $g | |
t1=$(( $h + $t1 + ${k[$i]} + ${m[$i]} )) | |
t2 t2 $a $b $c | |
h=$g | |
g=$f | |
f=$e | |
b32 e $(( $d + $t1 )) | |
d=$c | |
c=$b | |
b=$a | |
b32 a $(( $t1 + $t2 )) | |
done | |
b32 state[0] $(( ${state[0]} + $a )) | |
b32 state[1] $(( ${state[1]} + $b )) | |
b32 state[2] $(( ${state[2]} + $c )) | |
b32 state[3] $(( ${state[3]} + $d )) | |
b32 state[4] $(( ${state[4]} + $e )) | |
b32 state[5] $(( ${state[5]} + $f )) | |
b32 state[6] $(( ${state[6]} + $g )) | |
b32 state[7] $(( ${state[7]} + $h )) | |
} | |
local line byte | |
while read -r byte; do | |
data[$datalen]=$byte | |
datalen=$(( $datalen + 1 )) | |
if [ $datalen -eq 64 ]; then | |
sha256_transform | |
dbl_int_add 512 | |
datalen=0 | |
fi | |
done < <(od) | |
declare -i i=$datalen | |
if [ $datalen -lt 56 ]; then | |
data[$i]=$(( 0x80 )) | |
i=$(( $i + 1 )) | |
while [ $i -lt 56 ]; do | |
data[$i]=0 | |
i=$(( $i + 1 )) | |
done | |
else | |
data[$i]=$(( 0x80 )) | |
i=$(( $i + 1 )) | |
while [ $i -lt 64 ]; do | |
data[$i]=0 | |
i=$(( $i + 1 )) | |
done | |
sha256_transform | |
for (( j=0; j < 56; j++ )) do | |
data[$j]=0 | |
done | |
fi | |
dbl_int_add $(( $datalen * 8 )) | |
data[63]=$(( ${bitlen[0]} & 0xFF )) | |
data[62]=$(( (${bitlen[0]} >> 8) & 0xFF )) | |
data[61]=$(( (${bitlen[0]} >> 16) & 0xFF )) | |
data[60]=$(( (${bitlen[0]} >> 24) & 0xFF )) | |
data[59]=$(( ${bitlen[1]} & 0xFF )) | |
data[58]=$(( (${bitlen[1]} >> 8) & 0xFF )) | |
data[57]=$(( (${bitlen[1]} >> 16) & 0xFF )) | |
data[56]=$(( (${bitlen[1]} >> 24) & 0xFF )) | |
sha256_transform | |
for (( j=0; j < 4; j++ )) do | |
rhash[$j]=$(( (${state[0]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 4 ))]=$(( (${state[1]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 8 ))]=$(( (${state[2]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 12 ))]=$(( (${state[3]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 16 ))]=$(( (${state[4]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 20 ))]=$(( (${state[5]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 24 ))]=$(( (${state[6]} >> (24 - $j * 8)) & 0xff )) | |
rhash[$(( $j + 28 ))]=$(( (${state[7]} >> (24 - $j * 8)) & 0xff )) | |
done | |
printf "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n" ${rhash[@]} | |
} | |
sha256 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment