fork download
  1. import struct
  2. import sys
  3. import binascii
  4. from Crypto.Cipher import AES
  5.  
  6. QUAD = struct.Struct('>Q')
  7.  
  8. def aes_unwrap_key_and_iv(kek, wrapped):
  9. n = len(wrapped)/8 - 1
  10. #NOTE: R[0] is never accessed, left in for consistency with RFC indices
  11. R = [None]+[wrapped[i*8:i*8+8] for i in range(1, n+1)]
  12. A = QUAD.unpack(wrapped[:8])[0]
  13. decrypt = AES.new(kek).decrypt
  14. for j in range(5,-1,-1): #counting down
  15. for i in range(n, 0, -1): #(n, n-1, ..., 1)
  16. ciphertext = QUAD.pack(A^(n*j+i)) + R[i]
  17. B = decrypt(ciphertext)
  18. A = QUAD.unpack(B[:8])[0]
  19. R[i] = B[8:]
  20. return "".join(R[1:]), A
  21.  
  22. #key wrapping as defined in RFC 3394
  23. #http://w...content-available-to-author-only...f.org/rfc/rfc3394.txt
  24. #def aes_unwrap_key(kek, wrapped, iv=0xa6a6a6a6a6a6a6a6):
  25. #Changed iv for Watchguard
  26. def aes_unwrap_key(kek, wrapped, iv=100085249058027875):
  27. key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
  28. if key_iv != iv:
  29. raise ValueError("Integrity Check Failed: "+hex(key_iv)+" (expected "+hex(iv)+")")
  30. print (key)
  31. #print key_iv
  32. return key
  33.  
  34. #alternate initial value for aes key wrapping, as defined in RFC 5649 section 3
  35. #http://w...content-available-to-author-only...f.org/rfc/rfc5649.txt
  36. def aes_unwrap_key_withpad(kek, wrapped):
  37. if len(wrapped) == 16:
  38. plaintext = AES.new(kek).decrypt(wrapped)
  39. key, key_iv = plaintext[:8], plaintext[8:]
  40. else:
  41. key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
  42. key_iv = "{0:016X}".format(key_iv)
  43. if key_iv[:8] != "A65959A6":
  44. raise ValueError("Integrity Check Failed: "+key_iv[:8]+" (expected A65959A6)")
  45. key_len = int(key_iv[8:], 16)
  46. #print key[:key_len]
  47. return key[:key_len]
  48.  
  49. def aes_wrap_key(kek, plaintext, iv=0xa6a6a6a6a6a6a6a6):
  50. n = len(plaintext)/8
  51. R = [None]+[plaintext[i*8:i*8+8] for i in range(0, n)]
  52. A = iv
  53. encrypt = AES.new(kek).encrypt
  54. for j in range(6):
  55. for i in range(1, n+1):
  56. B = encrypt(QUAD.pack(A) + R[i])
  57. A = QUAD.unpack(B[:8])[0] ^ (n*j + i)
  58. R[i] = B[8:]
  59. return QUAD.pack(A) + "".join(R[1:])
  60.  
  61. def aes_wrap_key_withpad(kek, plaintext):
  62. iv = 0xA65959A600000000 + len(plaintext)
  63. plaintext = plaintext + "\0" * ((8 - len(plaintext)) % 8)
  64. if len(plaintext) == 8:
  65. return AES.new(kek).encrypt(QUAD.pack[iv] + plaintext)
  66. return aes_wrap_key(kek, plaintext, iv)
  67.  
  68. def test():
  69. # KEK as defined in your example
  70. KEK = binascii.unhexlify("1d03f58287982bc701227394e498de23")
  71.  
  72. # Read all lines of input from stdin
  73. inputs = sys.stdin.read().strip().splitlines()
  74.  
  75. for user_input in inputs:
  76. try:
  77. # Convert user input from hex to binary
  78. CIPHER = binascii.unhexlify(user_input.replace(' ', '').strip())
  79.  
  80. # Perform AES key unwrapping
  81. unwrapped_key = aes_unwrap_key(KEK, CIPHER)
  82.  
  83. # Print or handle the result accordingly
  84. #print("Input:", user_input)
  85. #print("Unwrapped Key:", binascii.hexlify(unwrapped_key))
  86. #print()
  87.  
  88. except ValueError as e:
  89. print("Error:", str(e))
  90. print()
  91.  
  92. # Example usage:
  93. if __name__ == "__main__":
  94. test()
  95.  
Success #stdin #stdout 0.02s 7460KB
stdin
5AC64F8A6BA453875D7C3C89FDEBFAB7BA981CEB0F2D37BA6E7F2E438DB051D5861424E58D3AA59D9B58631DEA174C0E
E274B9DC581AFE65D102EE2B3EA4A33FA9C64FF5F8E452AF1FBB2ECBAA54A393C738AE48249AD580
7A78EE92663ED743643A51BD7A0C6E6A473163D2D244805F6933FD0BE8A55281E77C5EF16A3C757F9B64B1B55E209D48
36811887E35C7942140013A61BD493AECC51BEFDAC2E1B1EF3489949E574D5B1DC5BFD3DB412A4BE20CD74B364E12807
886057B1ECE55CE84F977D9EFA9D1D8A3879DEBEFC7E2E8A51F58D2D8F8DE8C2036CE1310B375AB806E67BEA812B73EE
FE4D1C89922B47C1B1C363381F0D42ECF06B3A6A3524EE7DA67A9A866A00980D9C94847725461B96E968529F6A2476E6
4FBD37548DAFF5DAD2D9DEA59278F3562E69B0FB40EA9D19B1C9A358A28F6C65
8216676E78B6C2610A7899603D051409CC3A5F159866232449A63E7B76056B295A7495BBB06A300C
6958B152655064434CD56B27EA0AB1330532E04495D8AD4180C2E238B146FB8B21BD637A51A3C18A6FB0EBDB728B2F46
90A0383B13AB1D2CB00DC692FBAC95173C7EC490351C633EC0D6AC41C3963FEE5800D67F82C71DB6254150BF4BFFE007
2E1658FAF61C4DB933AC2516450F6046BFA85E75D734AA4397056D3A2CDCE6178663D8CEF076A9A32BD85CE2151FCC09
51913331D2B4DF206FC9135B493161F52348B3CAF486F71923EC0FA06FB89DC2FBC88D60ECE4E0AA
A4C33859DD4C1FFBD90D3DBD324C34E2DE6F5EA11206C66B
A4C33859DD4C1FFBD90D3DBD324C34E2DE6F5EA11206C66B
A4C33859DD4C1FFBD90D3DBD324C34E2DE6F5EA11206C66B
stdout
qZyXOh&ILbs53xNthkswzAR6(X4wF$XC
gjh1kjg12!@E#Ejwdqheg2#$
(GZzTVL4l5j%CN$KfXneQB1aXZ5@BvOp
Bf#FdpjP2dVJ_t%h_Z2EAPwT&UBbsMtF
5FbjCoumf&7lf0Bju6e6zE9IY#+A=uso
?phMEcMrM&rbfa^`R5DS8v|EC/tD!HSt
A@kSh!0OM@10v35$hy@@h!
EJwh23h@#Rijh32!#hjr32fewj23
Hms8*&6tgsk$!ZMl&*08%yh$gek#*4r2
Hl2=';D9F;Rr%\XOgw7,^"%ll.Prc'YG
YAHZdU#KOUExv#MpkoF5u0uPsfs*NCZ6x
Ajk5!oQEDPn^a2bkclv&zwyU4$c9HMP
c1sc0k1d
c1sc0k1d
c1sc0k1d