#!/bin/bash set -e die() { echo "$@" >&2 exit 1 } if [[ -z $1 ]] then die "Usage: $0 private_rsa_key" fi sshkey=$(< $1) if [[ $sshkey != "-----BEGIN RSA PRIVATE KEY-----"* ]] then die "This does not appear to be an RSA private key" fi if [[ $sshkey == *ENCRYPTED* ]] then echo "Key is encrypted, using openssl to decrypt" sshkey=$(openssl rsa <<< "$sshkey") fi base64key=$(sed '1d; $d;' <<< "$sshkey") #the base64 data decdump=$(base64 -d <<< "$base64key" | od -t u1 | sed -e 's/^[^ ]*//') decbytes=$(echo $decdump | tr ' ' '\n') #decimal bytes, one on each line readInt() { read byte # echo "read type $byte" >&2 (( (byte & 0x1F) != 2 )) && \ die "$byte doesn't encode an integer :O" length=$(readLength) # echo "read length $length" >&2 exp="0" for((i=0; i&2 exp="($exp)*256+$b" done bc <<< "$exp" | tr -d '\n\\ ' } readLength() { local bytes length n i read bytes n=$((bytes&0x7F)) if (( bytes & 0x80 )) then length=0 for((i=0; i /dev/null # the sequence length unknown=$(readInt) n=$(readInt) #modulo e=$(readInt) #public exponent d=$(readInt) #private exponent p=$(readInt) #first prime q=$(readInt) #second prime exp1=$(readInt) # d mod p-1 exp2=$(readInt) # d mod q-1 c=$(readInt) || c=0 # p^1 mod q length=$(bc -l <<< "scale=20; v=l($n)/l(2); scale=1; v/1") echo "# Key is $length bits long" echo "# Input for bc:" echo "n=$n" echo "p=$p" echo "q=$q" echo "e=$e" echo "d=$d" echo "c=$c" echo "exp1=$exp1" echo "exp2=$exp2" echo "scale=0" echo "define pmod(b,e,m) { if(e == 0 ) return 1; if(e == 1) return b%m; rest=pmod(b^2%m,e/2,m); if((e%2) == 1) return (b*rest)%m else return rest; }" echo "define encrypt(message) { return pmod(message, e, n); }" echo "define decrypt(message) { return pmod(message, d, n); }" echo "define verify() { return n == p*q && (d*e)%((p-1)*(q-1)) == 1 && exp1 == d % (p-1) && exp2 == d % (q-1) && (c*q)%p == 1; }" echo "# End bc" ) <<< "$decbytes"