Entry 4617
Simple AES implementation
Submitted by anonymous
on May 25, 2010 at 10:07 p.m.
Language: Python. Code size: 13.1 KB.
#!/usr/bin/env python """ Copyright 2010 kenkeiras <kenkeiras@gmail.com> Bajo la licencia WTFPL DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. """ from array import array # Galois Multiplication def galoisMult(a, b): p = 0 for counter in range(0,8): if((b & 1) == 1): p ^= a hi_bit_set = (a & 0x80) a = (a<<1) & 0xFF if(hi_bit_set == 0x80): a ^= 0x1b b >>= 1 return p # Se definen algunas variables globales... global sbox global rsbox global rcon #AES S-Box sbox = [ #0 1 2 3 4 5 6 7 8 9 A B C D E F 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, #0 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, #1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, #2 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, #3 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, #4 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, #5 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, #6 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, #7 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, #8 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, #9 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, #A 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, #B 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, #C 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, #D 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, #E 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ] #F #AES RS-Box (reverse S-Box) rsbox = [ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ] #AES Rcon rcon = [ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb ] # Word to array conversion def word2array(word): arr = [0,0,0,0] arr[3] = word&((1<<8)-1) arr[2] = (word/(1<<8))&((1<<8)-1) arr[1] = (word/(1<<16))&((1<<8)-1) arr[0] = (word/(1<<24))&((1<<8)-1) return arr # Array to word conversion def array2word(arr): word = 0 arr.reverse() for i in range(0,len(arr)): word+=(arr[i]<<(i*8)) return word # String to array conversion def str2arr(s): arr = [] for c in s: arr.append(ord(c)) return arr # Array to string conversion def arr2str(arr): s = "" for c in arr: s+=chr(c) return s # ------------------------------------ # AES Add Round Key Operation def aes_AddRoundKey(data, key): for i in range(0,4): for j in range(0,4): data[i][j]^=key[i][j] return data # AES ShiftRows Operation def aes_ShiftRows(data): new_data=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] for i in range(0,4): for j in range(0,4): new_data[i][j] = data[i] [ (j+i) % 4] return new_data # AES SubBytes Operation def aes_SubBytes(data): for i in range(0,4): for j in range(0,4): data[i][j]=sbox[data[i][j]] return data # AES MixColumns Operation def aes_MixColumns(data): for i in range(0,4): column = [] for j in range(0,4): column.append(data[j][i]) column = aes_MixColumn(column) for j in range(0,4): data[j][i] = column[j] return data # AES MixColumns Operation def aes_MixColumn(data): tmp = [] for i in data: tmp.append(i) for i in range(0,4): data[i]=galoisMult(tmp[i],2) ^ galoisMult(tmp[(i+3)%4],1) ^ \ galoisMult(tmp[(i+2)%4],1) ^ galoisMult(tmp[(i+1)%4],3) return data # AES rotate Operation def aes_rotate(data): aux=data[0] for i in range(0,3): data[i]=data[i+1] data[3]=aux return data # AES Key Schedule Core Operation def aes_KS_core(word,it): word = aes_rotate(word) newWord = [] for i in word: newWord.append(sbox[i]) newWord[0]^=rcon[it] return newWord # AES expandKey Operation def aes_expandKey( key, expandedKeySize): keyLength=len(key) rconIteration = 1 tmp = [0,0,0,0] expandedKey = [] for i in range(0,keyLength): expandedKey.append(ord(key[i])) while (len(expandedKey) < expandedKeySize): for i in range(0,4): tmp[i] = expandedKey[(len(expandedKey) - 4) + i] if(len(expandedKey) % keyLength == 0): tmp=aes_KS_core(tmp, rconIteration) rconIteration+=1 if(keyLength == 32 and ((len(expandedKey) % keyLength) == 16)): for i in range(0,4): tmp[i] = sbox[tmp[i]] for i in range(0,4): expandedKey.append(expandedKey[len(expandedKey) - keyLength] ^ tmp[i] ) return expandedKey # AES Create Round Key Operation def aes_CreateRoundKey(expandedKey,start): roundKey = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] for i in range(0,4): for j in range(0,4): roundKey[i][j] = expandedKey[(i*4)+j+start] return roundKey # AES Round def aes_Round(data,key): data = aes_SubBytes (data) data = aes_ShiftRows (data) data = aes_MixColumns (data) data = aes_AddRoundKey (data,key) return data # AES Main function def aes_Main(data,expandedKey, nbrRounds): block = [] for i in range(0,4): block.append(data[i*4:(i+1)*4]) roundKey = aes_CreateRoundKey(expandedKey, 0) block = aes_AddRoundKey(block, roundKey) for i in range(1,nbrRounds): roundKey = aes_CreateRoundKey(expandedKey, 16*i) block = aes_Round(block, roundKey) roundKey = aes_CreateRoundKey(expandedKey, 16*nbrRounds) block = aes_SubBytes(block) block = aes_ShiftRows(block) block = aes_AddRoundKey(block, roundKey) data = "" for b in block: data+=(arr2str(b)) return data # Encrypting function def aes_Encrypt(data,passwd,size=256): if (size not in [128,192,256]): raise Exception('Invalid key length') while (len(passwd)<(size/8)): passwd+="\0" while ((len(data)%0x10)!=0): data+="\0" data = str2arr(data) nbrRounds = { 128: 10, 192: 12, 256: 14 } [size] expandedKeySize = (nbrRounds+1) * 16 expandedKey = aes_expandKey(passwd, expandedKeySize) data = aes_Main(data, expandedKey,nbrRounds) return data ################################# # Now, decryption ! #================================ # AES Reverse SubBytes Operation def aes_invSubBytes(data): for i in range(0,4): for j in range(0,4): data[i][j]=rsbox[data[i][j]] return data # AES Reverse ShiftRows Operation def aes_invShiftRows(data): new_data=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] for i in range(0,4): for j in range(0,4): new_data[i][j] = data[i] [ (j-i) % 4] return new_data # AES Reverse MixColumns Operation def aes_invMixColumns(data): for i in range(0,4): column = [] for j in range(0,4): column.append(data[j][i]) column = aes_invMixColumn(column) for j in range(0,4): data[j][i] = column[j] return data # AES Reverse MixColumns Operation def aes_invMixColumn(data): tmp = [] for i in data: tmp.append(i) for i in range(0,4): data[i]=galoisMult(tmp[i],14) ^ galoisMult(tmp[(i+3)%4],9) ^ \ galoisMult(tmp[(i+2)%4],13) ^ galoisMult(tmp[(i+1)%4],11) return data # AES Reverse Round def aes_invRound(data,key): data = aes_invShiftRows (data) data = aes_invSubBytes (data) data = aes_AddRoundKey (data,key) data = aes_invMixColumns (data) return data # AES Reverse main function def aes_invMain(data,expandedKey, nbrRounds): block = [] for i in range(0,4): block.append(data[i*4:(i+1)*4]) roundKey = aes_CreateRoundKey(expandedKey, 16*nbrRounds) block = aes_AddRoundKey(block, roundKey) for i in range(nbrRounds-1,0,-1): roundKey = aes_CreateRoundKey(expandedKey, 16*i) block = aes_invRound(block, roundKey) roundKey = aes_CreateRoundKey(expandedKey, 0) block = aes_invShiftRows(block) block = aes_invSubBytes(block) block = aes_AddRoundKey(block, roundKey) data = "" for b in block: data+=(arr2str(b)) return data # Decrypting function def aes_Decrypt(data,passwd,size=256): if (size not in [128,192,256]): raise Exception('Invalid key length') while (len(passwd)<(size/8)): passwd+="\0" while ((len(data)&0xFF)<0xF): data+="\0" data = str2arr(data) nbrRounds = { 128: 10, 192: 12, 256: 14 } [size] expandedKeySize = (nbrRounds+1) * 16 expandedKey = aes_expandKey(passwd, expandedKeySize) data = aes_invMain(data, expandedKey,nbrRounds) return data # AES sample multi-byte encryption def aes_Long_Encrypt(text,key): out="" while (len(text)>15): out+=aes_Encrypt(text[0:16],key) text=text[16:] if (len(text)>0): out+=aes_Encrypt(text,key) return out # AES sample multi-byte decryption def aes_Long_Decrypt(text,key): out="" while (len(text)>15): out+=aes_Decrypt(text[0:16],key) text=text[16:] if (len(text)>0): out+=aes_Decrypt(text,key) return out
This snippet took 0.11 seconds to highlight.
Back to the Entry List or Home.