| 1 | """ |
|---|
| 2 | AES |
|---|
| 3 | |
|---|
| 4 | An implementation of the Advanced Encryption Standard (AES). This only allows |
|---|
| 5 | the encryption of a single 128-bit plaintext with either 128-bit, 192-bit or |
|---|
| 6 | 256-bit key. |
|---|
| 7 | |
|---|
| 8 | It thus provides a foundation for the user to build up standard NIST block |
|---|
| 9 | modes (ECB, CBC etc), and for padding. None of these are provided in this |
|---|
| 10 | implementation. |
|---|
| 11 | |
|---|
| 12 | Note that the AES is already implemented in Sage, as part of the SR |
|---|
| 13 | package: |
|---|
| 14 | |
|---|
| 15 | sage: from sage.crypto import mq |
|---|
| 16 | sage: sr = mq.SR(10, 4, 4, 8, star=True, allow_zero_inversions=True, aes_mode=True) |
|---|
| 17 | sage: k = sr.base_ring() |
|---|
| 18 | sage: plain = '3243f6a8885a308d313198a2e0370734' |
|---|
| 19 | sage: key = '2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 20 | sage: set_verbose(2) |
|---|
| 21 | sage: cipher = sr(plain, key) |
|---|
| 22 | R[01].start 193DE3BEA0F4E22B9AC68D2AE9F84808 |
|---|
| 23 | |
|---|
| 24 | [all intermediate values] |
|---|
| 25 | |
|---|
| 26 | R[10].output 3925841D02DC09FBDC118597196A0B32 |
|---|
| 27 | |
|---|
| 28 | AUTHORS: |
|---|
| 29 | |
|---|
| 30 | - Alasdair McAndrew (2010-05): initial version |
|---|
| 31 | """ |
|---|
| 32 | |
|---|
| 33 | ########################################################################### |
|---|
| 34 | # Copyright (c) 2010 Alasdair McAndrew <amca01@gmail.com> |
|---|
| 35 | # |
|---|
| 36 | # This program is free software; you can redistribute it and/or modify |
|---|
| 37 | # it under the terms of the GNU General Public License as published by |
|---|
| 38 | # the Free Software Foundation; either version 2 of the License, or |
|---|
| 39 | # (at your option) any later version. |
|---|
| 40 | # |
|---|
| 41 | # This program is distributed in the hope that it will be useful, |
|---|
| 42 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 43 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 44 | # GNU General Public License for more details. |
|---|
| 45 | # |
|---|
| 46 | # http://www.gnu.org/licenses/ |
|---|
| 47 | ########################################################################### |
|---|
| 48 | |
|---|
| 49 | from sage.structure.sage_object import SageObject |
|---|
| 50 | |
|---|
| 51 | class AES(SageObject): |
|---|
| 52 | """ |
|---|
| 53 | This class implements the Advanced Encryption Standard (AES) as |
|---|
| 54 | described in NIST standard FIPS PUB 197 and available at |
|---|
| 55 | <http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf> |
|---|
| 56 | |
|---|
| 57 | Input of plaintext is a 128 bit binary string, given as 32 |
|---|
| 58 | hexadecimal characters. The key can be any of 128-bit, 192-bit or |
|---|
| 59 | 256-bits long, given as a hexadecimal string of 32, 48, or 64 |
|---|
| 60 | characters respectively. These are the only lengths of plaintext |
|---|
| 61 | and key allowed in the standard above. |
|---|
| 62 | |
|---|
| 63 | EXAMPLES: |
|---|
| 64 | |
|---|
| 65 | sage: load aes.sage |
|---|
| 66 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 67 | sage: A=AES(k) |
|---|
| 68 | sage: p='3243f6a8885a308d313198a2e0370734' |
|---|
| 69 | sage: c=A.encrypt(p) |
|---|
| 70 | sage: c |
|---|
| 71 | '3925841d02dc09fbdc118597196a0b32' |
|---|
| 72 | sage: A.decrypt(c)==p |
|---|
| 73 | True |
|---|
| 74 | |
|---|
| 75 | """ |
|---|
| 76 | |
|---|
| 77 | from sage.rings.finite_field import FiniteField as __GF |
|---|
| 78 | |
|---|
| 79 | __F=__GF(2^8,name='x',modulus=(1, 1, 0, 1, 1, 0, 0, 0, 1)) |
|---|
| 80 | |
|---|
| 81 | __bin2hex = { |
|---|
| 82 | # Given a 4-char bitstring, return the corresponding 1-char hexstring |
|---|
| 83 | "0000": "0", "0001": "1", "0010": "2", "0011": "3", |
|---|
| 84 | "0100": "4", "0101": "5", "0110": "6", "0111": "7", |
|---|
| 85 | "1000": "8", "1001": "9", "1010": "a", "1011": "b", |
|---|
| 86 | "1100": "c", "1101": "d", "1110": "e", "1111": "f", |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | # Make the reverse lookup table too |
|---|
| 90 | __hex2bin = {} |
|---|
| 91 | for (__b, __h) in __bin2hex.items(): |
|---|
| 92 | __hex2bin[__h] = __b |
|---|
| 93 | |
|---|
| 94 | __hex2dec ={ |
|---|
| 95 | "0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9, |
|---|
| 96 | "a":10,"A":10,"b":11,"B":11,"c":12,"C":12,"d":13,"D":13,"e":14, |
|---|
| 97 | "E":14,"f":15,"F":15, |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | def __init__(self,key): |
|---|
| 101 | # Sanity checking of arguments. |
|---|
| 102 | S1=set(x for x in key) |
|---|
| 103 | S2=set(['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']) |
|---|
| 104 | if not(S1.issubset(S2)): |
|---|
| 105 | raise ValueError("Invalid key - must be a hexadecimal string") |
|---|
| 106 | if not(len(key) in [32,48,64]): |
|---|
| 107 | raise ValueError("Invalid key length. Key must be exactly 32, 48 or 64 hexadecimal characters long.") |
|---|
| 108 | self.__key=key.lower() |
|---|
| 109 | |
|---|
| 110 | def getkey(self): |
|---|
| 111 | """ |
|---|
| 112 | Returns the value of the current key |
|---|
| 113 | |
|---|
| 114 | INPUT: |
|---|
| 115 | |
|---|
| 116 | None |
|---|
| 117 | |
|---|
| 118 | OUTPUT: |
|---|
| 119 | |
|---|
| 120 | A 32, 48 or 64 character hexadecimal string, representing the |
|---|
| 121 | current key. |
|---|
| 122 | |
|---|
| 123 | EXAMPLES: |
|---|
| 124 | |
|---|
| 125 | sage: load aes.sage |
|---|
| 126 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 127 | sage: A=AES(k) |
|---|
| 128 | sage: A.getkey() |
|---|
| 129 | '2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 130 | """ |
|---|
| 131 | return self.__key |
|---|
| 132 | |
|---|
| 133 | def setkey(self,k): |
|---|
| 134 | """ |
|---|
| 135 | Replaces the current key with a new value. |
|---|
| 136 | |
|---|
| 137 | INPUT: |
|---|
| 138 | |
|---|
| 139 | A 32, 48 or 64 character hexadecimal string, representing the |
|---|
| 140 | new key |
|---|
| 141 | |
|---|
| 142 | OUTPUT: |
|---|
| 143 | |
|---|
| 144 | None |
|---|
| 145 | |
|---|
| 146 | EXAMPLES: |
|---|
| 147 | |
|---|
| 148 | sage: load aes.sage |
|---|
| 149 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 150 | sage: A=AES(k) |
|---|
| 151 | sage: A.getkey() |
|---|
| 152 | '2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 153 | sage: A.setkey('000102030405060708090a0b0c0d0e0f') |
|---|
| 154 | sage: A.getkey() |
|---|
| 155 | '000102030405060708090a0b0c0d0e0f' |
|---|
| 156 | |
|---|
| 157 | """ |
|---|
| 158 | # First check values of k |
|---|
| 159 | S1=set(x for x in key) |
|---|
| 160 | S2=set(['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']) |
|---|
| 161 | if not(S1.issubset(S2)): |
|---|
| 162 | raise ValueError("Invalid key - must be a hexadecimal string") |
|---|
| 163 | if not(len(key) in [32,48,64]): |
|---|
| 164 | raise ValueError("Invalid key length. Key must be exactly 32, 48 or 64 hexadecimal characters long.") |
|---|
| 165 | self.__key=k.lower() |
|---|
| 166 | |
|---|
| 167 | |
|---|
| 168 | def __bin2poly(self,z): # Converts a string of 8 bits to a polynomial |
|---|
| 169 | return sum(int(z[i])*x^(7-i) for i in range(8)) |
|---|
| 170 | |
|---|
| 171 | def __byte2poly(self,z): # Converts 2 hexadecimal characters to a polynomial |
|---|
| 172 | zb=self.__hex2bin[z[0]]+self.__hex2bin[z[1]] |
|---|
| 173 | return self.__bin2poly(zb) |
|---|
| 174 | |
|---|
| 175 | def __poly2bin(self,p): # converts a polynomial to an 8-bit string |
|---|
| 176 | pv=list(vector(p)) |
|---|
| 177 | pv.reverse() |
|---|
| 178 | pb=join([str(i) for i in pv],'') |
|---|
| 179 | return pb |
|---|
| 180 | |
|---|
| 181 | def __poly2byte(self,p): # converts a polynomial to a 2-hex character btye |
|---|
| 182 | pb=self.__poly2bin(p) |
|---|
| 183 | return self.__bin2hex[pb[:4]]+self.__bin2hex[pb[4:]] |
|---|
| 184 | |
|---|
| 185 | def __addroundkey(self,D,W,i): |
|---|
| 186 | # D is 4x4 array of 16 bytes, W is the keyexpansion, i is an integer |
|---|
| 187 | temp=[rows[4*i:4*i+4] for rows in W] |
|---|
| 188 | return [self.__xor_word(x,y) for (x,y) in zip(D,temp)] |
|---|
| 189 | |
|---|
| 190 | def mixcolumns(self,C): # C consists of a 4x4 array of bytes |
|---|
| 191 | """ |
|---|
| 192 | Mixcolumns multiplies the current state (a 4x4 array of bytes) |
|---|
| 193 | by the matrix |
|---|
| 194 | |
|---|
| 195 | [[x,x+1,1,1], |
|---|
| 196 | [1,x,x+1,1], |
|---|
| 197 | [1,1,x,x+1], |
|---|
| 198 | [x+1,1,1,x]] |
|---|
| 199 | |
|---|
| 200 | where x is the generator of the finite field GF(2^8) generated |
|---|
| 201 | by the polynomial x^8+x^4+x^3+x+1. |
|---|
| 202 | |
|---|
| 203 | INPUT: |
|---|
| 204 | |
|---|
| 205 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 206 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 207 | |
|---|
| 208 | OUTPUT: |
|---|
| 209 | |
|---|
| 210 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 211 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 212 | |
|---|
| 213 | EXAMPLES: |
|---|
| 214 | |
|---|
| 215 | sage: load aes.sage |
|---|
| 216 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 217 | sage: A=AES(k) |
|---|
| 218 | sage: p=A.string2state('3243f6a8885a308d313198a2e0370734') |
|---|
| 219 | sage: p |
|---|
| 220 | |
|---|
| 221 | [['32', '88', '31', 'e0'], |
|---|
| 222 | ['43', '5a', '31', '37'], |
|---|
| 223 | ['f6', '30', '98', '07'], |
|---|
| 224 | ['a8', '8d', 'a2', '34']] |
|---|
| 225 | |
|---|
| 226 | sage: A.mixcolumns(p) |
|---|
| 227 | |
|---|
| 228 | [['ff', '58', '0b', 'b1'], |
|---|
| 229 | ['1d', 'e1', '42', 'b3'], |
|---|
| 230 | ['65', '3e', 'd6', '85'], |
|---|
| 231 | ['a8', 'e8', 'a5', '63']] |
|---|
| 232 | |
|---|
| 233 | """ |
|---|
| 234 | M=matrix(self.__F,[[x,x+1,1,1],[1,x,x+1,1],[1,1,x,x+1],[x+1,1,1,x]]) |
|---|
| 235 | # P=matrix(map_threaded(self.__byte2poly,C)) |
|---|
| 236 | P=matrix(map_threaded(self.__byte2poly,C)) |
|---|
| 237 | Q=M*P |
|---|
| 238 | return map_threaded(self.__poly2byte,[list(row) for row in Q]) |
|---|
| 239 | |
|---|
| 240 | def inverse_mixcolumns(self,C): # C consists of a 4x4 array of |
|---|
| 241 | # bytes |
|---|
| 242 | """ |
|---|
| 243 | Multiplies the current state (a 4x4 array of bytes) by the |
|---|
| 244 | matrix |
|---|
| 245 | |
|---|
| 246 | [[x^3+x^2+x, x^3+x+1, x^3+x^2+1, x^3+1], |
|---|
| 247 | [x^3+1, x^3+x^2+x, x^3+x+1, x^3+x^2+1], |
|---|
| 248 | [x^3+x^2+1, x^3+1, x^3+x^2+x, x^3+x+1], |
|---|
| 249 | [x^3+x+1, x^3+x^2+1, x^3+1, x^3+x^2+x]] |
|---|
| 250 | |
|---|
| 251 | where x is the generator of the finite field GF(2^8) generated |
|---|
| 252 | by the polynomial x^8+x^4+x^3+x+1. |
|---|
| 253 | |
|---|
| 254 | INPUT: |
|---|
| 255 | |
|---|
| 256 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 257 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 258 | |
|---|
| 259 | OUTPUT: |
|---|
| 260 | |
|---|
| 261 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 262 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 263 | |
|---|
| 264 | EXAMPLES: |
|---|
| 265 | |
|---|
| 266 | sage: load aes.sage |
|---|
| 267 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 268 | sage: A=AES(k) |
|---|
| 269 | sage: p=A.string2state('3243f6a8885a308d313198a2e0370734') |
|---|
| 270 | sage: q=A.mixcolumns(p) |
|---|
| 271 | sage: mq=A.inverse_mixcolumns(q);mq |
|---|
| 272 | |
|---|
| 273 | [['32', '88', '31', 'e0'], |
|---|
| 274 | ['43', '5a', '31', '37'], |
|---|
| 275 | ['f6', '30', '98', '07'], |
|---|
| 276 | ['a8', '8d', 'a2', '34']] |
|---|
| 277 | |
|---|
| 278 | sage: mq==p |
|---|
| 279 | True |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | """ |
|---|
| 283 | M=matrix(F,[[x^3+x^2+x, x^3+x+1, x^3+x^2+1, x^3+1], |
|---|
| 284 | [x^3+1, x^3+x^2+x, x^3+x+1, x^3+x^2+1], |
|---|
| 285 | [x^3+x^2+1, x^3+1, x^3+x^2+x, x^3+x+1], |
|---|
| 286 | [x^3+x+1, x^3+x^2+1, x^3+1, x^3+x^2+x]]) |
|---|
| 287 | P=matrix(map_threaded(self.__byte2poly,C)) |
|---|
| 288 | Q=M*P |
|---|
| 289 | return map_threaded(self.__poly2byte,[list(row) for row in Q]) |
|---|
| 290 | |
|---|
| 291 | def shiftrows(self,B): # B consists of a 4x4 array of bytes |
|---|
| 292 | """ |
|---|
| 293 | Shiftrows takes a 4x4 array, and cyclicly shifts the first, second, |
|---|
| 294 | third and fourth rows to the left by 0, 1, 2 and 3 places |
|---|
| 295 | respectively. |
|---|
| 296 | |
|---|
| 297 | INPUT: |
|---|
| 298 | |
|---|
| 299 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 300 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 301 | |
|---|
| 302 | OUTPUT: |
|---|
| 303 | |
|---|
| 304 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 305 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 306 | |
|---|
| 307 | |
|---|
| 308 | EXAMPLES: |
|---|
| 309 | |
|---|
| 310 | sage: load aes.sage |
|---|
| 311 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 312 | sage: A=AES(k) |
|---|
| 313 | sage: state=A.string2state('3243f6a8885a308d313198a2e0370734') |
|---|
| 314 | sage: state |
|---|
| 315 | |
|---|
| 316 | [['32', '88', '31', 'e0'], |
|---|
| 317 | ['43', '5a', '31', '37'], |
|---|
| 318 | ['f6', '30', '98', '07'], |
|---|
| 319 | ['a8', '8d', 'a2', '34']] |
|---|
| 320 | sage: A.shiftrows(state) |
|---|
| 321 | |
|---|
| 322 | [['32', '88', '31', 'e0'], |
|---|
| 323 | ['5a', '31', '37', '43'], |
|---|
| 324 | ['98', '07', 'f6', '30'], |
|---|
| 325 | ['34', 'a8', '8d', 'a2']] |
|---|
| 326 | |
|---|
| 327 | """ |
|---|
| 328 | temp=[B[0],B[1][1:]+B[1][:1],B[2][2:]+B[2][:2],B[3][3:]+B[3][:3]] |
|---|
| 329 | return temp |
|---|
| 330 | |
|---|
| 331 | def inverse_shiftrows(self,B): # B consists of 16 bytes |
|---|
| 332 | """ |
|---|
| 333 | Inverse_Shiftrows takes a 4x4 array, and cyclicly shifts the first, second, |
|---|
| 334 | third and fourth rows to the right by 0, 1, 2 and 3 places |
|---|
| 335 | respectively. |
|---|
| 336 | |
|---|
| 337 | INPUT: |
|---|
| 338 | |
|---|
| 339 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 340 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 341 | |
|---|
| 342 | OUTPUT: |
|---|
| 343 | |
|---|
| 344 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 345 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 346 | |
|---|
| 347 | EXAMPLES: |
|---|
| 348 | |
|---|
| 349 | sage: load aes.sage |
|---|
| 350 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 351 | sage: A=AES(k) |
|---|
| 352 | sage: q=string2state('325a9834883107a83137f68de04330a2') |
|---|
| 353 | sage: q |
|---|
| 354 | |
|---|
| 355 | [['32', '88', '31', 'e0'], |
|---|
| 356 | ['5a', '31', '37', '43'], |
|---|
| 357 | ['98', '07', 'f6', '30'], |
|---|
| 358 | ['34', 'a8', '8d', 'a2']] |
|---|
| 359 | |
|---|
| 360 | sage: A.inverse_shiftrows(q) |
|---|
| 361 | |
|---|
| 362 | [['32', '88', '31', 'e0'], |
|---|
| 363 | ['43', '5a', '31', '37'], |
|---|
| 364 | ['f6', '30', '98', '07'], |
|---|
| 365 | ['a8', '8d', 'a2', '34']] |
|---|
| 366 | |
|---|
| 367 | """ |
|---|
| 368 | temp=[B[0],B[1][3:]+B[1][:3],B[2][2:]+B[2][:2],B[3][1:]+B[3][:1]] |
|---|
| 369 | return temp |
|---|
| 370 | |
|---|
| 371 | __sbox=[ |
|---|
| 372 | '63','7c','77','7b','f2','6b','6f','c5','30','01','67','2b','fe','d7','ab','76', |
|---|
| 373 | 'ca','82','c9','7d','fa','59','47','f0','ad','d4','a2','af','9c','a4','72','c0', |
|---|
| 374 | 'b7','fd','93','26','36','3f','f7','cc','34','a5','e5','f1','71','d8','31','15', |
|---|
| 375 | '04','c7','23','c3','18','96','05','9a','07','12','80','e2','eb','27','b2','75', |
|---|
| 376 | '09','83','2c','1a','1b','6e','5a','a0','52','3b','d6','b3','29','e3','2f','84', |
|---|
| 377 | '53','d1','00','ed','20','fc','b1','5b','6a','cb','be','39','4a','4c','58','cf', |
|---|
| 378 | 'd0','ef','aa','fb','43','4d','33','85','45','f9','02','7f','50','3c','9f','a8', |
|---|
| 379 | '51','a3','40','8f','92','9d','38','f5','bc','b6','da','21','10','ff','f3','d2', |
|---|
| 380 | 'cd','0c','13','ec','5f','97','44','17','c4','a7','7e','3d','64','5d','19','73', |
|---|
| 381 | '60','81','4f','dc','22','2a','90','88','46','ee','b8','14','de','5e','0b','db', |
|---|
| 382 | 'e0','32','3a','0a','49','06','24','5c','c2','d3','ac','62','91','95','e4','79', |
|---|
| 383 | 'e7','c8','37','6d','8d','d5','4e','a9','6c','56','f4','ea','65','7a','ae','08', |
|---|
| 384 | 'ba','78','25','2e','1c','a6','b4','c6','e8','dd','74','1f','4b','bd','8b','8a', |
|---|
| 385 | '70','3e','b5','66','48','03','f6','0e','61','35','57','b9','86','c1','1d','9e', |
|---|
| 386 | 'e1','f8','98','11','69','d9','8e','94','9b','1e','87','e9','ce','55','28','df', |
|---|
| 387 | '8c','a1','89','0d','bf','e6','42','68','41','99','2d','0f','b0','54','bb','16' |
|---|
| 388 | ] |
|---|
| 389 | |
|---|
| 390 | def sbox(self): # prints the sbox |
|---|
| 391 | """ |
|---|
| 392 | Prints out the full sbox. |
|---|
| 393 | |
|---|
| 394 | EXAMPLES: |
|---|
| 395 | |
|---|
| 396 | sage: load aes.sage |
|---|
| 397 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 398 | sage: A=AES(k) |
|---|
| 399 | sage: A.sbox() |
|---|
| 400 | [63, 7c, 77, 7b, f2, 6b, 6f, c5, 30, 01, 67, 2b, fe, d7, ab, 76] |
|---|
| 401 | |
|---|
| 402 | ...etc... |
|---|
| 403 | |
|---|
| 404 | [8c, a1, 89, 0d, bf, e6, 42, 68, 41, 99, 2d, 0f, b0, 54, bb, 16] |
|---|
| 405 | |
|---|
| 406 | """ |
|---|
| 407 | H=HexadecimalStrings() |
|---|
| 408 | for i in range(16): |
|---|
| 409 | print [H(self.__sbox[16*i+j]) for j in range(16)] |
|---|
| 410 | |
|---|
| 411 | def sbox_check(self,b): # b is a byte made from 2 hex characters |
|---|
| 412 | p=self.__byte2poly(b) |
|---|
| 413 | q=self.__poly2byte(p^-1) |
|---|
| 414 | c=[0,1,1,0,0,0,1,1] |
|---|
| 415 | b=map(Integer, self.__hex2bin[q[1]]+self.__hex2bin[q[0]]) |
|---|
| 416 | d=[] |
|---|
| 417 | for i in range(8): |
|---|
| 418 | d.append(b[i]^^b[(i+4)%8]^^b[(i+5)%8]^^b[(i+6)%8]^^b[(i+7)%8]^^c[i]) |
|---|
| 419 | e=join([str(i) for i in d],'') |
|---|
| 420 | return self.__bin2hex[e[:4]]+self.__bin2hex[e[4:]] |
|---|
| 421 | |
|---|
| 422 | def subbytes(self,A): # Replaces bytes with their indexed values |
|---|
| 423 | # from sbox |
|---|
| 424 | """ |
|---|
| 425 | Subbytes applies the sbox to a list or array of bytes. |
|---|
| 426 | |
|---|
| 427 | INPUT: |
|---|
| 428 | |
|---|
| 429 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 430 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 431 | |
|---|
| 432 | OUTPUT: |
|---|
| 433 | |
|---|
| 434 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 435 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 436 | |
|---|
| 437 | EXAMPLES: |
|---|
| 438 | |
|---|
| 439 | sage: sage: load aes.sage |
|---|
| 440 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 441 | sage: A=AES(k) |
|---|
| 442 | sage: state=A.string2state('3243f6a8885a308d313198a2e0370734') |
|---|
| 443 | |
|---|
| 444 | sage: A.subbytes(state) |
|---|
| 445 | |
|---|
| 446 | [['23', 'c4', 'c7', 'e1'], |
|---|
| 447 | ['be', 'c7', '9a', '1a'], |
|---|
| 448 | ['46', 'c5', '42', '04'], |
|---|
| 449 | ['18', 'c2', '5d', '3a']] |
|---|
| 450 | sage: A.subbytes(['ef']) |
|---|
| 451 | ['df'] |
|---|
| 452 | |
|---|
| 453 | """ |
|---|
| 454 | temp=map_threaded(lambda x:Integer('0x'+x),A) |
|---|
| 455 | return map_threaded(lambda i:self.__sbox[i],temp) |
|---|
| 456 | |
|---|
| 457 | inverse_sbox=[ |
|---|
| 458 | '52','09','6a','d5','30','36','a5','38','bf','40','a3','9e','81','f3','d7','fb', |
|---|
| 459 | '7c','e3','39','82','9b','2f','ff','87','34','8e','43','44','c4','de','e9','cb', |
|---|
| 460 | '54','7b','94','32','a6','c2','23','3d','ee','4c','95','0b','42','fa','c3','4e', |
|---|
| 461 | '08','2e','a1','66','28','d9','24','b2','76','5b','a2','49','6d','8b','d1','25', |
|---|
| 462 | '72','f8','f6','64','86','68','98','16','d4','a4','5c','cc','5d','65','b6','92', |
|---|
| 463 | '6c','70','48','50','fd','ed','b9','da','5e','15','46','57','a7','8d','9d','84', |
|---|
| 464 | '90','d8','ab','00','8c','bc','d3','0a','f7','e4','58','05','b8','b3','45','06', |
|---|
| 465 | 'd0','2c','1e','8f','ca','3f','0f','02','c1','af','bd','03','01','13','8a','6b', |
|---|
| 466 | '3a','91','11','41','4f','67','dc','ea','97','f2','cf','ce','f0','b4','e6','73', |
|---|
| 467 | '96','ac','74','22','e7','ad','35','85','e2','f9','37','e8','1c','75','df','6e', |
|---|
| 468 | '47','f1','1a','71','1d','29','c5','89','6f','b7','62','0e','aa','18','be','1b', |
|---|
| 469 | 'fc','56','3e','4b','c6','d2','79','20','9a','db','c0','fe','78','cd','5a','f4', |
|---|
| 470 | '1f','dd','a8','33','88','07','c7','31','b1','12','10','59','27','80','ec','5f', |
|---|
| 471 | '60','51','7f','a9','19','b5','4a','0d','2d','e5','7a','9f','93','c9','9c','ef', |
|---|
| 472 | 'a0','e0','3b','4d','ae','2a','f5','b0','c8','eb','bb','3c','83','53','99','61', |
|---|
| 473 | '17','2b','04','7e','ba','77','d6','26','e1','69','14','63','55','21','0c','7d' |
|---|
| 474 | ] |
|---|
| 475 | |
|---|
| 476 | def inverse_subbytes(self,A): |
|---|
| 477 | """ |
|---|
| 478 | Inverse_Subbytes applies the inverse sbox to a list or array |
|---|
| 479 | of bytes. |
|---|
| 480 | |
|---|
| 481 | INPUT: |
|---|
| 482 | |
|---|
| 483 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 484 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 485 | |
|---|
| 486 | OUTPUT: |
|---|
| 487 | |
|---|
| 488 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 489 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 490 | |
|---|
| 491 | EXAMPLES: |
|---|
| 492 | |
|---|
| 493 | sage: load aes.sage |
|---|
| 494 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 495 | sage: A=AES(k) |
|---|
| 496 | sage: state=A.string2state('325a9834883107a83137f68de04330a2') |
|---|
| 497 | sage: B=A.subbytes(state) |
|---|
| 498 | sage: C=A.inverse_subbytes(B) |
|---|
| 499 | |
|---|
| 500 | [['32', '88', '31', 'e0'], |
|---|
| 501 | ['5a', '31', '37', '43'], |
|---|
| 502 | ['98', '07', 'f6', '30'], |
|---|
| 503 | ['34', 'a8', '8d', 'a2']] |
|---|
| 504 | |
|---|
| 505 | sage: C==state |
|---|
| 506 | True |
|---|
| 507 | sage: A.inverse_subbytes(['df']) |
|---|
| 508 | ['ef'] |
|---|
| 509 | |
|---|
| 510 | |
|---|
| 511 | """ |
|---|
| 512 | # Replaces bytes with their indexed values from inverse_sbox |
|---|
| 513 | temp=map_threaded(lambda x:Integer('0x'+x),A) |
|---|
| 514 | return map_threaded(lambda i:self.inverse_sbox[i],temp) |
|---|
| 515 | |
|---|
| 516 | def __rotword(self,w): # w is a word of four bytes |
|---|
| 517 | return [w[1],w[2],w[3],w[0]] |
|---|
| 518 | |
|---|
| 519 | def __xor_word(self,w1,w2): # exclusive-or of two words |
|---|
| 520 | return [hex(Integer('0x'+X)^^Integer('0x'+Y)).zfill(2) for (X,Y) in zip(w1,w2)] |
|---|
| 521 | |
|---|
| 522 | def __rcon(self,i): |
|---|
| 523 | return [self.__poly2byte(x^(i-1)),'00','00','00'] |
|---|
| 524 | |
|---|
| 525 | def __keyexpansion(self): |
|---|
| 526 | k=self.__key |
|---|
| 527 | # k consists of 16, 24 or 32 bytes (32, 48, or 64 hexadecimal characters): |
|---|
| 528 | Nk=len(k)//8 |
|---|
| 529 | Nr=Nk+6 |
|---|
| 530 | Nb=4 |
|---|
| 531 | W=[[k[8*i+2*j:8*i+2*j+2] for i in range(Nk)] for j in range(4)] |
|---|
| 532 | # puts k into an array to obtain first Nk subkeys |
|---|
| 533 | for i in range(Nk,Nb*(Nr+1)): |
|---|
| 534 | temp = [row[i-1] for row in W] |
|---|
| 535 | if i%Nk == 0: |
|---|
| 536 | temp = self.__xor_word(self.subbytes(self.__rotword(temp)),self.__rcon(i//Nk)) |
|---|
| 537 | else: |
|---|
| 538 | if (Nk > 6 and i%Nk == 4): |
|---|
| 539 | temp = self.subbytes(temp) |
|---|
| 540 | temp2=self.__xor_word([row[i-Nk] for row in W],temp) |
|---|
| 541 | for i in range(4): |
|---|
| 542 | W[i].append(temp2[i]) |
|---|
| 543 | return W |
|---|
| 544 | |
|---|
| 545 | def __inv_keyexpansion(self): |
|---|
| 546 | # This is the key expansion as required for the Equivalent |
|---|
| 547 | # Inverse Cipher. The main difference is that all the |
|---|
| 548 | # subkeys, except for the first and last, are replaced by |
|---|
| 549 | # their outputs after an inverse_mixcolumn transformation. |
|---|
| 550 | k=self.__key |
|---|
| 551 | Nk=len(k)//8 |
|---|
| 552 | Nr=Nk+6 |
|---|
| 553 | Nb=4 |
|---|
| 554 | DW=self.__keyexpansion() |
|---|
| 555 | for i in range(1,Nr): |
|---|
| 556 | temp=[row[Nb*i:Nb*(i+1)] for row in DW] |
|---|
| 557 | temp=self.inverse_mixcolumns(temp) |
|---|
| 558 | for j in range(4): |
|---|
| 559 | DW[j][Nb*i:Nb*(i+1)]=temp[j] |
|---|
| 560 | return DW |
|---|
| 561 | |
|---|
| 562 | def printkeys(self): |
|---|
| 563 | """ |
|---|
| 564 | This prints out each key in the key expansion as a sequence of |
|---|
| 565 | strings of 16 bytes. For ease of reading, the strings are |
|---|
| 566 | printed as groups of two hexdecimal characters separated by |
|---|
| 567 | spaces. |
|---|
| 568 | |
|---|
| 569 | If the key is longer, then there are more subkeys. There are |
|---|
| 570 | examples of key schedules at |
|---|
| 571 | <http://www.samiam.org/key-schedule.html> |
|---|
| 572 | |
|---|
| 573 | EXAMPLES: |
|---|
| 574 | |
|---|
| 575 | INPUT: |
|---|
| 576 | |
|---|
| 577 | None |
|---|
| 578 | |
|---|
| 579 | OUTPUT: |
|---|
| 580 | |
|---|
| 581 | A list of all the subkeys. |
|---|
| 582 | |
|---|
| 583 | EXAMPLES: |
|---|
| 584 | |
|---|
| 585 | sage: k='000102030405060708090a0b0c0d0e0f' |
|---|
| 586 | sage: A=AES(k) |
|---|
| 587 | sage: A.printkeys() |
|---|
| 588 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |
|---|
| 589 | d6 aa 74 fd d2 af 72 fa da a6 78 f1 d6 ab 76 fe |
|---|
| 590 | b6 92 cf 0b 64 3d bd f1 be 9b c5 00 68 30 b3 fe |
|---|
| 591 | b6 ff 74 4e d2 c2 c9 bf 6c 59 0c bf 04 69 bf 41 |
|---|
| 592 | 47 f7 f7 bc 95 35 3e 03 f9 6c 32 bc fd 05 8d fd |
|---|
| 593 | 3c aa a3 e8 a9 9f 9d eb 50 f3 af 57 ad f6 22 aa |
|---|
| 594 | 5e 39 0f 7d f7 a6 92 96 a7 55 3d c1 0a a3 1f 6b |
|---|
| 595 | 14 f9 70 1a e3 5f e2 8c 44 0a df 4d 4e a9 c0 26 |
|---|
| 596 | 47 43 87 35 a4 1c 65 b9 e0 16 ba f4 ae bf 7a d2 |
|---|
| 597 | 54 99 32 d1 f0 85 57 68 10 93 ed 9c be 2c 97 4e |
|---|
| 598 | 13 11 1d 7f e3 94 4a 17 f3 07 a7 8b 4d 2b 30 c5 |
|---|
| 599 | |
|---|
| 600 | sage: k='000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' |
|---|
| 601 | sage: A=AES(k) |
|---|
| 602 | sage: A.printkeys() |
|---|
| 603 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |
|---|
| 604 | 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |
|---|
| 605 | a5 73 c2 9f a1 76 c4 98 a9 7f ce 93 a5 72 c0 9c |
|---|
| 606 | 16 51 a8 cd 02 44 be da 1a 5d a4 c1 06 40 ba de |
|---|
| 607 | ae 87 df f0 0f f1 1b 68 a6 8e d5 fb 03 fc 15 67 |
|---|
| 608 | 6d e1 f1 48 6f a5 4f 92 75 f8 eb 53 73 b8 51 8d |
|---|
| 609 | c6 56 82 7f c9 a7 99 17 6f 29 4c ec 6c d5 59 8b |
|---|
| 610 | 3d e2 3a 75 52 47 75 e7 27 bf 9e b4 54 07 cf 39 |
|---|
| 611 | 0b dc 90 5f c2 7b 09 48 ad 52 45 a4 c1 87 1c 2f |
|---|
| 612 | 45 f5 a6 60 17 b2 d3 87 30 0d 4d 33 64 0a 82 0a |
|---|
| 613 | 7c cf f7 1c be b4 fe 54 13 e6 bb f0 d2 61 a7 df |
|---|
| 614 | f0 1a fa fe e7 a8 29 79 d7 a5 64 4a b3 af e6 40 |
|---|
| 615 | 25 41 fe 71 9b f5 00 25 88 13 bb d5 5a 72 1c 0a |
|---|
| 616 | 4e 5a 66 99 a9 f2 4f e0 7e 57 2b aa cd f8 cd ea |
|---|
| 617 | 24 fc 79 cc bf 09 79 e9 37 1a c2 3c 6d 68 de 36 |
|---|
| 618 | |
|---|
| 619 | |
|---|
| 620 | """ |
|---|
| 621 | k=self.__key |
|---|
| 622 | Nk=len(k)//8 |
|---|
| 623 | W=self.__keyexpansion() |
|---|
| 624 | for i in range(Nk+7): |
|---|
| 625 | temp=[rows[4*i:4*i+4] for rows in W] |
|---|
| 626 | print join([temp[i%4][i//4] for i in range(16)],' ') |
|---|
| 627 | |
|---|
| 628 | |
|---|
| 629 | def string2state(self,s): |
|---|
| 630 | """ |
|---|
| 631 | This takes a string of 32 hexadecimal characters, and returns |
|---|
| 632 | a column-majored 4x4 array of bytes, each byte represented as two |
|---|
| 633 | consecutive characters from the original string. |
|---|
| 634 | |
|---|
| 635 | INPUT: |
|---|
| 636 | |
|---|
| 637 | A string of 32 hexadecimal characters. |
|---|
| 638 | |
|---|
| 639 | OUTPUT: |
|---|
| 640 | |
|---|
| 641 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 642 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 643 | |
|---|
| 644 | EXAMPLES: |
|---|
| 645 | |
|---|
| 646 | sage: load aes.sage |
|---|
| 647 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 648 | sage: A=AES(k) |
|---|
| 649 | sage: p='3243f6a8885a308d313198a2e0370734' |
|---|
| 650 | sage: A.string2state(p) |
|---|
| 651 | |
|---|
| 652 | [['32', '88', '31', 'e0'], |
|---|
| 653 | ['43', '5a', '31', '37'], |
|---|
| 654 | ['f6', '30', '98', '07'], |
|---|
| 655 | ['a8', '8d', 'a2', '34']] |
|---|
| 656 | |
|---|
| 657 | |
|---|
| 658 | """ |
|---|
| 659 | return [[s[8*i+2*j:8*i+2*j+2] for i in range(4)] for j in range(4)] |
|---|
| 660 | |
|---|
| 661 | |
|---|
| 662 | def state2string(self,p): # p consists of a 4x4 array of bytes |
|---|
| 663 | """ |
|---|
| 664 | A state is a 4x4 array of bytes with each byte represented as |
|---|
| 665 | two hexadecimal characters. This method joins all bytes |
|---|
| 666 | together in order of columns to make a single string. |
|---|
| 667 | |
|---|
| 668 | INPUT: |
|---|
| 669 | |
|---|
| 670 | A 4x4 array (represented as 4 lists of 4 elements each) of |
|---|
| 671 | bytes, each given as a string of two hexadecimal characters. |
|---|
| 672 | |
|---|
| 673 | OUTPUT: |
|---|
| 674 | |
|---|
| 675 | A string of 32 hexadecimal characters. |
|---|
| 676 | |
|---|
| 677 | EXAMPLES: |
|---|
| 678 | |
|---|
| 679 | sage: load aes.sage |
|---|
| 680 | sage: k='2b7e151628aed2a6abf7158809cf4f3c' |
|---|
| 681 | sage: A=AES(k) |
|---|
| 682 | sage: p='3243f6a8885a308d313198a2e0370734' |
|---|
| 683 | sage: state=A.string2state(p) |
|---|
| 684 | sage: A.state2string(state) |
|---|
| 685 | '3243f6a8885a308d313198a2e0370734' |
|---|
| 686 | |
|---|
| 687 | |
|---|
| 688 | """ |
|---|
| 689 | temp=join([p[i%4][i//4] for i in range(16)],'') |
|---|
| 690 | return temp |
|---|
| 691 | |
|---|
| 692 | |
|---|
| 693 | def encrypt(self,p): |
|---|
| 694 | """ |
|---|
| 695 | This implements encryption with any of the allowed key sizes. |
|---|
| 696 | |
|---|
| 697 | INPUT: |
|---|
| 698 | |
|---|
| 699 | A string of 32 hexadecimal characters. |
|---|
| 700 | |
|---|
| 701 | OUTPUT: |
|---|
| 702 | |
|---|
| 703 | A string of 32 hexadecimal characters. |
|---|
| 704 | |
|---|
| 705 | EXAMPLES: |
|---|
| 706 | |
|---|
| 707 | sage: load aes.sage |
|---|
| 708 | sage: key='000102030405060708090a0b0c0d0e0f' |
|---|
| 709 | sage: A=AES(key) |
|---|
| 710 | sage: p='00112233445566778899aabbccddeeff' |
|---|
| 711 | sage: c=A.encrypt(p) |
|---|
| 712 | sage: c |
|---|
| 713 | '69c4e0d86a7b0430d8cdb78070b4c55a' |
|---|
| 714 | sage: A.setkey('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f') |
|---|
| 715 | sage: c=A.encrypt(p);c |
|---|
| 716 | '8ea2b7ca516745bfeafc49904b496089' |
|---|
| 717 | |
|---|
| 718 | """ |
|---|
| 719 | k=self.__key |
|---|
| 720 | Nr=6+len(k)//8 # Number of rounds |
|---|
| 721 | # First turn the hexadecimal string into a 4x4 array of bytes |
|---|
| 722 | state=A.string2state(p) |
|---|
| 723 | W=self.__keyexpansion() |
|---|
| 724 | state=self.__addroundkey(state,W,0) |
|---|
| 725 | for i in range(1,Nr): |
|---|
| 726 | state=self.subbytes(state) |
|---|
| 727 | state=self.shiftrows(state) |
|---|
| 728 | state=self.mixcolumns(state) |
|---|
| 729 | state=self.__addroundkey(state,W,i) |
|---|
| 730 | state=self.subbytes(state) |
|---|
| 731 | state=self.shiftrows(state) |
|---|
| 732 | state=self.__addroundkey(state,W,Nr) |
|---|
| 733 | return self.state2string(state) |
|---|
| 734 | |
|---|
| 735 | |
|---|
| 736 | def encrypt_with_print(self,p): |
|---|
| 737 | """ |
|---|
| 738 | This implements encryption with any of the allowed key sizes, |
|---|
| 739 | and prints out all intermediate steps. |
|---|
| 740 | |
|---|
| 741 | INPUT: |
|---|
| 742 | |
|---|
| 743 | A string of 32 hexadecimal characters. |
|---|
| 744 | |
|---|
| 745 | OUTPUT: |
|---|
| 746 | |
|---|
| 747 | A string of 32 hexadecimal characters. |
|---|
| 748 | |
|---|
| 749 | EXAMPLES: |
|---|
| 750 | |
|---|
| 751 | sage: load aes.sage |
|---|
| 752 | sage: key='000102030405060708090a0b0c0d0e0f' |
|---|
| 753 | sage: A=AES(key) |
|---|
| 754 | sage: p='00112233445566778899aabbccddeeff' |
|---|
| 755 | sage: c=A.encrypt_with_print(p) |
|---|
| 756 | round[ 0].input 00112233445566778899aabbccddeeff |
|---|
| 757 | round[ 0].k_sch 000102030405060708090a0b0c0d0e0f |
|---|
| 758 | round[ 1].start 00102030405060708090a0b0c0d0e0f0 |
|---|
| 759 | round[ 1].s_box 63cab7040953d051cd60e0e7ba70e18c |
|---|
| 760 | round[ 1].s_row 6353e08c0960e104cd70b751bacad0e7 |
|---|
| 761 | round[ 1].m_col 5f72641557f5bc92f7be3b291db9f91a |
|---|
| 762 | round[ 2].k_sch d6aa74fdd2af72fadaa678f1d6ab76fe |
|---|
| 763 | round[ 2].start 89d810e8855ace682d1843d8cb128fe4 |
|---|
| 764 | round[ 2].s_box a761ca9b97be8b45d8ad1a611fc97369 |
|---|
| 765 | round[ 2].s_row a7be1a6997ad739bd8c9ca451f618b61 |
|---|
| 766 | round[ 2].m_col ff87968431d86a51645151fa773ad009 |
|---|
| 767 | round[ 3].k_sch b692cf0b643dbdf1be9bc5006830b3fe |
|---|
| 768 | round[ 3].start 4915598f55e5d7a0daca94fa1f0a63f7 |
|---|
| 769 | round[ 3].s_box 3b59cb73fcd90ee05774222dc067fb68 |
|---|
| 770 | round[ 3].s_row 3bd92268fc74fb735767cbe0c0590e2d |
|---|
| 771 | round[ 3].m_col 4c9c1e66f771f0762c3f868e534df256 |
|---|
| 772 | round[ 4].k_sch b6ff744ed2c2c9bf6c590cbf0469bf41 |
|---|
| 773 | round[ 4].start fa636a2825b339c940668a3157244d17 |
|---|
| 774 | round[ 4].s_box 2dfb02343f6d12dd09337ec75b36e3f0 |
|---|
| 775 | round[ 4].s_row 2d6d7ef03f33e334093602dd5bfb12c7 |
|---|
| 776 | round[ 4].m_col 6385b79ffc538df997be478e7547d691 |
|---|
| 777 | round[ 5].k_sch 47f7f7bc95353e03f96c32bcfd058dfd |
|---|
| 778 | round[ 5].start 247240236966b3fa6ed2753288425b6c |
|---|
| 779 | round[ 5].s_box 36400926f9336d2d9fb59d23c42c3950 |
|---|
| 780 | round[ 5].s_row 36339d50f9b539269f2c092dc4406d23 |
|---|
| 781 | round[ 5].m_col f4bcd45432e554d075f1d6c51dd03b3c |
|---|
| 782 | round[ 6].k_sch 3caaa3e8a99f9deb50f3af57adf622aa |
|---|
| 783 | round[ 6].start c81677bc9b7ac93b25027992b0261996 |
|---|
| 784 | round[ 6].s_box e847f56514dadde23f77b64fe7f7d490 |
|---|
| 785 | round[ 6].s_row e8dab6901477d4653ff7f5e2e747dd4f |
|---|
| 786 | round[ 6].m_col 9816ee7400f87f556b2c049c8e5ad036 |
|---|
| 787 | round[ 7].k_sch 5e390f7df7a69296a7553dc10aa31f6b |
|---|
| 788 | round[ 7].start c62fe109f75eedc3cc79395d84f9cf5d |
|---|
| 789 | round[ 7].s_box b415f8016858552e4bb6124c5f998a4c |
|---|
| 790 | round[ 7].s_row b458124c68b68a014b99f82e5f15554c |
|---|
| 791 | round[ 7].m_col c57e1c159a9bd286f05f4be098c63439 |
|---|
| 792 | round[ 8].k_sch 14f9701ae35fe28c440adf4d4ea9c026 |
|---|
| 793 | round[ 8].start d1876c0f79c4300ab45594add66ff41f |
|---|
| 794 | round[ 8].s_box 3e175076b61c04678dfc2295f6a8bfc0 |
|---|
| 795 | round[ 8].s_row 3e1c22c0b6fcbf768da85067f6170495 |
|---|
| 796 | round[ 8].m_col baa03de7a1f9b56ed5512cba5f414d23 |
|---|
| 797 | round[ 9].k_sch 47438735a41c65b9e016baf4aebf7ad2 |
|---|
| 798 | round[ 9].start fde3bad205e5d0d73547964ef1fe37f1 |
|---|
| 799 | round[ 9].s_box 5411f4b56bd9700e96a0902fa1bb9aa1 |
|---|
| 800 | round[ 9].s_row 54d990a16ba09ab596bbf40ea111702f |
|---|
| 801 | round[ 9].m_col e9f74eec023020f61bf2ccf2353c21c7 |
|---|
| 802 | round[10].k_sch 549932d1f08557681093ed9cbe2c974e |
|---|
| 803 | round[10].start bd6e7c3df2b5779e0b61216e8b10b689 |
|---|
| 804 | round[10].s_box 7a9f102789d5f50b2beffd9f3dca4ea7 |
|---|
| 805 | round[10].s_row 7ad5fda789ef4e272bca100b3d9ff59f |
|---|
| 806 | round[10].k_sch 13111d7fe3944a17f307a78b4d2b30c5 |
|---|
| 807 | round[10].output 69c4e0d86a7b0430d8cdb78070b4c55a |
|---|
| 808 | '69c4e0d86a7b0430d8cdb78070b4c55a' |
|---|
| 809 | |
|---|
| 810 | |
|---|
| 811 | """ |
|---|
| 812 | |
|---|
| 813 | k=self.__key |
|---|
| 814 | Nr=6+len(k)//8 # Number of rounds |
|---|
| 815 | print "round[%2d].input %s"%(0,str(p)) |
|---|
| 816 | state=A.string2state(p) |
|---|
| 817 | print "round[%2d].k_sch %s"%(0,str(k)) |
|---|
| 818 | W=self.__keyexpansion() |
|---|
| 819 | state=self.__addroundkey(state,W,0) |
|---|
| 820 | print "round[%2d].start %s"%(1,self.state2string(state)) |
|---|
| 821 | for i in range(1,Nr): |
|---|
| 822 | state=self.subbytes(state) |
|---|
| 823 | print "round[%2d].s_box %s"%(i,self.state2string(state)) |
|---|
| 824 | state=self.shiftrows(state) |
|---|
| 825 | print "round[%2d].s_row %s"%(i,self.state2string(state)) |
|---|
| 826 | state=self.mixcolumns(state) |
|---|
| 827 | print "round[%2d].m_col %s"%(i,self.state2string(state)) |
|---|
| 828 | state=self.__addroundkey(state,W,i) |
|---|
| 829 | print "round[%2d].k_sch %s"%(i+1,self.state2string([rows[4*i:4*i+4] for rows in W])) |
|---|
| 830 | print "round[%2d].start %s"%(i+1,self.state2string(state)) |
|---|
| 831 | state=self.subbytes(state) |
|---|
| 832 | print "round[%2d].s_box %s"%(Nr,self.state2string(state)) |
|---|
| 833 | state=self.shiftrows(state) |
|---|
| 834 | print "round[%2d].s_row %s"%(Nr,self.state2string(state)) |
|---|
| 835 | state=self.__addroundkey(state,W,Nr) |
|---|
| 836 | print "round[%2d].k_sch %s"%(Nr,self.state2string([rows[4*Nr:4*Nr+4] for rows in W])) |
|---|
| 837 | print "round[%2d].output %s"%(Nr,self.state2string(state)) |
|---|
| 838 | return self.state2string(state) |
|---|
| 839 | |
|---|
| 840 | def decrypt(self,c): |
|---|
| 841 | """ |
|---|
| 842 | This implements decryption using the Inverse Cipher method |
|---|
| 843 | (Figure 11 in FIPS Pub 197) |
|---|
| 844 | |
|---|
| 845 | INPUT: |
|---|
| 846 | |
|---|
| 847 | A string of 32 hexadecimal characters. |
|---|
| 848 | |
|---|
| 849 | OUTPUT: |
|---|
| 850 | |
|---|
| 851 | A string of 32 hexadecimal characters. |
|---|
| 852 | |
|---|
| 853 | EXAMPLES: |
|---|
| 854 | |
|---|
| 855 | sage: load aes.sage |
|---|
| 856 | sage: key='000102030405060708090a0b0c0d0e0f' |
|---|
| 857 | sage: A=AES(key) |
|---|
| 858 | sage: p='00112233445566778899aabbccddeeff' |
|---|
| 859 | sage: c=A.encrypt(p) |
|---|
| 860 | sage: c |
|---|
| 861 | '69c4e0d86a7b0430d8cdb78070b4c55a' |
|---|
| 862 | sage: A.decrypt(c) |
|---|
| 863 | '00112233445566778899aabbccddeeff' |
|---|
| 864 | sage: key='000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f' |
|---|
| 865 | sage: A=AES(key) |
|---|
| 866 | sage: c=A.encrypt(p);c |
|---|
| 867 | '8ea2b7ca516745bfeafc49904b496089' |
|---|
| 868 | sage: A.decrypt(c) |
|---|
| 869 | '00112233445566778899aabbccddeeff' |
|---|
| 870 | |
|---|
| 871 | """ |
|---|
| 872 | k=self.__key |
|---|
| 873 | Nr=6+len(k)//8 # Number of rounds |
|---|
| 874 | state=self.string2state(c) |
|---|
| 875 | W=self.__keyexpansion() |
|---|
| 876 | state=self.__addroundkey(state,W,Nr) |
|---|
| 877 | for i in range(Nr-1,0,-1): |
|---|
| 878 | state=self.inverse_shiftrows(state) |
|---|
| 879 | state=self.inverse_subbytes(state) |
|---|
| 880 | state=self.__addroundkey(state,W,i) |
|---|
| 881 | state=self.inverse_mixcolumns(state) |
|---|
| 882 | state=self.inverse_shiftrows(state) |
|---|
| 883 | state=self.inverse_subbytes(state) |
|---|
| 884 | state=self.__addroundkey(state,W,0) |
|---|
| 885 | return self.state2string(state) |
|---|
| 886 | |
|---|
| 887 | def decrypt_with_print(self,c): |
|---|
| 888 | """ |
|---|
| 889 | This implements decryption using the Inverse Cipher method |
|---|
| 890 | (Figure 11 in FIPS Pub 197) but prints out all intermediate |
|---|
| 891 | steps. |
|---|
| 892 | |
|---|
| 893 | INPUT: |
|---|
| 894 | |
|---|
| 895 | A string of 32 hexadecimal characters. |
|---|
| 896 | |
|---|
| 897 | OUTPUT: |
|---|
| 898 | |
|---|
| 899 | A string of 32 hexadecimal characters. |
|---|
| 900 | |
|---|
| 901 | EXAMPLES: |
|---|
| 902 | |
|---|
| 903 | sage: load aes.sage |
|---|
| 904 | sage: key='000102030405060708090a0b0c0d0e0f' |
|---|
| 905 | sage: A=AES(key) |
|---|
| 906 | sage: p='00112233445566778899aabbccddeeff' |
|---|
| 907 | sage: c=A.encrypt(p) |
|---|
| 908 | sage: A.decrypt_with_print(c) |
|---|
| 909 | round[ 0].iinput 69c4e0d86a7b0430d8cdb78070b4c55a |
|---|
| 910 | round[ 0].ik_sch 13111d7fe3944a17f307a78b4d2b30c5 |
|---|
| 911 | round[ 1].istart 7ad5fda789ef4e272bca100b3d9ff59f |
|---|
| 912 | round[ 1].is_row 7a9f102789d5f50b2beffd9f3dca4ea7 |
|---|
| 913 | round[ 1].is_box bd6e7c3df2b5779e0b61216e8b10b689 |
|---|
| 914 | round[ 1].ik_sch 549932d1f08557681093ed9cbe2c974e |
|---|
| 915 | round[ 1].ik_add e9f74eec023020f61bf2ccf2353c21c7 |
|---|
| 916 | round[ 2].istart 54d990a16ba09ab596bbf40ea111702f |
|---|
| 917 | round[ 2].is_row 5411f4b56bd9700e96a0902fa1bb9aa1 |
|---|
| 918 | round[ 2].is_box fde3bad205e5d0d73547964ef1fe37f1 |
|---|
| 919 | round[ 2].ik_sch 47438735a41c65b9e016baf4aebf7ad2 |
|---|
| 920 | round[ 2].ik_add baa03de7a1f9b56ed5512cba5f414d23 |
|---|
| 921 | round[ 3].istart 3e1c22c0b6fcbf768da85067f6170495 |
|---|
| 922 | round[ 3].is_row 3e175076b61c04678dfc2295f6a8bfc0 |
|---|
| 923 | round[ 3].is_box d1876c0f79c4300ab45594add66ff41f |
|---|
| 924 | round[ 3].ik_sch 14f9701ae35fe28c440adf4d4ea9c026 |
|---|
| 925 | round[ 3].ik_add c57e1c159a9bd286f05f4be098c63439 |
|---|
| 926 | round[ 4].istart b458124c68b68a014b99f82e5f15554c |
|---|
| 927 | round[ 4].is_row b415f8016858552e4bb6124c5f998a4c |
|---|
| 928 | round[ 4].is_box c62fe109f75eedc3cc79395d84f9cf5d |
|---|
| 929 | round[ 4].ik_sch 5e390f7df7a69296a7553dc10aa31f6b |
|---|
| 930 | round[ 4].ik_add 9816ee7400f87f556b2c049c8e5ad036 |
|---|
| 931 | round[ 5].istart e8dab6901477d4653ff7f5e2e747dd4f |
|---|
| 932 | round[ 5].is_row e847f56514dadde23f77b64fe7f7d490 |
|---|
| 933 | round[ 5].is_box c81677bc9b7ac93b25027992b0261996 |
|---|
| 934 | round[ 5].ik_sch 3caaa3e8a99f9deb50f3af57adf622aa |
|---|
| 935 | round[ 5].ik_add f4bcd45432e554d075f1d6c51dd03b3c |
|---|
| 936 | round[ 6].istart 36339d50f9b539269f2c092dc4406d23 |
|---|
| 937 | round[ 6].is_row 36400926f9336d2d9fb59d23c42c3950 |
|---|
| 938 | round[ 6].is_box 247240236966b3fa6ed2753288425b6c |
|---|
| 939 | round[ 6].ik_sch 47f7f7bc95353e03f96c32bcfd058dfd |
|---|
| 940 | round[ 6].ik_add 6385b79ffc538df997be478e7547d691 |
|---|
| 941 | round[ 7].istart 2d6d7ef03f33e334093602dd5bfb12c7 |
|---|
| 942 | round[ 7].is_row 2dfb02343f6d12dd09337ec75b36e3f0 |
|---|
| 943 | round[ 7].is_box fa636a2825b339c940668a3157244d17 |
|---|
| 944 | round[ 7].ik_sch b6ff744ed2c2c9bf6c590cbf0469bf41 |
|---|
| 945 | round[ 7].ik_add 4c9c1e66f771f0762c3f868e534df256 |
|---|
| 946 | round[ 8].istart 3bd92268fc74fb735767cbe0c0590e2d |
|---|
| 947 | round[ 8].is_row 3b59cb73fcd90ee05774222dc067fb68 |
|---|
| 948 | round[ 8].is_box 4915598f55e5d7a0daca94fa1f0a63f7 |
|---|
| 949 | round[ 8].ik_sch b692cf0b643dbdf1be9bc5006830b3fe |
|---|
| 950 | round[ 8].ik_add ff87968431d86a51645151fa773ad009 |
|---|
| 951 | round[ 9].istart a7be1a6997ad739bd8c9ca451f618b61 |
|---|
| 952 | round[ 9].is_row a761ca9b97be8b45d8ad1a611fc97369 |
|---|
| 953 | round[ 9].is_box 89d810e8855ace682d1843d8cb128fe4 |
|---|
| 954 | round[ 9].ik_sch d6aa74fdd2af72fadaa678f1d6ab76fe |
|---|
| 955 | round[ 9].ik_add 5f72641557f5bc92f7be3b291db9f91a |
|---|
| 956 | round[10].istart 6353e08c0960e104cd70b751bacad0e7 |
|---|
| 957 | round[10].is_row 63cab7040953d051cd60e0e7ba70e18c |
|---|
| 958 | round[10].is_box 00102030405060708090a0b0c0d0e0f0 |
|---|
| 959 | round[10].ik_sch 000102030405060708090a0b0c0d0e0f |
|---|
| 960 | round[10].ioutput 00112233445566778899aabbccddeeff |
|---|
| 961 | '00112233445566778899aabbccddeeff' |
|---|
| 962 | |
|---|
| 963 | |
|---|
| 964 | """ |
|---|
| 965 | k=self.__key |
|---|
| 966 | Nr=6+len(k)//8 # Number of rounds |
|---|
| 967 | print "round[%2d].iinput %s"%(0,str(c)) |
|---|
| 968 | state=self.string2state(c) |
|---|
| 969 | W=self.__keyexpansion() |
|---|
| 970 | temp=[rows[Nr*4:Nr*4+4] for rows in W] |
|---|
| 971 | print "round[%2d].ik_sch %s"%(0,self.state2string(temp)) |
|---|
| 972 | W=self.__keyexpansion() |
|---|
| 973 | state=self.__addroundkey(state,W,Nr) |
|---|
| 974 | print "round[%2d].istart %s"%(1,self.state2string(state)) |
|---|
| 975 | for i in range(Nr-1,0,-1): |
|---|
| 976 | state=self.inverse_shiftrows(state) |
|---|
| 977 | print "round[%2d].is_row %s"%(Nr-i,self.state2string(state)) |
|---|
| 978 | state=self.inverse_subbytes(state) |
|---|
| 979 | print "round[%2d].is_box %s"%(Nr-i,self.state2string(state)) |
|---|
| 980 | state=self.__addroundkey(state,W,i) |
|---|
| 981 | temp=[rows[4*i:4*i+4] for rows in W] |
|---|
| 982 | print "round[%2d].ik_sch %s"%(Nr-i,self.state2string(temp)) |
|---|
| 983 | print "round[%2d].ik_add %s"%(Nr-i,self.state2string(state)) |
|---|
| 984 | state=self.inverse_mixcolumns(state) |
|---|
| 985 | #print str(Nr-i).zfill(2),'im_col ',self.state2string(state) |
|---|
| 986 | #print str(Nr-i+1).zfill(2),'istart ',self.state2string(state) |
|---|
| 987 | print "round[%2d].istart %s"%(Nr-i+1,self.state2string(state)) |
|---|
| 988 | |
|---|
| 989 | state=self.inverse_shiftrows(state) |
|---|
| 990 | print "round[%2d].is_row %s"%(Nr,self.state2string(state)) |
|---|
| 991 | state=self.inverse_subbytes(state) |
|---|
| 992 | print "round[%2d].is_box %s"%(Nr,self.state2string(state)) |
|---|
| 993 | state=self.__addroundkey(state,W,0) |
|---|
| 994 | temp=[rows[0:4] for rows in W] |
|---|
| 995 | print "round[%2d].ik_sch %s"%(Nr,self.state2string(temp)) |
|---|
| 996 | print "round[%2d].ioutput %s"%(Nr,self.state2string(state)) |
|---|
| 997 | return self.state2string(state) |
|---|
| 998 | |
|---|
| 999 | |
|---|
| 1000 | def eq_decrypt(self,c): |
|---|
| 1001 | """ |
|---|
| 1002 | This implements decryption using the "Equivalent Inverse |
|---|
| 1003 | Cipher" as described in figure 15 of FIPS Pub 197. The result |
|---|
| 1004 | is the same as for the Inverse Cipher, but the order of |
|---|
| 1005 | operations is different. For that reason the intermediate |
|---|
| 1006 | results are automatically printed. |
|---|
| 1007 | |
|---|
| 1008 | |
|---|
| 1009 | INPUT: |
|---|
| 1010 | |
|---|
| 1011 | A string of 32 hexadecimal characters. |
|---|
| 1012 | |
|---|
| 1013 | OUTPUT: |
|---|
| 1014 | |
|---|
| 1015 | A string of 32 hexadecimal characters. |
|---|
| 1016 | |
|---|
| 1017 | EXAMPLES: |
|---|
| 1018 | |
|---|
| 1019 | sage: load aes.sage |
|---|
| 1020 | sage: key='000102030405060708090a0b0c0d0e0f' |
|---|
| 1021 | sage: A=AES(key) |
|---|
| 1022 | sage: p='00112233445566778899aabbccddeeff' |
|---|
| 1023 | sage: c=A.encrypt(p) |
|---|
| 1024 | sage: A.eq_decrypt(c) |
|---|
| 1025 | round[ 0].iinput 69c4e0d86a7b0430d8cdb78070b4c55a |
|---|
| 1026 | round[ 0].ik_sch 13111d7fe3944a17f307a78b4d2b30c5 |
|---|
| 1027 | round[ 1].istart 7ad5fda789ef4e272bca100b3d9ff59f |
|---|
| 1028 | round[ 1].is_box bdb52189f261b63d0b107c9e8b6e776e |
|---|
| 1029 | round[ 1].is_row bd6e7c3df2b5779e0b61216e8b10b689 |
|---|
| 1030 | round[ 1].im_col 4773b91ff72f354361cb018ea1e6cf2c |
|---|
| 1031 | round[ 1].ik_sch 13aa29be9c8faff6f770f58000f7bf03 |
|---|
| 1032 | round[ 2].istart 54d990a16ba09ab596bbf40ea111702f |
|---|
| 1033 | round[ 2].is_box fde596f1054737d235febad7f1e3d04e |
|---|
| 1034 | round[ 2].is_row fde3bad205e5d0d73547964ef1fe37f1 |
|---|
| 1035 | round[ 2].im_col 2d7e86a339d9393ee6570a1101904e16 |
|---|
| 1036 | round[ 2].ik_sch 1362a4638f2586486bff5a76f7874a83 |
|---|
| 1037 | round[ 3].istart 3e1c22c0b6fcbf768da85067f6170495 |
|---|
| 1038 | round[ 3].is_box d1c4941f7955f40fb46f6c0ad68730ad |
|---|
| 1039 | round[ 3].is_row d1876c0f79c4300ab45594add66ff41f |
|---|
| 1040 | round[ 3].im_col 39daee38f4f1a82aaf432410c36d45b9 |
|---|
| 1041 | round[ 3].ik_sch 8d82fc749c47222be4dadc3e9c7810f5 |
|---|
| 1042 | round[ 4].istart b458124c68b68a014b99f82e5f15554c |
|---|
| 1043 | round[ 4].is_box c65e395df779cf09ccf9e1c3842fed5d |
|---|
| 1044 | round[ 4].is_row c62fe109f75eedc3cc79395d84f9cf5d |
|---|
| 1045 | round[ 4].im_col 9a39bf1d05b20a3a476a0bf79fe51184 |
|---|
| 1046 | round[ 4].ik_sch 72e3098d11c5de5f789dfe1578a2cccb |
|---|
| 1047 | round[ 5].istart e8dab6901477d4653ff7f5e2e747dd4f |
|---|
| 1048 | round[ 5].is_box c87a79969b0219bc2526773bb016c992 |
|---|
| 1049 | round[ 5].is_row c81677bc9b7ac93b25027992b0261996 |
|---|
| 1050 | round[ 5].im_col 18f78d779a93eef4f6742967c47f5ffd |
|---|
| 1051 | round[ 5].ik_sch 2ec410276326d7d26958204a003f32de |
|---|
| 1052 | round[ 6].istart 36339d50f9b539269f2c092dc4406d23 |
|---|
| 1053 | round[ 6].is_box 2466756c69d25b236e4240fa8872b332 |
|---|
| 1054 | round[ 6].is_row 247240236966b3fa6ed2753288425b6c |
|---|
| 1055 | round[ 6].im_col 85cf8bf472d124c10348f545329c0053 |
|---|
| 1056 | round[ 6].ik_sch a8a2f5044de2c7f50a7ef79869671294 |
|---|
| 1057 | round[ 7].istart 2d6d7ef03f33e334093602dd5bfb12c7 |
|---|
| 1058 | round[ 7].is_box fab38a1725664d2840246ac957633931 |
|---|
| 1059 | round[ 7].is_row fa636a2825b339c940668a3157244d17 |
|---|
| 1060 | round[ 7].im_col fc1fc1f91934c98210fbfb8da340eb21 |
|---|
| 1061 | round[ 7].ik_sch c7c6e391e54032f1479c306d6319e50c |
|---|
| 1062 | round[ 8].istart 3bd92268fc74fb735767cbe0c0590e2d |
|---|
| 1063 | round[ 8].is_box 49e594f755ca638fda0a59a01f15d7fa |
|---|
| 1064 | round[ 8].is_row 4915598f55e5d7a0daca94fa1f0a63f7 |
|---|
| 1065 | round[ 8].im_col 076518f0b52ba2fb7a15c8d93be45e00 |
|---|
| 1066 | round[ 8].ik_sch a0db02992286d160a2dc029c2485d561 |
|---|
| 1067 | round[ 9].istart a7be1a6997ad739bd8c9ca451f618b61 |
|---|
| 1068 | round[ 9].is_box 895a43e485188fe82d121068cbd8ced8 |
|---|
| 1069 | round[ 9].is_row 89d810e8855ace682d1843d8cb128fe4 |
|---|
| 1070 | round[ 9].im_col ef053f7c8b3d32fd4d2a64ad3c93071a |
|---|
| 1071 | round[ 9].ik_sch 8c56dff0825dd3f9805ad3fc8659d7fd |
|---|
| 1072 | round[10].istart 6353e08c0960e104cd70b751bacad0e7 |
|---|
| 1073 | round[10].is_box 0050a0f04090e03080d02070c01060b0 |
|---|
| 1074 | round[10].is_row 00102030405060708090a0b0c0d0e0f0 |
|---|
| 1075 | round[10].ik_sch 13111d7fe3944a17f307a78b4d2b30c5 |
|---|
| 1076 | round[10].ioutput 00112233445566778899aabbccddeeff |
|---|
| 1077 | '00112233445566778899aabbccddeeff' |
|---|
| 1078 | |
|---|
| 1079 | |
|---|
| 1080 | """ |
|---|
| 1081 | |
|---|
| 1082 | k=self.__key |
|---|
| 1083 | Nr=6+len(k)//8 # Number of rounds |
|---|
| 1084 | print "round[%2d].iinput %s"%(0,str(c)) |
|---|
| 1085 | # First turn the hexadecimal string into a 4x4 array of bytes |
|---|
| 1086 | state=self.string2state(c) |
|---|
| 1087 | DW=self.__inv_keyexpansion() |
|---|
| 1088 | temp=[rows[Nr*4:Nr*4+4] for rows in DW] |
|---|
| 1089 | print "round[%2d].ik_sch %s"%(0,self.state2string(temp)) |
|---|
| 1090 | state=self.__addroundkey(state,DW,Nr) |
|---|
| 1091 | print "round[%2d].istart %s"%(1,self.state2string(state)) |
|---|
| 1092 | for i in range(Nr-1,0,-1): |
|---|
| 1093 | state=self.inverse_subbytes(state) |
|---|
| 1094 | print "round[%2d].is_box %s"%(Nr-i,self.state2string(state)) |
|---|
| 1095 | state=self.inverse_shiftrows(state) |
|---|
| 1096 | print "round[%2d].is_row %s"%(Nr-i,self.state2string(state)) |
|---|
| 1097 | state=self.inverse_mixcolumns(state) |
|---|
| 1098 | print "round[%2d].im_col %s"%(Nr-i,self.state2string(state)) |
|---|
| 1099 | state=self.__addroundkey(state,DW,i) |
|---|
| 1100 | temp=[rows[4*i:4*i+4] for rows in DW] |
|---|
| 1101 | print "round[%2d].ik_sch %s"%(Nr-i,self.state2string(temp)) |
|---|
| 1102 | print "round[%2d].istart %s"%(Nr-i+1,self.state2string(state)) |
|---|
| 1103 | state=self.inverse_subbytes(state) |
|---|
| 1104 | print "round[%2d].is_box %s"%(Nr,self.state2string(state)) |
|---|
| 1105 | state=self.inverse_shiftrows(state) |
|---|
| 1106 | print "round[%2d].is_row %s"%(Nr,self.state2string(state)) |
|---|
| 1107 | state=self.__addroundkey(state,DW,0) |
|---|
| 1108 | temp=[rows[4*Nr:4*Nr+4] for rows in DW] |
|---|
| 1109 | print "round[%2d].ik_sch %s"%(Nr,self.state2string(temp)) |
|---|
| 1110 | print "round[%2d].ioutput %s"%(Nr,self.state2string(state)) |
|---|
| 1111 | return self.state2string(state) |
|---|