#!/usr/bin/perl -PX use strict; ## MBC1 perl implementation. ## Algorithm developed by Michael W. Bombardieri ## Version 0.0.2 (2006.09.21) ## The following code is released into the public domain by its author. ## is perl using 32-bit or 64-bit integers... #define INT32 #ifdef INT32 #define add32(a,b) (((a) + (b)) % 0x100000000) #define sub32(a,b) (((a) - (b)) % 0x100000000) #endif #ifdef INT64 #define add32(a,b) (((a) + (b)) & 0xffffffff) #define sub32(a,b) (((a) - (b)) & 0xffffffff) #endif #define rotr32(a,b) ((((a) >> (b)) | ((a) << (32 - (b)))) & 0xffffffff) #define rotl32(a,b) ((((a) << (b)) | ((a) >> (32 - (b)))) & 0xffffffff) #define Pa ($p[$i][0]) #define Pb ($p[$i][1]) #define Pc ($p[$i][2]) #define Pd ($p[$i][3]) my @iv_tbl = ( 0xFA5D7CEC, 0x734533F8, 0x484EA4B2, 0x2BF0E46B, 0xA853884B, 0xCBE7DEE0, 0x976DF92A, 0xE2B17575, 0xF9BC1EFD, 0xF8ADC573, 0x2E5B6EA9, 0x1C5A4FFD, 0x3DF27762, 0x2D7BF0BD, 0x039D26D6, 0x0A937D09, 0x01052BC2, 0x8AEEEA1C, 0xFB7D3EBE, 0x2449A182, 0x17B71BA3, 0xC6E68955, 0x74C7A0CD, 0xE1B88745, 0x4D71958C, 0x149CEB88, 0x5344E0B9, 0xC3F0A21F, 0xA348429B, 0xF672C8CD, 0xD01FA55C, 0x4C6FD3DF, 0xC05B564E, 0xE0D81861, 0xA3B3EAAC, 0x17AE4A08, 0x9D8DF3BF, 0x1353CBFE, 0x25C0F1C8, 0xD52818EC, 0x1BA102B0, 0xC2FDC394, 0x9AB0505E, 0xF8D5F8CB, 0x708749DA, 0x34C5D60B, 0xD1C046B0, 0x4C8E4672, 0x0E236A84, 0x5A36C5AB, 0xDC9B9EB5, 0x0ADB5718, 0x57D27CC5, 0xC4ECAEFD, 0xB57C0D9E, 0x764E92EA, 0x4CA01ED6, 0xA7314405, 0xEE5E6B4B, 0xF9560189, 0xC50CD4D5, 0xBFE0AFD8, 0x8322F984, 0x65601B60 ); my @p = ## permutations ( [3, 0, 1, 2], [3, 0, 2, 1], [3, 1, 0, 2], [3, 1, 2, 0], [3, 2, 0, 1], [3, 2, 1, 0], [1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0], [0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], [0, 3, 2, 1] ); my @key = (); sub set_key { my @in_key = @_; my @blk = (); my @key_exp = (); my $fbk = 0x19860719; my $t; ## temp. variable for shuffle my $x; ## index into iv_tbl[] my $j; ## index into key[] my $i; $blk[0] = add32($in_key[0], rotl32($fbk, 3)); $blk[1] = add32($in_key[1], rotl32($blk[0], 5)); $blk[2] = add32($in_key[2], rotl32($blk[1], 7)); $blk[3] = add32($in_key[3], rotl32($blk[2], 11)); $x = rotl32($blk[3], 1) % 64; $fbk ^= add32(rotl32($blk[3], 2), $iv_tbl[$x]); $blk[0] ^= rotl32($fbk, 1); $blk[1] ^= rotl32($blk[0], 2); $blk[2] ^= rotl32($blk[1], 3); $blk[3] ^= rotl32($blk[2], 4); $x = ($x + ($blk[0] & 0xff)) % 64; for ($i = 0; $i < 4; $i++) { $blk[Pd] = add32($blk[Pd], $iv_tbl[$x]); $blk[Pc] = add32($blk[Pc], $iv_tbl[($x + 1) % 64]); $blk[Pb] = add32($blk[Pb], $iv_tbl[($x + 2) % 64]); $blk[Pa] = add32($blk[Pa], $iv_tbl[($x + 3) % 64]); } $key[0] = rotl32($blk[0], 5); $key[1] = rotl32($blk[1], 9); $key[2] = rotl32($blk[2], 13); $key[3] = rotl32($blk[3], 17); $j = 4; for ($i = 0; $i < 7; $i++) { $blk[Pa] = add32($blk[Pa], $iv_tbl[$x]); $blk[Pb] = add32($blk[Pb], $iv_tbl[($x + 1) % 64]); $blk[Pc] = add32($blk[Pc], $iv_tbl[($x + 2) % 64]); $blk[Pd] = add32($blk[Pd], $iv_tbl[($x + 3) % 64]); $key[$j] = rotl32($blk[Pa], 5); $key[$j + 1] = rotl32($blk[Pb], 9); $key[$j + 2] = rotl32($blk[Pc], 13); $key[$j + 3] = rotl32($blk[Pd], 17); $x = ($x + 4) % 64; $j += 4; } for ($i = 0; $i < 32; $i++) { $key_exp[$i] = $key[$i] & 0xff; $key_exp[$i + 32] = ($key[$i] & 0xff00) >> 8; } for ($i = 0; $i < 64; $i++) { $j = $key_exp[$i] % 32; $t = $key[$i % 32]; $key[$i % 32] = $key[$j]; $key[$j] = $t; } } sub encrypt { my @blk = @_; my $i; my $fbk; for ($i = 0; $i < 16; $i++) { $blk[Pa] ^= $key[($i + 16) % 32]; $blk[Pb] ^= $key[($i + 19) % 32]; $blk[Pc] ^= $key[($i + 21) % 32]; $blk[Pd] ^= $key[($i + 23) % 32]; $blk[Pa] = add32($blk[Pa], $key[$i]); $blk[Pb] = add32($blk[Pb], rotl32($blk[Pa], 1)); $blk[Pc] = add32($blk[Pc], rotl32($blk[Pb], 2)); $blk[Pd] = add32($blk[Pd], rotl32($blk[Pc], 3)); $fbk = add32(rotl32($blk[Pd], 5), $key[$i]) ^ $key[$i + 1]; $blk[Pa] ^= $fbk; $blk[Pb] ^= rotl32($fbk, 1); $blk[Pc] ^= rotl32($fbk, 2); $blk[Pd] ^= rotl32($key[$i], 1); } return @blk; } sub decrypt { my @blk = @_; my $i; my $fbk; for ($i = 15; $i > -1; $i--) { $blk[Pd] ^= rotl32($key[$i], 1); $fbk = add32(rotl32($blk[Pd], 5), $key[$i]) ^ $key[$i + 1]; $blk[Pa] ^= $fbk; $blk[Pb] ^= rotl32($fbk, 1); $blk[Pc] ^= rotl32($fbk, 2); $blk[Pd] = sub32($blk[Pd], rotl32($blk[Pc], 3)); $blk[Pc] = sub32($blk[Pc], rotl32($blk[Pb], 2)); $blk[Pb] = sub32($blk[Pb], rotl32($blk[Pa], 1)); $blk[Pa] = sub32($blk[Pa], $key[$i]); $blk[Pa] ^= $key[($i + 16) % 32]; $blk[Pb] ^= $key[($i + 19) % 32]; $blk[Pc] ^= $key[($i + 21) % 32]; $blk[Pd] ^= $key[($i + 23) % 32]; } return @blk; } sub main { my @in_key = (0x11111111, 0x22222222, 0x33333333, 0x44444444); my @blk = (0x00000000, 0x11111111, 0x22222222, 0x33333333); my @ct = (); my @pt = (); printf("%08lx%08lx%08lx%08lx = %s\n", $in_key[0], $in_key[1], $in_key[2], $in_key[3], "User key"); printf("%08lx%08lx%08lx%08lx = %s\n", $blk[0], $blk[1], $blk[2], $blk[3], "Plaintext"); set_key(@in_key); @ct = encrypt(@blk); printf("%08lx%08lx%08lx%08lx = %s\n", $ct[0], $ct[1], $ct[2], $ct[3], "Ciphertext"); @pt = decrypt(@ct); printf("%08lx%08lx%08lx%08lx = %s\n", $pt[0], $pt[1], $pt[2], $pt[3], "Plaintext"); exit 0; } main();