ciphers.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import abc
  2. import nacl.bindings
  3. from Cryptodome.Cipher import AES
  4. from .key_schedule import tls_sha256, tls_sha384
  5. class TLS_AEAD_Cipher(abc.ABC):
  6. NONCE_LEN = 12
  7. @property
  8. @abc.abstractmethod
  9. def KEY_LEN(self):
  10. ""
  11. @property
  12. @abc.abstractmethod
  13. def MAC_LEN(self):
  14. ""
  15. @property
  16. @abc.abstractmethod
  17. def tls_hash(self):
  18. ""
  19. @abc.abstractmethod
  20. def cipher(self):
  21. ""
  22. def __init__(self, secret):
  23. self.reset(secret)
  24. def reset(self, secret):
  25. self.secret = secret
  26. self.key = self.tls_hash.derive_key(self.secret, self.KEY_LEN)
  27. self.iv = int.from_bytes(
  28. self.tls_hash.derive_iv(self.secret, self.NONCE_LEN), "big"
  29. )
  30. self.sequence_number = 0
  31. def next_application_traffic_secret(self):
  32. return self.tls_hash.hkdf_expand_label(
  33. self.secret, b"traffic upd", b"", self.tls_hash.hash_len
  34. )
  35. def update_traffic_secret(self):
  36. self.reset(self.next_application_traffic_secret())
  37. def verify_data(self, msg):
  38. return self.tls_hash.verify_data(self.secret, msg)
  39. def get_nonce(self):
  40. nonce = self.sequence_number ^ self.iv
  41. nonce = nonce.to_bytes(self.NONCE_LEN, "big")
  42. self.sequence_number += 1
  43. return nonce
  44. def decrypt(self, ciphertext, associated_data):
  45. cipher = self.cipher()
  46. cipher.update(associated_data)
  47. return cipher.decrypt_and_verify(
  48. ciphertext[: -self.MAC_LEN], ciphertext[-self.MAC_LEN :]
  49. )
  50. def encrypt(self, plaintext, associated_data):
  51. cipher = self.cipher()
  52. cipher.update(associated_data)
  53. ciphertext, tag = cipher.encrypt_and_digest(plaintext)
  54. return ciphertext + tag
  55. def tls_ciphertext(self, plaintext):
  56. head = b"\x17\x03\x03" + (len(plaintext) + self.MAC_LEN).to_bytes(2, "big")
  57. return head + self.encrypt(plaintext, head)
  58. class TLS_CHACHA20_POLY1305_SHA256(TLS_AEAD_Cipher):
  59. KEY_LEN = 32
  60. MAC_LEN = 16
  61. tls_hash = tls_sha256
  62. def cipher(self):
  63. ""
  64. def decrypt(self, ciphertext, associated_data):
  65. nonce = self.get_nonce()
  66. return nacl.bindings.crypto_aead_chacha20poly1305_ietf_decrypt(
  67. bytes(ciphertext), associated_data, nonce, self.key
  68. )
  69. def encrypt(self, plaintext, associated_data):
  70. nonce = self.get_nonce()
  71. return nacl.bindings.crypto_aead_chacha20poly1305_ietf_encrypt(
  72. bytes(plaintext), associated_data, nonce, self.key
  73. )
  74. class TLS_AES_128_GCM_SHA256(TLS_AEAD_Cipher):
  75. KEY_LEN = 16
  76. MAC_LEN = 16
  77. tls_hash = tls_sha256
  78. def cipher(self):
  79. return AES.new(
  80. self.key, AES.MODE_GCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
  81. )
  82. class TLS_AES_256_GCM_SHA384(TLS_AEAD_Cipher):
  83. KEY_LEN = 32
  84. MAC_LEN = 16
  85. tls_hash = tls_sha384
  86. def cipher(self):
  87. return AES.new(
  88. self.key, AES.MODE_GCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
  89. )
  90. class TLS_AES_128_CCM_SHA256(TLS_AEAD_Cipher):
  91. KEY_LEN = 16
  92. MAC_LEN = 16
  93. tls_hash = tls_sha256
  94. def cipher(self):
  95. return AES.new(
  96. self.key, AES.MODE_CCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
  97. )
  98. class TLS_AES_128_CCM_8_SHA256(TLS_AEAD_Cipher):
  99. tls_hash = tls_sha256
  100. KEY_LEN = 16
  101. MAC_LEN = 8
  102. def cipher(self):
  103. return AES.new(
  104. self.key, AES.MODE_CCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
  105. )