fork(1) download
  1. import struct
  2. from Crypto.Cipher import AES
  3.  
  4. QUAD = struct.Struct('>Q')
  5.  
  6. def aes_unwrap_key_and_iv(kek, wrapped):
  7. n = len(wrapped)/8 - 1
  8. #NOTE: R[0] is never accessed, left in for consistency with RFC indices
  9. R = [None]+[wrapped[i*8:i*8+8] for i in range(1, n+1)]
  10. A = QUAD.unpack(wrapped[:8])[0]
  11. decrypt = AES.new(kek).decrypt
  12. for j in range(5,-1,-1): #counting down
  13. for i in range(n, 0, -1): #(n, n-1, ..., 1)
  14. ciphertext = QUAD.pack(A^(n*j+i)) + R[i]
  15. B = decrypt(ciphertext)
  16. A = QUAD.unpack(B[:8])[0]
  17. R[i] = B[8:]
  18. return "".join(R[1:]), A
  19.  
  20. #key wrapping as defined in RFC 3394
  21. #http://w...content-available-to-author-only...f.org/rfc/rfc3394.txt
  22. #def aes_unwrap_key(kek, wrapped, iv=0xa6a6a6a6a6a6a6a6):
  23. #Changed iv for Watchguard
  24. def aes_unwrap_key(kek, wrapped, iv=100085249058027875):
  25. key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
  26. if key_iv != iv:
  27. raise ValueError("Integrity Check Failed: "+hex(key_iv)+" (expected "+hex(iv)+")")
  28. print (key)
  29. #print key_iv
  30. return key
  31.  
  32. #alternate initial value for aes key wrapping, as defined in RFC 5649 section 3
  33. #http://w...content-available-to-author-only...f.org/rfc/rfc5649.txt
  34. def aes_unwrap_key_withpad(kek, wrapped):
  35. if len(wrapped) == 16:
  36. plaintext = AES.new(kek).decrypt(wrapped)
  37. key, key_iv = plaintext[:8], plaintext[8:]
  38. else:
  39. key, key_iv = aes_unwrap_key_and_iv(kek, wrapped)
  40. key_iv = "{0:016X}".format(key_iv)
  41. if key_iv[:8] != "A65959A6":
  42. raise ValueError("Integrity Check Failed: "+key_iv[:8]+" (expected A65959A6)")
  43. key_len = int(key_iv[8:], 16)
  44. #print key[:key_len]
  45. return key[:key_len]
  46.  
  47. def aes_wrap_key(kek, plaintext, iv=0xa6a6a6a6a6a6a6a6):
  48. n = len(plaintext)/8
  49. R = [None]+[plaintext[i*8:i*8+8] for i in range(0, n)]
  50. A = iv
  51. encrypt = AES.new(kek).encrypt
  52. for j in range(6):
  53. for i in range(1, n+1):
  54. B = encrypt(QUAD.pack(A) + R[i])
  55. A = QUAD.unpack(B[:8])[0] ^ (n*j + i)
  56. R[i] = B[8:]
  57. return QUAD.pack(A) + "".join(R[1:])
  58.  
  59. def aes_wrap_key_withpad(kek, plaintext):
  60. iv = 0xA65959A600000000 + len(plaintext)
  61. plaintext = plaintext + "\0" * ((8 - len(plaintext)) % 8)
  62. if len(plaintext) == 8:
  63. return AES.new(kek).encrypt(QUAD.pack[iv] + plaintext)
  64. return aes_wrap_key(kek, plaintext, iv)
  65.  
  66. def test():
  67. #test vector from RFC 3394
  68. import binascii
  69. import sys
  70. #KEK = binascii.unhexlify("000102030405060708090A0B0C0D0E0F")
  71. KEK = binascii.unhexlify("1d03f58287982bc701227394e498de23")
  72. array_kek = [ 29, 3, 245, 130, 135, 152, 43, 199, 1, 34, 115, 148, 228, 152, 222, 35 ]
  73. #print ''.join('{:02x}'.format(x) for x in array_kek)
  74. #print binascii.hexlify(KEK)
  75. print ("Input PSK: ")
  76. user_input = sys.stdin.readline().translate(None, '+')
  77. CIPHER = binascii.unhexlify(user_input.strip())
  78. #CIPHER = binascii.unhexlify("9539C9564FB73887D8CCA21F7B29FD3FE60E471D80C9B371")
  79. #CIPHER = binascii.unhexlify("0E611DC31F2AEBB4A6E69F2641E1E83D762F514F3636E1EFA86B9BDECFEFADFB")
  80. #CIPHER = binascii.unhexlify("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5")
  81. PLAIN = binascii.unhexlify("00112233445566778899AABBCCDDEEFF")
  82. #assert aes_unwrap_key(KEK, CIPHER) == PLAIN
  83. binascii.hexlify(aes_unwrap_key(KEK, CIPHER))
  84. #assert aes_wrap_key(KEK, PLAIN) == CIPHER
  85.  
  86. test()
  87.  
Success #stdin #stdout 0.01s 7444KB
stdin
4F28798DA248C747FB959EF54D179860197A98AA9742EC49E5EF648F319CE29C3B25D47799498C3D109F8A8EF3C5B07D
stdout
Input PSK: 
3zytKy#QSRpCW536lb4@b3yNk3)q4YS9