Created
November 30, 2012 01:20
-
-
Save kurtbrose/4173118 to your computer and use it in GitHub Desktop.
AES key unwrapping as defined in RFC 3394
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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