Skip to content

Instantly share code, notes, and snippets.

@dmage
Created July 29, 2018 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmage/e70fcccc852441a4b1a7d44da3f876f0 to your computer and use it in GitHub Desktop.
Save dmage/e70fcccc852441a4b1a7d44da3f876f0 to your computer and use it in GitHub Desktop.
#!/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