Skip to content

Instantly share code, notes, and snippets.

@kurtbrose
Created November 30, 2012 01:20
Show Gist options
  • Save kurtbrose/4173118 to your computer and use it in GitHub Desktop.
Save kurtbrose/4173118 to your computer and use it in GitHub Desktop.
AES key unwrapping as defined in RFC 3394
import struct
from Crypto.Cipher import AES
QUAD = struct.Struct('>Q')
#key wrapping as defined in RFC 3394
#http://www.ietf.org/rfc/rfc3394.txt
def aes_unwrap(kek, wrapped, iv=0xa6a6a6a6a6a6a6a6):
n = len(wrapped)/8 - 1
#NOTE: R[0] is never accessed, left in for consistency with RFC indices
R = [None]+[wrapped[i*8:i*8+8] for i in range(1, n+1)]
A = QUAD.unpack(wrapped[:8])[0]
decrypt = AES.new(kek).decrypt
for j in range(5,-1,-1): #counting down
for i in range(n, 0, -1): #(n, n-1, ..., 1)
ciphertext = QUAD.pack(A^(n*j+i)) + R[i]
B = decrypt(ciphertext)
A = QUAD.unpack(B[:8])[0]
R[i] = B[8:]
if A != iv:
return None #integrity check failed
return b"".join(R[1:])
def test():
import binascii
KEK = binascii.unhexlify("000102030405060708090A0B0C0D0E0F")
CIPHER = binascii.unhexlify("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5")
PLAIN = binascii.unhexlify("00112233445566778899AABBCCDDEEFF")
assert aes_unwrap(KEK, CIPHER) == PLAIN
'''
Could only find one Python implementation googling, and it wasn't very clean.
Took a couple of hours to re-implement from the RFC.
Hopefully this terse, pythonic aes_unwrap will be useful to the next person in my position. :-)
(One external dependency: PyCrypto for AES)
'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment