#NOEKEON Block Cipher in PERL # #Tom St Denis, tomstdenis@yahoo.com, http://tomstdenis.home.dhs.org # # # Functions you want to call: # # # noekeon_encrypt_ecb(blk, key) # # Encrypts the four 32-bit words in 'blk' under control of the four 32-bit words in 'key' and returns # the ciphertext as four 32-bit words. # # # noekeon_get_decrypt_key(key) # # Converts a key into an decryption key and returns it. # # # noekeon_decrypt_ecb(blk, key) # # Opposite of noekeon_encrypt_ecb(). # # # noekeon_encrypt_cbc(blk, key, iv) # # Encrypts a single block in CBC mode like the ECB routine. It updates the third argument with the new IV and returns # the ciphertext. # # # noekeon_decrypt_cbc(blk, key, iv) # # Opposite of noekeon_encrypt_cbc(). # #rotations sub lrot { return (($_[0] << $_[1]) | ($_[0] >> ((32 - $_[1]) & 31))) % (2**32); } sub rrot { return (($_[0] >> $_[1]) | ($_[0] << ((32 - $_[1]) & 31))) % (2**32); } #find the i'th round constant sub noekeon_RoundCt { my($RC, $i) = (0x80, 0); for ($i = 1; $i <= $_[0]; $i++) { if ($RC & 0x80) { $RC = ($RC << 1) ^ 0x11B; } else { $RC = ($RC << 1); } } return $RC; } #Noekeons Theta sub noekeon_Theta { my($temp) = $_[0] ^ $_[2]; $temp ^= lrot($temp,8) ^ rrot($temp,8); $_[1] ^= $temp; $_[3] ^= $temp; # XOR Key material $_[0] ^= vec($_[4], 0, 32); $_[1] ^= vec($_[4], 1, 32); $_[2] ^= vec($_[4], 2, 32); $_[3] ^= vec($_[4], 3, 32); $temp = $_[1] ^ $_[3]; $temp ^= lrot($temp,8) ^ rrot($temp,8); $_[0] ^= $temp; $_[2] ^= $temp; } sub noekeon_Pi1 { $_[1] = lrot($_[1], 1); $_[2] = lrot($_[2], 5); $_[3] = lrot($_[3], 2); } sub noekeon_Pi2 { $_[1] = rrot($_[1], 1); $_[2] = rrot($_[2], 5); $_[3] = rrot($_[3], 2); } sub noekeon_Gamma { $_[1] ^= ($_[3]|$_[2])^0xFFFFFFFF; $_[0] ^= ($_[2]&$_[1]); my($tmp) = $_[3]; $_[3] = $_[0]; $_[0] = $tmp; $_[2] ^= $_[0] ^ $_[1] ^ $_[3]; $_[1] ^= ($_[3]|$_[2])^0xFFFFFFFF; $_[0] ^= ($_[2]&$_[1]); } #round(a,b,c,d,c1,c2,key) sub noekeon_round { #add constant $_[0] ^= $_[4]; #do theta noekeon_Theta($_[0],$_[1],$_[2],$_[3],$_[6]); $_[0] ^= $_[5]; #pi1 noekeon_Pi1($_[0],$_[1],$_[2],$_[3]); #gamma noekeon_Gamma($_[0],$_[1],$_[2],$_[3]); #pi2 noekeon_Pi2($_[0],$_[1],$_[2],$_[3]); } #noekeon_encrypt_ecb(blk, key) sub noekeon_encrypt_ecb { #grab input my($a) = vec($_[0], 0, 32); my($b) = vec($_[0], 1, 32); my($c) = vec($_[0], 2, 32); my($d) = vec($_[0], 3, 32); #do 16 rounds in forward direction for (my($r) = 0; $r < 16; $r++) { noekeon_round($a,$b,$c,$d,noekeon_RoundCt($r),0,$_[1]); } #do last theta $a ^= noekeon_RoundCt(16); noekeon_Theta($a, $b, $c, $d,$_[1]); my($res) = 0; vec($res, 0, 32) = $a; vec($res, 1, 32) = $b; vec($res, 2, 32) = $c; vec($res, 3, 32) = $d; return $res; } #get a decrypt key sub noekeon_get_decrypt_key { #do theta on key thingy my($a) = vec($_[0], 0, 32); my($b) = vec($_[0], 1, 32); my($c) = vec($_[0], 2, 32); my($d) = vec($_[0], 3, 32); my($e) = 0; for (my($i) = 0; $i < 4; $i++) { vec($e, $i, 32) = 0; } noekeon_Theta($a,$b,$c,$d,$e); my($tkey) = 0; vec($tkey, 0, 32) = $a; vec($tkey, 1, 32) = $b; vec($tkey, 2, 32) = $c; vec($tkey, 3, 32) = $d; return $tkey; } #noekeon_decrypt_ecb(blk, key) sub noekeon_decrypt_ecb { #grab input my($a) = vec($_[0], 0, 32); my($b) = vec($_[0], 1, 32); my($c) = vec($_[0], 2, 32); my($d) = vec($_[0], 3, 32); #do 16 rounds in forward direction for (my($r) = 16; $r > 0; $r--) { noekeon_round($a,$b,$c,$d,0,noekeon_RoundCt($r),$_[1]); } #undo last theta noekeon_Theta($a, $b, $c, $d,$_[1]); $a ^= noekeon_RoundCt(0); my($res) = 0; vec($res, 0, 32) = $a; vec($res, 1, 32) = $b; vec($res, 2, 32) = $c; vec($res, 3, 32) = $d; return $res; } #encode a block in CBC mode #noekeon_encrypt_cbc(blk, key, iv) sub noekeon_encrypt_cbc { for (my($i) = 0; $i < 4; $i++) { vec($_[0], $i, 32) ^= vec($_[2], $i, 32); } my($tmp) = noekeon_encrypt_ecb($_[0], $_[1]); for ($i = 0; $i < 4; $i++) { vec($_[2], $i, 32) = vec($tmp, $i, 32); } return $tmp; } #decode a block in CBC mode #noekeon_decrypt_cbc(blk, key, iv) sub noekeon_decrypt_cbc { my($tmp) = noekeon_decrypt_ecb($_[0], $_[1]); for (my($i) = 0; $i < 4; $i++) { vec($tmp, $i, 32) ^= vec($_[2], $i, 32); vec($_[2], $i, 32) = vec($_[0], $i, 32); } return $tmp; } # # # # ------> DEMO <------- # make up a key, IV and msg $blk1 = $iv = $blk2 = $key = 0; for ($i = 0; $i < 4; $i++) { vec($blk1, $i, 32) = vec($iv, $i, 32) = vec($key, $i, 32) = $i; vec($blk2, $i, 32) = $i + 4; } # get decrypt key $dkey = noekeon_get_decrypt_key($key); #encrypt it $ct1 = noekeon_encrypt_cbc($blk1, $key, $iv); $ct2 = noekeon_encrypt_cbc($blk2, $key, $iv); for ($i = 0; $i < 4; $i++) { print sprintf("%08lx ", vec($ct1, $i, 32)); } print "\n"; for ($i = 0; $i < 4; $i++) { print sprintf("%08lx ", vec($ct2, $i, 32)); } print "\n"; #reset iv for ($i = 0; $i < 4; $i++) { vec($iv, $i, 32) = $i; } print "\n\n"; #decrypt it $pt1 = noekeon_decrypt_cbc($ct1, $dkey, $iv); $pt2 = noekeon_decrypt_cbc($ct2, $dkey, $iv); for ($i = 0; $i < 4; $i++) { print sprintf("%08lx ", vec($pt1, $i, 32)); } print "\n"; for ($i = 0; $i < 4; $i++) { print sprintf("%08lx ", vec($pt2, $i, 32)); } print "\n";