import struct
import sys
import binascii
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():
# KEK as defined in your example
KEK = binascii.unhexlify("1d03f58287982bc701227394e498de23")
# Read all lines of input from stdin
inputs = sys.stdin.read().strip().splitlines()
for user_input in inputs:
try:
# Convert user input from hex to binary
CIPHER = binascii.unhexlify(user_input.replace(' ', '').strip())
# Perform AES key unwrapping
unwrapped_key = aes_unwrap_key(KEK, CIPHER)
# Print or handle the result accordingly
#print("Input:", user_input)
#print("Unwrapped Key:", binascii.hexlify(unwrapped_key))
#print()
except ValueError as e:
print("Error:", str(e))
print()
# Example usage:
if __name__ == "__main__":
test()