Skip to content

Instantly share code, notes, and snippets.

@legionus
Last active November 13, 2019 14:17
Show Gist options
  • Save legionus/272b7d027a36c6c5912bdef945dd0da4 to your computer and use it in GitHub Desktop.
Save legionus/272b7d027a36c6c5912bdef945dd0da4 to your computer and use it in GitHub Desktop.
#!/bin/bash -u
# 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
odbash()
{
local c x
while IFS= read -r -n 1 -d '' c; do
printf -v x "%d" "'$c"
printf '%4d' $(( $x & 0xff ))
done
printf '\n'
}
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} ))
}
rotright()
{
eval $1=$(( (($2 >> $3) | ($2 << (32 - $3))) & 0xFFFFFFFF ))
}
ch()
{
declare -i a=$2 b=$3 c=$4 nota
not32 nota $2
eval $1=$(( ($a & $b) ^ ($nota & $c) ))
}
maj()
{
declare -i a=$2 b=$3 c=$4
eval $1=$(( ($a & $b) ^ ($a & $c) ^ ($b & $c) ))
}
ep0()
{
declare -i a b c
rotright a $2 2
rotright b $2 13
rotright c $2 22
eval $1=$(( $a ^ $b ^ $c ))
}
ep1()
{
declare -i a b c
rotright a $2 6
rotright b $2 11
rotright c $2 25
eval $1=$(( $a ^ $b ^ $c ))
}
sig0()
{
declare -i a b
rotright a $2 7
rotright b $2 18
eval $1=$(( $a ^ $b ^ ($2 >> 3) ))
}
sig1()
{
declare -i a b
rotright a $2 17
rotright b $2 19
eval $1=$(( $a ^ $b ^ ($2 >> 10) ))
}
b32()
{
eval $1=$(( $2 & 0xFFFFFFFF ))
}
not32()
{
declare -i a
b32 a $(( ~$2 ))
eval $1=$a
}
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
sig1 x1 ${m[$(($i - 2))]}
sig0 x2 ${m[$(($i - 15))]}
b32 m[$i] $(( $x1 + ${m[$(($i - 7))]} + $x2 + ${m[$(($i - 16))]} ))
done
declare -i a=${state[0]}
declare -i b=${state[1]}
declare -i c=${state[2]}
declare -i d=${state[3]}
declare -i e=${state[4]}
declare -i f=${state[5]}
declare -i g=${state[6]}
declare -i h=${state[7]}
for (( i=0; i < 64; i++ )) do
ep1 x1 $e
ch x2 $e $f $g
b32 t1 $(( $h + $x1 + $x2 + ${k[$i]} + ${m[$i]} ))
ep0 x1 $a
maj x2 $a $b $c
b32 t2 $(( $x1 + $x2 ))
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 line; do
for byte in $line; do
data[$datalen]=$byte
datalen=$(( $datalen + 1 ))
if [ $datalen -eq 64 ]; then
sha256_transform
dbl_int_add 512
datalen=0
fi
done
done < <(odbash)
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