ghash.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from Crypto.Cipher import AES
  2. from Crypto.Util import Counter
  3. from Crypto.Util.number import long_to_bytes, bytes_to_long
  4. from Utils import *
  5. def gf_2_128_mul(x, y):
  6. assert x < (1 << 128)
  7. assert y < (1 << 128)
  8. res = 0
  9. for i in range(127, -1, -1):
  10. res ^= x * ((y >> i) & 1) # branchless
  11. x = (x >> 1) ^ ((x & 1) * 0xE1000000000000000000000000000000)
  12. assert res < 1 << 128
  13. return res
  14. class InvalidInputException(Exception):
  15. def __init__(self, msg):
  16. self.msg = msg
  17. def __str__(self):
  18. return str(self.msg)
  19. class InvalidTagException(Exception):
  20. def __str__(self):
  21. return 'The authenticaiton tag is invalid.'
  22. # Galois/Counter Mode with AES-128 and 96-bit IV
  23. class GhashCry:
  24. def __init__(self, master_key, init_value):
  25. print(type(master_key))
  26. print(type(init_value))
  27. if master_key >= (1 << 128):
  28. raise InvalidInputException('Master key should be 128-bit')
  29. self.init_value = init_value
  30. self.__master_key = long_to_bytes(master_key, 16)
  31. self.__aes_ecb = AES.new(self.__master_key, AES.MODE_ECB)
  32. self.__auth_key = bytes_to_long(self.__aes_ecb.encrypt(b'\x00' * 16))
  33. self.__last_key = bytes_to_long(self.__aes_ecb.encrypt(
  34. long_to_bytes((init_value << 32) | 1, 16)))
  35. def get(self):
  36. return self.__auth_key, self.__last_key
  37. def encIV(self, n):
  38. res = []
  39. print(long_to_bytes(self.init_value, 16))
  40. print(long_to_bytes(self.init_value << 32, 16))
  41. for i in range(n):
  42. print(long_to_bytes((self.init_value << 32) + i + 2, 16).hex())
  43. a = long_to_bytes((self.init_value << 32) + i + 2, 16)
  44. simplePrint("iv", a.hex())
  45. r = self.__aes_ecb.encrypt(a)
  46. s = "ENC iv "
  47. simplePrint(s, r.hex())
  48. res.insert(i, r)
  49. print(res)
  50. return res
  51. class GhashCon:
  52. def __init__(self, __auth_key, __last_key):
  53. self.change_key(__auth_key, __last_key)
  54. def change_key(self, __auth_key, __last_key):
  55. self.__auth_key = __auth_key
  56. self.__last_key = __last_key
  57. # precompute the table for multiplication in finite field
  58. table = [] # for 8-bit
  59. for i in range(16):
  60. row = []
  61. for j in range(256):
  62. row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
  63. table.append(tuple(row))
  64. self.__pre_table = tuple(table)
  65. # print(f"Ghash_0 {tuple(table)}")
  66. self.prev_init_value = None # reset
  67. def __times_auth_key(self, val):
  68. res = 0
  69. for i in range(16):
  70. res ^= self.__pre_table[i][val & 0xFF]
  71. val >>= 8
  72. return res
  73. def ghash(self, aad, txt):
  74. len_aad = len(aad)
  75. len_txt = len(txt)
  76. # padding
  77. print(aad)
  78. if 0 == len_aad % 16:
  79. data = aad
  80. else:
  81. data = aad + b'\x00' * (16 - len_aad % 16)
  82. print(data)
  83. if 0 == len_txt % 16:
  84. data += txt
  85. else:
  86. data += txt + b'\x00' * (16 - len_txt % 16)
  87. # print(data)
  88. tag = 0
  89. assert len(data) % 16 == 0
  90. print(len(data))
  91. print(len(data) // 16)
  92. for i in range(len(data) // 16):
  93. print("tag\t", hex(tag))
  94. print("data ", i, "\t", data[i * 16: (i + 1) * 16].hex())
  95. tag ^= bytes_to_long(data[i * 16: (i + 1) * 16])
  96. print("data XOR tag \t", hex(tag))
  97. tag = self.__times_auth_key(tag)
  98. print("__times_auth_key", tag, "\n\n")
  99. # print 'X\t', hex(tag)
  100. tag ^= ((8 * len_aad) << 64) | (8 * len_txt)
  101. print("XOR ahib \t", ((8 * len_aad) << 64) | (8 * len_txt))
  102. print("tag \t", tag)
  103. tag = self.__times_auth_key(tag)
  104. print("salam man ejra shodam", tag, "\n\n")
  105. print("salam man ejra shodam", tag.to_bytes(16, "big").hex(), "\n\n")
  106. return tag ^ self.__last_key