G2A Many GEOs
SHARE
TWEET

linear cipher demo

a guest Feb 25th, 2019 156 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. #
  3. # aes.py: implements AES - Advanced Encryption Standard
  4. # from the SlowAES project, http://code.google.com/p/slowaes/
  5. #
  6. # Copyright (c) 2008    Josh Davis ( http://www.josh-davis.org ),
  7. #           Alex Martelli ( http://www.aleax.it )
  8. #
  9. # Ported from C code written by Laurent Haan ( http://www.progressive-coding.com )
  10. #
  11. # Licensed under the Apache License, Version 2.0
  12. # http://www.apache.org/licenses/
  13. #
  14. # modified by Ella Rose to demonstrate the weakness of linear ciphers
  15.  
  16. import os
  17. import sys
  18. import math
  19.  
  20. class AES(object):
  21.     '''AES funtions for a single block
  22.    '''
  23.     # Very annoying code:  all is for an object, but no state is kept!
  24.     # Should just be plain functions in a AES modlule.
  25.  
  26.     # valid key sizes
  27.     keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32)
  28.  
  29.     # Rijndael S-box
  30.     #sbox =  [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
  31.     #        0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
  32.     #        0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
  33.     #        0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
  34.     #        0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
  35.     #        0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
  36.     #        0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
  37.     #        0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
  38.     #        0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
  39.     #        0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
  40.     #        0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
  41.     #        0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
  42.     #        0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
  43.     #        0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
  44.     #        0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
  45.     #        0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
  46.     #        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
  47.     #        0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
  48.     #        0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
  49.     #        0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
  50.     #        0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
  51.     #        0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
  52.     #        0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
  53.     #        0x54, 0xbb, 0x16]
  54.     sbox = range(256)
  55.     # Rijndael Inverted S-box
  56.     #rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
  57.     #        0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
  58.     #        0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54,
  59.     #        0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b,
  60.     #        0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24,
  61.     #        0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8,
  62.     #        0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
  63.     #        0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
  64.     #        0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab,
  65.     #        0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
  66.     #        0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1,
  67.     #        0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41,
  68.     #        0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
  69.     #        0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9,
  70.     #        0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d,
  71.     #        0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b ,
  72.     #        0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,
  73.     #        0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07,
  74.     #        0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60,
  75.     #        0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f,
  76.     #        0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5,
  77.     #        0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b,
  78.     #        0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
  79.     #        0x21, 0x0c, 0x7d]
  80.     rsbox = range(256)
  81.     def getSBoxValue(self,num):
  82.         """Retrieves a given S-Box Value"""
  83.         return self.sbox[num]
  84.  
  85.     def getSBoxInvert(self,num):
  86.         """Retrieves a given Inverted S-Box Value"""
  87.         return self.rsbox[num]
  88.  
  89.     def rotate(self, word):
  90.         """ Rijndael's key schedule rotate operation.
  91.  
  92.        Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d
  93.        Word is an char list of size 4 (32 bits overall).
  94.        """
  95.         return word[1:] + word[:1]
  96.  
  97.     # Rijndael Rcon
  98.     Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
  99.             0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
  100.             0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
  101.             0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
  102.             0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
  103.             0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
  104.             0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
  105.             0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61,
  106.             0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
  107.             0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
  108.             0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
  109.             0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
  110.             0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
  111.             0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
  112.             0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
  113.             0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
  114.             0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4,
  115.             0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
  116.             0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08,
  117.             0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
  118.             0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
  119.             0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
  120.             0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
  121.             0xe8, 0xcb ]
  122.  
  123.     def getRconValue(self, num):
  124.         """Retrieves a given Rcon Value"""
  125.         return self.Rcon[num]
  126.  
  127.     def core(self, word, iteration):
  128.         """Key schedule core."""
  129.         # rotate the 32-bit word 8 bits to the left
  130.         word = self.rotate(word)
  131.         # apply S-Box substitution on all 4 parts of the 32-bit word
  132.         for i in range(4):
  133.             word[i] = self.getSBoxValue(word[i])
  134.         # XOR the output of the rcon operation with i to the first part
  135.         # (leftmost) only
  136.         word[0] = word[0] ^ self.getRconValue(iteration)
  137.         return word
  138.  
  139.     def expandKey(self, key, size, expandedKeySize):
  140.         """Rijndael's key expansion.
  141.  
  142.        Expands an 128,192,256 key into an 176,208,240 bytes key
  143.  
  144.        expandedKey is a char list of large enough size,
  145.        key is the non-expanded key.
  146.        """
  147.         # current expanded keySize, in bytes
  148.         currentSize = 0
  149.         rconIteration = 1
  150.         expandedKey = [0] * expandedKeySize
  151.  
  152.         # set the 16, 24, 32 bytes of the expanded key to the input key
  153.         for j in range(size):
  154.             expandedKey[j] = key[j]
  155.         currentSize += size
  156.  
  157.         while currentSize < expandedKeySize:
  158.             # assign the previous 4 bytes to the temporary value t
  159.             t = expandedKey[currentSize-4:currentSize]
  160.  
  161.             # every 16,24,32 bytes we apply the core schedule to t
  162.             # and increment rconIteration afterwards
  163.             if currentSize % size == 0:
  164.                 t = self.core(t, rconIteration)
  165.                 rconIteration += 1
  166.             # For 256-bit keys, we add an extra sbox to the calculation
  167.             if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16):
  168.                 for l in range(4): t[l] = self.getSBoxValue(t[l])
  169.  
  170.             # We XOR t with the four-byte block 16,24,32 bytes before the new
  171.             # expanded key.  This becomes the next four bytes in the expanded
  172.             # key.
  173.             for m in range(4):
  174.                 expandedKey[currentSize] = expandedKey[currentSize - size] ^ \
  175.                         t[m]
  176.                 currentSize += 1
  177.  
  178.         return expandedKey
  179.  
  180.     def addRoundKey(self, state, roundKey):
  181.         """Adds (XORs) the round key to the state."""
  182.         for i in range(16):
  183.             state[i] ^= roundKey[i]
  184.         return state
  185.  
  186.     def createRoundKey(self, expandedKey, roundKeyPointer):
  187.         """Create a round key.
  188.        Creates a round key from the given expanded key and the
  189.        position within the expanded key.
  190.        """
  191.         roundKey = [0] * 16
  192.         for i in range(4):
  193.             for j in range(4):
  194.                 roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]
  195.         return roundKey
  196.  
  197.     def galois_multiplication(self, a, b):
  198.         """Galois multiplication of 8 bit characters a and b."""
  199.         p = 0
  200.         for counter in range(8):
  201.             if b & 1: p ^= a
  202.             hi_bit_set = a & 0x80
  203.             a <<= 1
  204.             # keep a 8 bit
  205.             a &= 0xFF
  206.             if hi_bit_set:
  207.                 a ^= 0x1b
  208.             b >>= 1
  209.         return p
  210.  
  211.     #
  212.     # substitute all the values from the state with the value in the SBox
  213.     # using the state value as index for the SBox
  214.     #
  215.     def subBytes(self, state, isInv):
  216.         if isInv: getter = self.getSBoxInvert
  217.         else: getter = self.getSBoxValue
  218.         for i in range(16): state[i] = getter(state[i])
  219.         return state
  220.  
  221.     # iterate over the 4 rows and call shiftRow() with that row
  222.     def shiftRows(self, state, isInv):
  223.         for i in range(4):
  224.             state = self.shiftRow(state, i*4, i, isInv)
  225.         return state
  226.  
  227.     # each iteration shifts the row to the left by 1
  228.     def shiftRow(self, state, statePointer, nbr, isInv):
  229.         for i in range(nbr):
  230.             if isInv:
  231.                 state[statePointer:statePointer+4] = \
  232.                         state[statePointer+3:statePointer+4] + \
  233.                         state[statePointer:statePointer+3]
  234.             else:
  235.                 state[statePointer:statePointer+4] = \
  236.                         state[statePointer+1:statePointer+4] + \
  237.                         state[statePointer:statePointer+1]
  238.         return state
  239.  
  240.     # galois multiplication of the 4x4 matrix
  241.     def mixColumns(self, state, isInv):
  242.         # iterate over the 4 columns
  243.         for i in range(4):
  244.             # construct one column by slicing over the 4 rows
  245.             column = state[i:i+16:4]
  246.             # apply the mixColumn on one column
  247.             column = self.mixColumn(column, isInv)
  248.             # put the values back into the state
  249.             state[i:i+16:4] = column
  250.  
  251.         return state
  252.  
  253.     # galois multiplication of 1 column of the 4x4 matrix
  254.     def mixColumn(self, column, isInv):
  255.         if isInv: mult = [14, 9, 13, 11]
  256.         else: mult = [2, 1, 1, 3]
  257.         cpy = list(column)
  258.         g = self.galois_multiplication
  259.  
  260.         column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \
  261.                     g(cpy[2], mult[2]) ^ g(cpy[1], mult[3])
  262.         column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \
  263.                     g(cpy[3], mult[2]) ^ g(cpy[2], mult[3])
  264.         column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \
  265.                     g(cpy[0], mult[2]) ^ g(cpy[3], mult[3])
  266.         column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \
  267.                     g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
  268.         return column
  269.  
  270.     # applies the 4 operations of the forward round in sequence
  271.     def aes_round(self, state, roundKey):
  272.         state = self.subBytes(state, False)
  273.         state = self.shiftRows(state, False)
  274.         state = self.mixColumns(state, False)
  275.         state = self.addRoundKey(state, roundKey)
  276.         return state
  277.  
  278.     def aes_round_no_key(self, state):
  279.         state = self.subBytes(state, False)
  280.         state = self.shiftRows(state, False)
  281.         state = self.mixColumns(state, False)
  282.         return state
  283.  
  284.     # applies the 4 operations of the inverse round in sequence
  285.     def aes_invRound(self, state, roundKey):
  286.         state = self.shiftRows(state, True)
  287.         state = self.subBytes(state, True)
  288.         state = self.addRoundKey(state, roundKey)
  289.         state = self.mixColumns(state, True)
  290.         return state
  291.  
  292.     # Perform the initial operations, the standard round, and the final
  293.     # operations of the forward aes, creating a round key for each round
  294.     def aes_main(self, state, expandedKey, nbrRounds):
  295.         state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
  296.         i = 1
  297.         while i < nbrRounds:
  298.             state = self.aes_round(state,
  299.                                    self.createRoundKey(expandedKey, 16*i))
  300.             i += 1
  301.         state = self.subBytes(state, False)
  302.         state = self.shiftRows(state, False)
  303.         state = self.addRoundKey(state,
  304.                                  self.createRoundKey(expandedKey, 16*nbrRounds))
  305.         return state
  306.  
  307.     # Perform the initial operations, the standard round, and the final
  308.     # operations of the inverse aes, creating a round key for each round
  309.     def aes_invMain(self, state, expandedKey, nbrRounds):
  310.         state = self.addRoundKey(state,
  311.                                  self.createRoundKey(expandedKey, 16*nbrRounds))
  312.         i = nbrRounds - 1
  313.         while i > 0:
  314.             state = self.aes_invRound(state,
  315.                                       self.createRoundKey(expandedKey, 16*i))
  316.             i -= 1
  317.         state = self.shiftRows(state, True)
  318.         state = self.subBytes(state, True)
  319.         state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
  320.         return state
  321.  
  322.     # encrypts a 128 bit input block against the given key of size specified
  323.     def encrypt(self, iput, key, size):
  324.         output = [0] * 16
  325.         # the number of rounds
  326.         nbrRounds = 0
  327.         # the 128 bit block to encode
  328.         block = [0] * 16
  329.         # set the number of rounds
  330.         if size == self.keySize["SIZE_128"]: nbrRounds = 10
  331.         elif size == self.keySize["SIZE_192"]: nbrRounds = 12
  332.         elif size == self.keySize["SIZE_256"]: nbrRounds = 14
  333.         else: return None
  334.  
  335.         # the expanded keySize
  336.         expandedKeySize = 16*(nbrRounds+1)
  337.  
  338.         # Set the block values, for the block:
  339.         # a0,0 a0,1 a0,2 a0,3
  340.         # a1,0 a1,1 a1,2 a1,3
  341.         # a2,0 a2,1 a2,2 a2,3
  342.         # a3,0 a3,1 a3,2 a3,3
  343.         # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
  344.         #
  345.         # iterate over the columns
  346.         for i in range(4):
  347.             # iterate over the rows
  348.             for j in range(4):
  349.                 block[(i+(j*4))] = iput[(i*4)+j]
  350.  
  351.         # expand the key into an 176, 208, 240 bytes key
  352.         # the expanded key
  353.         expandedKey = self.expandKey(key, size, expandedKeySize)
  354.  
  355.         # encrypt the block using the expandedKey
  356.         block = self.aes_main(block, expandedKey, nbrRounds)
  357.  
  358.         # unmap the block again into the output
  359.         for k in range(4):
  360.             # iterate over the rows
  361.             for l in range(4):
  362.                 output[(k*4)+l] = block[(k+(l*4))]
  363.         return output
  364.  
  365.     # decrypts a 128 bit input block against the given key of size specified
  366.     def decrypt(self, iput, key, size):
  367.         output = [0] * 16
  368.         # the number of rounds
  369.         nbrRounds = 0
  370.         # the 128 bit block to decode
  371.         block = [0] * 16
  372.         # set the number of rounds
  373.         if size == self.keySize["SIZE_128"]: nbrRounds = 10
  374.         elif size == self.keySize["SIZE_192"]: nbrRounds = 12
  375.         elif size == self.keySize["SIZE_256"]: nbrRounds = 14
  376.         else: return None
  377.  
  378.         # the expanded keySize
  379.         expandedKeySize = 16*(nbrRounds+1)
  380.  
  381.         # Set the block values, for the block:
  382.         # a0,0 a0,1 a0,2 a0,3
  383.         # a1,0 a1,1 a1,2 a1,3
  384.         # a2,0 a2,1 a2,2 a2,3
  385.         # a3,0 a3,1 a3,2 a3,3
  386.         # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
  387.  
  388.         # iterate over the columns
  389.         for i in range(4):
  390.             # iterate over the rows
  391.             for j in range(4):
  392.                 block[(i+(j*4))] = iput[(i*4)+j]
  393.         # expand the key into an 176, 208, 240 bytes key
  394.         expandedKey = self.expandKey(key, size, expandedKeySize)
  395.         # decrypt the block using the expandedKey
  396.         block = self.aes_invMain(block, expandedKey, nbrRounds)
  397.         # unmap the block again into the output
  398.         for k in range(4):
  399.             # iterate over the rows
  400.             for l in range(4):
  401.                 output[(k*4)+l] = block[(k+(l*4))]
  402.         return output
  403.  
  404. def test_break():
  405.     size = 16
  406.     key = range(size)
  407.     attack_plaintext = [0] * size
  408.     encryptor = AES()
  409.  
  410.     equivalent_key = encryptor.encrypt(attack_plaintext[:], key, size)
  411.     _check1 = encryptor.decrypt(equivalent_key[:], key, size)
  412.     assert _check1 == attack_plaintext
  413.  
  414.     from os import urandom
  415.     random_plaintext = list(bytearray(urandom(size)))
  416.     ciphertext = encryptor.encrypt(random_plaintext[:], key, size)
  417.  
  418.     partial_plaintext = [equivalent_key[i] ^ ciphertext[i] for i in range(16)]
  419.     encryptor.addRoundKey = lambda state, __: state
  420.     recovered_plaintext = encryptor.decrypt(partial_plaintext, key, size) # key not actually used now
  421.     assert recovered_plaintext == random_plaintext, (recovered_plaintext, random_plaintext)
  422.  
  423. if __name__ == "__main__":
  424.     test_break()
RAW Paste Data
Ledger Nano X - The secure hardware wallet
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top