import struct
from Crypto.Cipher import AES
QUAD = struct.Struct('>Q')
def aes_unwrap_key_and_iv(kek, wrapped):
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:]
return "".join(R[1:]), A
#key wrapping as defined in RFC 3394
#http://w...content-available-to-author-only...f.org/rfc/rfc3394.txt
#def aes_unwrap_key(kek, wrapped, iv=0xa6a6a6a6a6a6a6a6):
#Changed iv for Watchguard
def aes_unwrap_key(kek, wrapped, iv=100085249058027875):
key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
if key_iv != iv:
raise ValueError("Integrity Check Failed: "+hex(key_iv)+" (expected "+hex(iv)+")")
print (key)
#print key_iv
return key
#alternate initial value for aes key wrapping, as defined in RFC 5649 section 3
#http://w...content-available-to-author-only...f.org/rfc/rfc5649.txt
def aes_unwrap_key_withpad(kek, wrapped):
if len(wrapped) == 16:
plaintext = AES.new(kek).decrypt(wrapped)
key, key_iv = plaintext[:8], plaintext[8:]
else:
key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
key_iv = "{0:016X}".format(key_iv)
if key_iv[:8] != "A65959A6":
raise ValueError("Integrity Check Failed: "+key_iv[:8]+" (expected A65959A6)")
key_len = int(key_iv[8:], 16)
#print key[:key_len]
return key[:key_len]
def aes_wrap_key(kek, plaintext, iv=0xa6a6a6a6a6a6a6a6):
n = len(plaintext)/8
R = [None]+[plaintext[i*8:i*8+8] for i in range(0, n)]
A = iv
encrypt = AES.new(kek).encrypt
for j in range(6):
for i in range(1, n+1):
B = encrypt(QUAD.pack(A) + R[i])
A = QUAD.unpack(B[:8])[0] ^ (n*j + i)
R[i] = B[8:]
return QUAD.pack(A) + "".join(R[1:])
def aes_wrap_key_withpad(kek, plaintext):
iv = 0xA65959A600000000 + len(plaintext)
plaintext = plaintext + "\0" * ((8 - len(plaintext)) % 8)
if len(plaintext) == 8:
return AES.new(kek).encrypt(QUAD.pack[iv] + plaintext)
return aes_wrap_key(kek, plaintext, iv)
def test():
#test vector from RFC 3394
import binascii
import sys
#KEK = binascii.unhexlify("000102030405060708090A0B0C0D0E0F")
KEK = binascii.unhexlify("1d03f58287982bc701227394e498de23")
array_kek = [ 29, 3, 245, 130, 135, 152, 43, 199, 1, 34, 115, 148, 228, 152, 222, 35 ]
#print ''.join('{:02x}'.format(x) for x in array_kek)
#print binascii.hexlify(KEK)
print ("Input PSK: ")
user_input = sys.stdin.readline().translate(None, '+')
CIPHER = binascii.unhexlify(user_input.strip())
#CIPHER = binascii.unhexlify("9539C9564FB73887D8CCA21F7B29FD3FE60E471D80C9B371")
#CIPHER = binascii.unhexlify("0E611DC31F2AEBB4A6E69F2641E1E83D762F514F3636E1EFA86B9BDECFEFADFB")
#CIPHER = binascii.unhexlify("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5")
PLAIN = binascii.unhexlify("00112233445566778899AABBCCDDEEFF")
#assert aes_unwrap_key(KEK, CIPHER) == PLAIN
binascii.hexlify(aes_unwrap_key(KEK, CIPHER))
#assert aes_wrap_key(KEK, PLAIN) == CIPHER
test()
aW1wb3J0IHN0cnVjdApmcm9tIENyeXB0by5DaXBoZXIgaW1wb3J0IEFFUwoKUVVBRCA9IHN0cnVjdC5TdHJ1Y3QoJz5RJykKCmRlZiBhZXNfdW53cmFwX2tleV9hbmRfaXYoa2VrLCB3cmFwcGVkKToKICAgIG4gPSBsZW4od3JhcHBlZCkvOCAtIDEKICAgICNOT1RFOiBSWzBdIGlzIG5ldmVyIGFjY2Vzc2VkLCBsZWZ0IGluIGZvciBjb25zaXN0ZW5jeSB3aXRoIFJGQyBpbmRpY2VzCiAgICBSID0gW05vbmVdK1t3cmFwcGVkW2kqODppKjgrOF0gZm9yIGkgaW4gcmFuZ2UoMSwgbisxKV0KICAgIEEgPSBRVUFELnVucGFjayh3cmFwcGVkWzo4XSlbMF0KICAgIGRlY3J5cHQgPSBBRVMubmV3KGtlaykuZGVjcnlwdAogICAgZm9yIGogaW4gcmFuZ2UoNSwtMSwtMSk6ICNjb3VudGluZyBkb3duCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UobiwgMCwgLTEpOiAjKG4sIG4tMSwgLi4uLCAxKQogICAgICAgICAgICBjaXBoZXJ0ZXh0ID0gUVVBRC5wYWNrKEFeKG4qaitpKSkgKyBSW2ldCiAgICAgICAgICAgIEIgPSBkZWNyeXB0KGNpcGhlcnRleHQpCiAgICAgICAgICAgIEEgPSBRVUFELnVucGFjayhCWzo4XSlbMF0KICAgICAgICAgICAgUltpXSA9IEJbODpdCiAgICByZXR1cm4gIiIuam9pbihSWzE6XSksIEEKCiNrZXkgd3JhcHBpbmcgYXMgZGVmaW5lZCBpbiBSRkMgMzM5NAojaHR0cDovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmYub3JnL3JmYy9yZmMzMzk0LnR4dAojZGVmIGFlc191bndyYXBfa2V5KGtlaywgd3JhcHBlZCwgaXY9MHhhNmE2YTZhNmE2YTZhNmE2KToKI0NoYW5nZWQgaXYgZm9yIFdhdGNoZ3VhcmQKZGVmIGFlc191bndyYXBfa2V5KGtlaywgd3JhcHBlZCwgaXY9MTAwMDg1MjQ5MDU4MDI3ODc1KToKICAgIGtleSwga2V5X2l2ID0gYWVzX3Vud3JhcF9rZXlfYW5kX2l2KGtlaywgd3JhcHBlZCkKICAgIGlmIGtleV9pdiAhPSBpdjoKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCJJbnRlZ3JpdHkgQ2hlY2sgRmFpbGVkOiAiK2hleChrZXlfaXYpKyIgKGV4cGVjdGVkICIraGV4KGl2KSsiKSIpCiAgICBwcmludCAoa2V5KQogICAgI3ByaW50IGtleV9pdgogICAgcmV0dXJuIGtleQoKI2FsdGVybmF0ZSBpbml0aWFsIHZhbHVlIGZvciBhZXMga2V5IHdyYXBwaW5nLCBhcyBkZWZpbmVkIGluIFJGQyA1NjQ5IHNlY3Rpb24gMwojaHR0cDovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmYub3JnL3JmYy9yZmM1NjQ5LnR4dApkZWYgYWVzX3Vud3JhcF9rZXlfd2l0aHBhZChrZWssIHdyYXBwZWQpOgogICAgaWYgbGVuKHdyYXBwZWQpID09IDE2OgogICAgICAgIHBsYWludGV4dCA9IEFFUy5uZXcoa2VrKS5kZWNyeXB0KHdyYXBwZWQpCiAgICAgICAga2V5LCBrZXlfaXYgPSBwbGFpbnRleHRbOjhdLCBwbGFpbnRleHRbODpdCiAgICBlbHNlOgogICAgICAgIGtleSwga2V5X2l2ID0gYWVzX3Vud3JhcF9rZXlfYW5kX2l2KGtlaywgd3JhcHBlZCkKICAgIGtleV9pdiA9ICJ7MDowMTZYfSIuZm9ybWF0KGtleV9pdikKICAgIGlmIGtleV9pdls6OF0gIT0gIkE2NTk1OUE2IjoKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCJJbnRlZ3JpdHkgQ2hlY2sgRmFpbGVkOiAiK2tleV9pdls6OF0rIiAoZXhwZWN0ZWQgQTY1OTU5QTYpIikKICAgIGtleV9sZW4gPSBpbnQoa2V5X2l2Wzg6XSwgMTYpCiAgICAjcHJpbnQga2V5WzprZXlfbGVuXQogICAgcmV0dXJuIGtleVs6a2V5X2xlbl0KCmRlZiBhZXNfd3JhcF9rZXkoa2VrLCBwbGFpbnRleHQsIGl2PTB4YTZhNmE2YTZhNmE2YTZhNik6CiAgICBuID0gbGVuKHBsYWludGV4dCkvOAogICAgUiA9IFtOb25lXStbcGxhaW50ZXh0W2kqODppKjgrOF0gZm9yIGkgaW4gcmFuZ2UoMCwgbildCiAgICBBID0gaXYKICAgIGVuY3J5cHQgPSBBRVMubmV3KGtlaykuZW5jcnlwdAogICAgZm9yIGogaW4gcmFuZ2UoNik6CiAgICAgICAgZm9yIGkgaW4gcmFuZ2UoMSwgbisxKToKICAgICAgICAgICAgQiA9IGVuY3J5cHQoUVVBRC5wYWNrKEEpICsgUltpXSkKICAgICAgICAgICAgQSA9IFFVQUQudW5wYWNrKEJbOjhdKVswXSBeIChuKmogKyBpKQogICAgICAgICAgICBSW2ldID0gQls4Ol0KICAgIHJldHVybiBRVUFELnBhY2soQSkgKyAiIi5qb2luKFJbMTpdKQoKZGVmIGFlc193cmFwX2tleV93aXRocGFkKGtlaywgcGxhaW50ZXh0KToKICAgIGl2ID0gMHhBNjU5NTlBNjAwMDAwMDAwICsgbGVuKHBsYWludGV4dCkKICAgIHBsYWludGV4dCA9IHBsYWludGV4dCArICJcMCIgKiAoKDggLSBsZW4ocGxhaW50ZXh0KSkgJSA4KQogICAgaWYgbGVuKHBsYWludGV4dCkgPT0gODoKICAgICAgICByZXR1cm4gQUVTLm5ldyhrZWspLmVuY3J5cHQoUVVBRC5wYWNrW2l2XSArIHBsYWludGV4dCkKICAgIHJldHVybiBhZXNfd3JhcF9rZXkoa2VrLCBwbGFpbnRleHQsIGl2KQoKZGVmIHRlc3QoKToKICAgICN0ZXN0IHZlY3RvciBmcm9tIFJGQyAzMzk0CiAgICBpbXBvcnQgYmluYXNjaWkKICAgIGltcG9ydCBzeXMKICAgICNLRUsgPSBiaW5hc2NpaS51bmhleGxpZnkoIjAwMDEwMjAzMDQwNTA2MDcwODA5MEEwQjBDMEQwRTBGIikKICAgIEtFSyA9IGJpbmFzY2lpLnVuaGV4bGlmeSgiMWQwM2Y1ODI4Nzk4MmJjNzAxMjI3Mzk0ZTQ5OGRlMjMiKQogICAgYXJyYXlfa2VrID0gWyAyOSwgMywgMjQ1LCAxMzAsIDEzNSwgMTUyLCA0MywgMTk5LCAxLCAzNCwgMTE1LCAxNDgsIDIyOCwgMTUyLCAyMjIsIDM1IF0KICAgICNwcmludCAnJy5qb2luKCd7OjAyeH0nLmZvcm1hdCh4KSBmb3IgeCBpbiBhcnJheV9rZWspCiAgICAjcHJpbnQgYmluYXNjaWkuaGV4bGlmeShLRUspICAgIAogICAgcHJpbnQgKCJJbnB1dCBQU0s6ICIpCiAgICB1c2VyX2lucHV0ID0gc3lzLnN0ZGluLnJlYWRsaW5lKCkudHJhbnNsYXRlKE5vbmUsICcrJykKICAgIENJUEhFUiA9IGJpbmFzY2lpLnVuaGV4bGlmeSh1c2VyX2lucHV0LnN0cmlwKCkpCiAgICAjQ0lQSEVSID0gYmluYXNjaWkudW5oZXhsaWZ5KCI5NTM5Qzk1NjRGQjczODg3RDhDQ0EyMUY3QjI5RkQzRkU2MEU0NzFEODBDOUIzNzEiKQogICAgI0NJUEhFUiA9IGJpbmFzY2lpLnVuaGV4bGlmeSgiMEU2MTFEQzMxRjJBRUJCNEE2RTY5RjI2NDFFMUU4M0Q3NjJGNTE0RjM2MzZFMUVGQTg2QjlCREVDRkVGQURGQiIpCiAgICAjQ0lQSEVSID0gYmluYXNjaWkudW5oZXhsaWZ5KCIxRkE2OEIwQTgxMTJCNDQ3QUVGMzRCRDhGQjVBN0I4MjlEM0U4NjIzNzFEMkNGRTUiKQogICAgUExBSU4gPSBiaW5hc2NpaS51bmhleGxpZnkoIjAwMTEyMjMzNDQ1NTY2Nzc4ODk5QUFCQkNDRERFRUZGIikKICAgICNhc3NlcnQgYWVzX3Vud3JhcF9rZXkoS0VLLCBDSVBIRVIpID09IFBMQUlOCiAgICBiaW5hc2NpaS5oZXhsaWZ5KGFlc191bndyYXBfa2V5KEtFSywgQ0lQSEVSKSkKICAgICNhc3NlcnQgYWVzX3dyYXBfa2V5KEtFSywgUExBSU4pID09IENJUEhFUgoKdGVzdCgpCg==