A wrapper to present a cryptography api but use the pycryptodome module.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

129 lines
5.9 KiB

  1. import unittest
  2. from cryptography.exceptions import InvalidSignature
  3. from cryptography.hazmat.backends import default_backend
  4. from cryptography.hazmat.primitives import serialization
  5. from cryptography.hazmat.primitives import hashes
  6. from cryptography.hazmat.primitives.asymmetric import ec
  7. from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
  8. from cryptography.hazmat.primitives.kdf.hkdf import HKDF
  9. class TestECC(unittest.TestCase):
  10. def test_dh(self):
  11. # slightly modified from:
  12. # https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/#elliptic-curve-key-exchange-algorithm
  13. # private keys for use in the exchange.
  14. keya = b'0\x81\x87\x02\x01\x000\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x04m0k\x02\x01\x01\x04 \x04\xa3X\xbd\x0e\xff*\x8cw\xf8\x9f\x05BD<\nY\xb3\xf1\xd2\xc1\xb0\r\x1e\xedu\x92]4M?\x01\xa1D\x03B\x00\x04P\xd9y\x92f\t\xa7x\xf3\xcf\x17O\xad\x93\xf9\x18"\t\xd3\x13*]3\xa7#\x8bH$j\xea\xfb\x8a\xd3\xb5\xee\xd9\x0f\x9c\xdb\xcc\xf1\xd7\x10\x88\x10e\x82-\x15CR\x08\xbe\x0c\x1e\x82p\x00C\xb2.O\x17\xd4'
  15. keyb = b'0\x81\x87\x02\x01\x000\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x04m0k\x02\x01\x01\x04 \xfb\xf8\xf7\x9f\xa3\xb7\xed\x8cT@`\xf6\x9c\xbbv\x0e?\x87\xb1(\xf6\xa8\xb3`\x91\xb4\x92W\xc6\xaa\xf5~\xa1D\x03B\x00\x04\xb8\xfe\xe4\x8dkukc\xa4^\x87\x98\x9c\xb9\xa8\xec\x86\xf8\xc2\x89\xaeF\xe8q\xb9q\x92I\x98n\xfe\xe3<{\x1c&R\x82\xb1\x94=\xa5h*)m/\x13\xfb\x05\x1d\x98u\xec\x1ew\xdfW\x84\xfe\x9eSl\x83'
  16. #server_private_key = ec.generate_private_key(ec.SECP256R1())
  17. #print('spk:', repr(server_private_key.private_bytes(
  18. # encoding=serialization.Encoding.DER,
  19. # format=serialization.PublicFormat.UncompressedPoint,
  20. # algorithm=None)))
  21. server_private_key = serialization.load_der_private_key(keya,
  22. None, backend=default_backend())
  23. pubpoint = server_private_key.private_numbers().public_numbers
  24. self.assertEqual(server_private_key.private_numbers(). \
  25. private_value,
  26. 2097859916579721232322403601989230314767884081400167668022347085958538411777)
  27. self.assertEqual(pubpoint.x,
  28. 36569272757924220784927781299997671003354453138026426189464987345196826688394)
  29. self.assertEqual(pubpoint.y,
  30. 95759458837377270694950453035845273914475242769728982836658929275588228093908)
  31. self.assertEqual(keya, server_private_key.private_bytes(
  32. encoding=serialization.Encoding.DER,
  33. format=serialization.PrivateFormat.PKCS8,
  34. encryption_algorithm=serialization.NoEncryption()))
  35. # In a real handshake the peer is a remote client. For this
  36. # example we'll generate another local private key though.
  37. peer_private_key = serialization.load_der_private_key(keyb,
  38. None)
  39. shared_key = server_private_key.exchange(
  40. ec.ECDH(), peer_private_key.public_key())
  41. self.assertEqual(shared_key,
  42. b'\x1a\x9f\x93c\xb0s\xa2\x15]{\xa3\xcc\xcf&Q\xd6g\x83\x86%\x7f\t\xfem@\xcb\xe9:U\x16\x07\x02')
  43. # Perform key derivation.
  44. derived_key = HKDF(algorithm=hashes.SHA256(),
  45. length=32, salt=None, info=b'handshake data', backend=None
  46. ).derive(shared_key)
  47. # And now we can demonstrate that the handshake performed in
  48. # the opposite direction gives the same final value
  49. same_shared_key = peer_private_key.exchange(
  50. ec.ECDH(), server_private_key.public_key())
  51. self.assertEqual(shared_key, same_shared_key)
  52. # Perform key derivation.
  53. same_derived_key = HKDF(algorithm=hashes.SHA256(),
  54. length=32, salt=None, info=b'handshake data',
  55. ).derive(same_shared_key)
  56. self.assertEqual(derived_key,
  57. b'\x89\r\xf7\xf0\xa6\xb9Z\xb9\xd7\xd0\x9b\x95y\xe0M\x11,\xb4\xe1Z\xe5\xa2j\xee)\xa0I\xb5Q\x18\x94\xd1')
  58. self.assertEqual(derived_key, same_derived_key)
  59. def test_decode_sig(self):
  60. sig = b"0D\x02 P\x92\xaf\xffoN\xadq\r=\x92\xb5\r\xe0l3\xf2\x80*\xdd|\xfe\xd8'\xb8\\\xe8\x94\xd6\xa1\xdb\xea\x02 \x18\x89j\xa8P\x83jk*\xb8\xa2\x15r&d\xa1\x9e\xf6\xec\xd2\xf4 \xd6\x08\x91bs\x18\xb5\x11/\x04"
  61. res = (36444202250238074078057463719437572015031876874679459625290239663827367091178, 11098302536735876471048588108325227764001515075886106999029234198831298588420)
  62. self.assertEqual(decode_dss_signature(sig), res)
  63. def test_sign(self):
  64. private_key = ec.generate_private_key(ec.SECP256R1())
  65. data = b"this is some data I'd like to sign"
  66. signature = private_key.sign(data, ec.ECDSA(hashes.SHA256()))
  67. # make sure we can decode our own signatures
  68. decode_dss_signature(signature)
  69. public_key = private_key.public_key()
  70. public_key.verify(signature, data, ec.ECDSA(hashes.SHA256()))
  71. wrongsig = bytearray(signature)
  72. wrongsig[0] ^= 1
  73. wrongsig[1] ^= 4
  74. wrongsig = bytes(wrongsig)
  75. self.assertRaises(InvalidSignature, public_key.verify, wrongsig, data, ec.ECDSA(hashes.SHA256()))
  76. def test_misc(self):
  77. keya = b'0\x81\x87\x02\x01\x000\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x04m0k\x02\x01\x01\x04 \x04\xa3X\xbd\x0e\xff*\x8cw\xf8\x9f\x05BD<\nY\xb3\xf1\xd2\xc1\xb0\r\x1e\xedu\x92]4M?\x01\xa1D\x03B\x00\x04P\xd9y\x92f\t\xa7x\xf3\xcf\x17O\xad\x93\xf9\x18"\t\xd3\x13*]3\xa7#\x8bH$j\xea\xfb\x8a\xd3\xb5\xee\xd9\x0f\x9c\xdb\xcc\xf1\xd7\x10\x88\x10e\x82-\x15CR\x08\xbe\x0c\x1e\x82p\x00C\xb2.O\x17\xd4'
  78. skey = serialization.load_der_private_key(keya,
  79. None, backend=default_backend())
  80. ckey = skey.public_key().public_bytes(
  81. encoding=serialization.Encoding.X962,
  82. format=serialization.PublicFormat.UncompressedPoint
  83. )
  84. self.assertEqual(ckey, b'\x04P\xd9y\x92f\t\xa7x\xf3\xcf\x17O\xad\x93\xf9\x18"\t\xd3\x13*]3\xa7#\x8bH$j\xea\xfb\x8a\xd3\xb5\xee\xd9\x0f\x9c\xdb\xcc\xf1\xd7\x10\x88\x10e\x82-\x15CR\x08\xbe\x0c\x1e\x82p\x00C\xb2.O\x17\xd4')
  85. pubkey = ec.EllipticCurvePublicKey.from_encoded_point(
  86. ec.SECP256R1(), ckey)
  87. self.assertTrue(isinstance(pubkey, ec.EllipticCurvePublicKey))
  88. self.assertEqual(ckey, pubkey.public_bytes(
  89. encoding=serialization.Encoding.X962,
  90. format=serialization.PublicFormat.UncompressedPoint
  91. ))