diff --git a/lib/Crypto/PublicKey/ECC.py b/lib/Crypto/PublicKey/ECC.py index 1d104a91a..b9a4cba92 100644 --- a/lib/Crypto/PublicKey/ECC.py +++ b/lib/Crypto/PublicKey/ECC.py @@ -456,6 +456,52 @@ def init_ed448(): del init_ed448 +sm2_names = ["sm2", "sm2p256v1"] + + +def init_sm2p256v1(): + p = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF + b = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93 + order = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123 + Gx = 0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7 + Gy = 0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0 + + p256_modulus = long_to_bytes(p, 32) + p256_b = long_to_bytes(b, 32) + p256_order = long_to_bytes(order, 32) + + ec_p256_context = VoidPointer() + result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(), + c_uint8_ptr(p256_modulus), + c_uint8_ptr(p256_b), + c_uint8_ptr(p256_order), + c_size_t(len(p256_modulus)), + c_ulonglong(getrandbits(64)) + ) + if result: + raise ImportError("Error %d initializing sm2p256v1 context" % result) + + context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_free_context) + p256 = _Curve(Integer(p), + Integer(b), + Integer(order), + Integer(Gx), + Integer(Gy), + None, + 256, + "1.2.156.10197.1.301", # China GM Standards Committee + context, + "sm2p256v1", + None, + "sm2") + global sm2_names + _curves.update(dict.fromkeys(sm2_names, p256)) + + +init_sm2p256v1() +del init_sm2p256v1 + + class UnsupportedEccFeature(ValueError): pass @@ -701,6 +747,11 @@ def __rmul__(self, left_hand): _curves.update(dict.fromkeys(ed448_names, ed448)) del ed448_G, ed448, ed448_names +sm2p256_G = EccPoint(_curves['sm2'].Gx, _curves['sm2'].Gy, "sm2") +sm2p256 = _curves['sm2']._replace(G=sm2p256_G) +_curves.update(dict.fromkeys(sm2_names, sm2p256)) +del sm2p256_G, sm2p256, sm2_names + class EccKey(object): r"""Class defining an ECC key. diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py b/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py index eb53c5761..e6497ee74 100644 --- a/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py +++ b/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py @@ -163,6 +163,19 @@ def create_ref_keys_ed448(): return (key, key.public_key()) +def create_ref_keys_sm2(): + key_len = 32 + key_lines = load_file("ecc_sm2.txt").splitlines() + private_key_d = bytes_to_long(compact(key_lines[2:5])) + public_key_xy = compact(key_lines[6:11]) + assert bord(public_key_xy[0]) == 4 # Uncompressed + public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) + public_key_y = bytes_to_long(public_key_xy[key_len+1:]) + + return (ECC.construct(curve="sm2", d=private_key_d), + ECC.construct(curve="sm2", point_x=public_key_x, point_y=public_key_y)) + + # Create reference key pair # ref_private, ref_public = create_ref_keys_p521() @@ -824,6 +837,117 @@ def test_import_openssh_private_password(self): self.assertEqual(key, key_old) +class TestImport_SM2(unittest.TestCase): + + def __init__(self, *args, **kwargs): + super(TestImport_SM2, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_sm2() + + def test_import_public_der(self): + key_file = load_file("ecc_sm2_public.der") + + key = ECC._import_subjectPublicKeyInfo(key_file) + self.assertEqual(self.ref_public, key) + + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) + + def test_import_sec1_uncompressed(self): + key_file = load_file("ecc_sm2_public.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name='sm2') + self.assertEqual(self.ref_public, key) + + def test_import_sec1_compressed(self): + key_file = load_file("ecc_sm2_public_compressed.der") + value = extract_bitstring_from_spki(key_file) + key = ECC.import_key(key_file, curve_name='sm2') + self.assertEqual(self.ref_public, key) + + def test_import_rfc5915_der(self): + key_file = load_file("ecc_sm2_private.der") + + key = ECC._import_rfc5915_der(key_file, None) + self.assertEqual(self.ref_private, key) + + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) + + def test_import_private_pkcs8_clear(self): + key_file = load_file("ecc_sm2_private_p8_clear.der") + + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_private, key) + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) + + def test_import_private_pkcs8_in_pem_clear(self): + key_file = load_file("ecc_sm2_private_p8_clear.pem") + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) + + def test_import_private_pkcs8_encrypted_1(self): + key_file = load_file("ecc_sm2_private_p8.der") + + key = ECC._import_der(key_file, "secret") + self.assertEqual(self.ref_private, key) + + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) + + def test_import_private_pkcs8_encrypted_2(self): + key_file = load_file("ecc_sm2_private_p8.pem") + + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) + + def test_import_x509_der(self): + key_file = load_file("ecc_sm2_x509.der") + + key = ECC._import_der(key_file, None) + self.assertEqual(self.ref_public, key) + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) + + def test_import_public_pem(self): + key_file = load_file("ecc_sm2_public.pem") + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) + + def test_import_private_pem(self): + key_file = load_file("ecc_sm2_private.pem") + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_private, key) + + def test_import_private_pem_encrypted(self): + for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": + key_file = load_file("ecc_sm2_private_enc_%s.pem" % algo) + + key = ECC.import_key(key_file, "secret") + self.assertEqual(self.ref_private, key) + + key = ECC.import_key(tostr(key_file), b"secret") + self.assertEqual(self.ref_private, key) + + def test_import_x509_pem(self): + key_file = load_file("ecc_sm2_x509.pem") + + key = ECC.import_key(key_file) + self.assertEqual(self.ref_public, key) + + + class TestExport_P192(unittest.TestCase): def __init__(self, *args, **kwargs): @@ -2623,6 +2747,258 @@ def test_error_params1(self): passphrase="secret") +class TestExport_SM2(unittest.TestCase): + + def __init__(self, *args, **kwargs): + super(TestExport_SM2, self).__init__(*args, **kwargs) + self.ref_private, self.ref_public = create_ref_keys_sm2() + + def test_export_public_der_uncompressed(self): + key_file = load_file("ecc_sm2_public.der") + + encoded = self.ref_public._export_subjectPublicKeyInfo(False) + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="DER", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_der_compressed(self): + key_file = load_file("ecc_sm2_public.der") + pub_key = ECC.import_key(key_file) + key_file_compressed = pub_key.export_key(format="DER", compress=True) + + key_file_compressed_ref = load_file("ecc_sm2_public_compressed.der") + self.assertEqual(key_file_compressed, key_file_compressed_ref) + + def test_export_public_sec1_uncompressed(self): + key_file = load_file("ecc_sm2_public.der") + value = extract_bitstring_from_spki(key_file) + + encoded = self.ref_public.export_key(format="SEC1") + self.assertEqual(value, encoded) + + def test_export_public_sec1_compressed(self): + key_file = load_file("ecc_sm2_public.der") + encoded = self.ref_public.export_key(format="SEC1", compress=True) + + key_file_compressed_ref = load_file("ecc_sm2_public_compressed.der") + value = extract_bitstring_from_spki(key_file_compressed_ref) + self.assertEqual(value, encoded) + + def test_export_rfc5915_private_der(self): + key_file = load_file("ecc_sm2_private.der") + + encoded = self.ref_private._export_rfc5915_private_der() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_clear(self): + key_file = load_file("ecc_sm2_private_p8_clear.der") + + encoded = self.ref_private._export_pkcs8() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="DER") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_encrypted(self): + encoded = self.ref_private._export_pkcs8(passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) + + decoded = ECC._import_pkcs8(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key(format="DER", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_public_pem_uncompressed(self): + key_file = load_file("ecc_sm2_public.pem", "rt").strip() + + encoded = self.ref_private._export_public_pem(False) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_public.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + encoded = self.ref_public.export_key(format="PEM", compress=False) + self.assertEqual(key_file, encoded) + + def test_export_public_pem_compressed(self): + key_file = load_file("ecc_sm2_public.pem", "rt").strip() + pub_key = ECC.import_key(key_file) + + key_file_compressed = pub_key.export_key(format="PEM", compress=True) + key_file_compressed_ref = load_file("ecc_sm2_public_compressed.pem", "rt").strip() + + self.assertEqual(key_file_compressed, key_file_compressed_ref) + + def test_export_private_pem_clear(self): + key_file = load_file("ecc_sm2_private.pem", "rt").strip() + + encoded = self.ref_private._export_private_pem(None) + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) + self.assertEqual(key_file, encoded) + + def test_export_private_pem_encrypted(self): + encoded = self.ref_private._export_private_pem(passphrase=b"secret") + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "EC PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM", + passphrase="secret", + use_pkcs8=False) + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_export_private_pkcs8_and_pem_1(self): + # PKCS8 inside PEM with both unencrypted + key_file = load_file("ecc_sm2_private_p8_clear.pem", "rt").strip() + + encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() + self.assertEqual(key_file, encoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM") + self.assertEqual(key_file, encoded) + + def test_export_private_pkcs8_and_pem_2(self): + # PKCS8 inside PEM with PKCS8 encryption + encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + + # This should prove that the output is password-protected + self.assertRaises(ValueError, ECC.import_key, encoded) + + assert "ENCRYPTED PRIVATE KEY" in encoded + + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + # --- + + encoded = self.ref_private.export_key(format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + decoded = ECC.import_key(encoded, "secret") + self.assertEqual(self.ref_private, decoded) + + def test_prng(self): + # Test that password-protected containers use the provided PRNG + encoded1 = self.ref_private.export_key(format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng()) + encoded2 = self.ref_private.export_key(format="PEM", + passphrase="secret", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", + randfunc=get_fixed_prng()) + self.assertEqual(encoded1, encoded2) + + # --- + + encoded1 = self.ref_private.export_key(format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng()) + encoded2 = self.ref_private.export_key(format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng()) + self.assertEqual(encoded1, encoded2) + + def test_byte_or_string_passphrase(self): + encoded1 = self.ref_private.export_key(format="PEM", + use_pkcs8=False, + passphrase="secret", + randfunc=get_fixed_prng()) + encoded2 = self.ref_private.export_key(format="PEM", + use_pkcs8=False, + passphrase=b"secret", + randfunc=get_fixed_prng()) + self.assertEqual(encoded1, encoded2) + + def test_error_params1(self): + # Unknown format + self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") + + # Missing 'protection' parameter when PKCS#8 is used + self.ref_private.export_key(format="PEM", passphrase="secret", + use_pkcs8=False) + self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", + passphrase="secret") + + # DER format but no PKCS#8 + self.assertRaises(ValueError, self.ref_private.export_key, format="DER", + passphrase="secret", + use_pkcs8=False, + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + + # Incorrect parameters for public keys + self.assertRaises(ValueError, self.ref_public.export_key, format="DER", + use_pkcs8=False) + + # Empty password + self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", + passphrase="", use_pkcs8=False) + self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", + passphrase="", + protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") + + def test_compressed_curve(self): + + # Compressed sm2 curve (Y-point is even) + pem1 = """-----BEGIN EC PRIVATE KEY----- + MFcCAQEEIN509xPy6uRGyYkiy0t1VBG7kGewTnEZGp6QEUR3guX3oAoGCCqBHM9V + AYItoSQDIgACVf1bhKVDUXZ3yWD6LZ41i/4yaJzWtEuujrCw+4rTIfU= + -----END EC PRIVATE KEY-----""" + + # Compressed sm2 curve (Y-point is odd) + pem2 = """-----BEGIN EC PRIVATE KEY----- + MFcCAQEEIKaNq594sjs8C65Pn+B4pjFPc7nN5ZIxCjTLSZXCRG4ioAoGCCqBHM9V + AYItoSQDIgADL4goDzlQBtdaSRyKWiWmYyyBGR7z/btnQVQlRKG66nU= + -----END EC PRIVATE KEY-----""" + + key1 = ECC.import_key(pem1) + low16 = int(key1.pointQ.y % 65536) + self.assertEqual(low16, 0xF810) + + key2 = ECC.import_key(pem2) + low16 = int(key2.pointQ.y % 65536) + self.assertEqual(low16, 0x6C81) + + def get_tests(config={}): tests = [] tests += list_test_cases(TestImport) @@ -2634,6 +3010,7 @@ def get_tests(config={}): tests += list_test_cases(TestImport_P521) tests += list_test_cases(TestImport_Ed25519) tests += list_test_cases(TestImport_Ed448) + tests += list_test_cases(TestImport_SM2) tests += list_test_cases(TestExport_P192) tests += list_test_cases(TestExport_P224) @@ -2642,6 +3019,7 @@ def get_tests(config={}): tests += list_test_cases(TestExport_P521) tests += list_test_cases(TestExport_Ed25519) tests += list_test_cases(TestExport_Ed448) + tests += list_test_cases(TestExport_SM2) except MissingTestVectorException: pass diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2.txt b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2.txt new file mode 100644 index 000000000..757a95776 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2.txt @@ -0,0 +1,17 @@ +Private-Key: (256 bit) +priv: + 77:3a:9e:2d:35:5c:0d:4b:e5:6e:27:15:26:2f:06: + a5:25:bf:0d:d8:27:09:7e:d6:f6:a6:f5:30:89:46: + 23:3a +pub: + 04:a9:4a:d8:10:0d:2e:94:14:de:ce:60:e1:44:7c: + 55:83:c3:d1:b5:53:6e:ff:58:b1:a4:5d:d8:97:92: + 98:37:af:33:a7:3a:a8:25:23:66:eb:0e:f3:5b:e4: + 1f:3f:0c:6a:b3:4b:e5:bc:5e:9a:80:87:93:e3:5c: + c0:41:ce:aa:42 +ASN1 OID: SM2 +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHc6ni01XA1L5W4nFSYvBqUlvw3YJwl+1vam9TCJRiM6oAoGCCqBHM9V +AYItoUQDQgAEqUrYEA0ulBTezmDhRHxVg8PRtVNu/1ixpF3Yl5KYN68zpzqoJSNm +6w7zW+QfPwxqs0vlvF6agIeT41zAQc6qQg== +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.der new file mode 100644 index 000000000..a60b9d05b Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.pem new file mode 100644 index 000000000..798a85b9b --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHc6ni01XA1L5W4nFSYvBqUlvw3YJwl+1vam9TCJRiM6oAoGCCqBHM9V +AYItoUQDQgAEqUrYEA0ulBTezmDhRHxVg8PRtVNu/1ixpF3Yl5KYN68zpzqoJSNm +6w7zW+QfPwxqs0vlvF6agIeT41zAQc6qQg== +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes128.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes128.pem new file mode 100644 index 000000000..c3f7d39a5 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes128.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,6321FAC28DC895819922B05F87D24466 + +YcI8iLbS7x9jYD5GnZnOr1Ch7MgVmHxhEp05XD5OfWuWD7+o2hiF9Vkx66sKlkUM +zRJXNgA4+k3mAYBr000q/PZFi0Vwi1k6S/bf7fsYd3uWSacldGEDhx0P/OaXMH6X +OhwukTUfQCpmMqXT9RjWYxR9ElTGDoOmWhen/HUnSoU= +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes192.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes192.pem new file mode 100644 index 000000000..cd9fd1b14 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes192.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-192-CBC,B34E427A65739B48DC15C5EEB0824EC4 + +/TT6ouJarBwl6S2GBzNMkoxAtwhiAGJUvgMgSSWvp6iBtlzRo6mKzTrGlocyB4PH +UKzTMHXQotFhkBjGPevQT6C+XzuvCM0tvOAWy3pRYXCBuYCB3D59/Xsu5qTlAi6U +4ddGec3JrzN8odr9FSE9Um9mGIUFCryJW84urEL5lCQ= +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256.pem new file mode 100644 index 000000000..1fe697363 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,DEE3ACA0613D915E64C9463AD8737713 + +hTZ/hjjnhM7iiagnO8xN70ONKIVz59yyY/XWE0Q9X+mZ0k6qjDm53f9pppvchGmu +Yz8zulJxMSHNL7lIp/Up4fXPN7gHhEOD36w8I0/ZRqzbKFyBFp3WYTn1GdrmZ4rk +A5nOr+Pf1xv3lR/Hkv1OQzLESNl9s3h+aFsgxTul+zI= +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256_gcm.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256_gcm.pem new file mode 100644 index 000000000..00753a746 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_aes256_gcm.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: id-aes256-GCM,7C4DC2C82DD19AE204A5631D + +m76/n6sPDF+VPRpZaVr2vH+lsgCpgDBMceXiCDnpFcIssB3VSxEah3aVx1Ki3Pux +oFGLUhHtcNZnCjpT1+MBgL8y9A0ZgH6AtgVTbO/0yfb2dIY5k7Bkgg7bm/xvd7BT +/0v5vizwwcrqGNm3ND3AmxG+ZNc1HuV6sQ== +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_des3.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_des3.pem new file mode 100644 index 000000000..f644309b0 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_enc_des3.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,E1FB36B75446E0B6 + +hTSTwbcaVT36XNY5szu4Tv41pdOrwa1VH5aiTNtsPyO4maGnsubkURaMZPcYCP+q +ipdG7WckG/FaJyGzyhjMMK12qXPhRolFNZgZIe4Gf1t5rjirx4oeSQTTDgUrggoQ +3l0qD/9jwO4cEUX/Wq3t6bBsGs42k4hHslWeaLmj5CA= +-----END EC PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.der new file mode 100644 index 000000000..b04a08e7c Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.pem new file mode 100644 index 000000000..030b4be75 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8.pem @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjbYOY5GSvTlgICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEK+1rJGQVS025dmSzynCJecEgZDr +i0CdXhse+hrokBc/xrUV6FfNc/AI5aV/jOwH4tRg2Mi9/qXFRoE0t1TMvqZaf8W3 +PssJgTNcdUYkoVbp8CwxkoTLv6blyLHu7YuQBDsTUGsy/ECLVyyDoPEDlXjOEJKx +CeVBSKwK14HDnSIGaGpNDoMnjIwY5aS6XVg1YQ1M33lQ1lnJErS190Pi7/qyCeA= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.der new file mode 100644 index 000000000..8a7937e25 Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.pem new file mode 100644 index 000000000..471454ec6 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_private_p8_clear.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgdzqeLTVcDUvlbicV +Ji8GpSW/DdgnCX7W9qb1MIlGIzqhRANCAASpStgQDS6UFN7OYOFEfFWDw9G1U27/ +WLGkXdiXkpg3rzOnOqglI2brDvNb5B8/DGqzS+W8XpqAh5PjXMBBzqpC +-----END PRIVATE KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.der new file mode 100644 index 000000000..fda1a2f27 Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.pem new file mode 100644 index 000000000..55988b03e --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEqUrYEA0ulBTezmDhRHxVg8PRtVNu +/1ixpF3Yl5KYN68zpzqoJSNm6w7zW+QfPwxqs0vlvF6agIeT41zAQc6qQg== +-----END PUBLIC KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.der new file mode 100644 index 000000000..27998f7ae Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.pem new file mode 100644 index 000000000..765804052 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_public_compressed.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MDkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DIgACqUrYEA0ulBTezmDhRHxVg8PRtVNu +/1ixpF3Yl5KYN68= +-----END PUBLIC KEY----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.der b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.der new file mode 100644 index 000000000..f5f89010a Binary files /dev/null and b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.der differ diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.pem b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.pem new file mode 100644 index 000000000..9db353b8d --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/ecc_sm2_x509.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBmjCCAUGgAwIBAgIUVCTxcx7BKvJIRnE5hkBEm4nCdjQwCgYIKoZIzj0EAwIw +IzELMAkGA1UEBhMCR0IxFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIzMDUwOTAx +NTUwOFoXDTI0MDUwODAxNTUwOFowIzELMAkGA1UEBhMCR0IxFDASBgNVBAMMC2V4 +YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEqUrYEA0ulBTezmDh +RHxVg8PRtVNu/1ixpF3Yl5KYN68zpzqoJSNm6w7zW+QfPwxqs0vlvF6agIeT41zA +Qc6qQqNTMFEwHQYDVR0OBBYEFFzDBOKmGUqbVMTN9KUJXb/I2qMQMB8GA1UdIwQY +MBaAFFzDBOKmGUqbVMTN9KUJXb/I2qMQMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZI +zj0EAwIDRwAwRAIgd/6o6XT/9G54EwS+0cxTCqyMyuZneIjfDvzOLiVScB8CIGqm +8wY7r+Lc8FsE2YkE1henIa9raoSQqLs9/4Pt9gmO +-----END CERTIFICATE----- diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/gen_ecc_sm2.sh b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/gen_ecc_sm2.sh new file mode 100644 index 000000000..4738b63d2 --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/gen_ecc_sm2.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e +set -x + +openssl version | tee openssl_version_sm2.txt + +# Private key +openssl ecparam -name SM2 -genkey -noout -conv_form uncompressed -out ecc_sm2_private.pem +openssl ec -in ecc_sm2_private.pem -outform DER -out ecc_sm2_private.der +openssl pkcs8 -in ecc_sm2_private.der -inform DER -out ecc_sm2_private_p8_clear.der -outform DER -nocrypt -topk8 +openssl pkcs8 -in ecc_sm2_private.der -inform DER -out ecc_sm2_private_p8_clear.pem -outform PEM -nocrypt -topk8 +openssl ec -in ecc_sm2_private.pem -text -out ecc_sm2.txt + +# Encrypted private key +openssl pkcs8 -in ecc_sm2_private.der -inform DER -passout 'pass:secret' -out ecc_sm2_private_p8.der -outform DER -topk8 +openssl pkcs8 -in ecc_sm2_private.der -inform DER -passout 'pass:secret' -out ecc_sm2_private_p8.pem -outform PEM -topk8 +openssl ec -in ecc_sm2_private.pem -des3 -out ecc_sm2_private_enc_des3.pem -passout 'pass:secret' -outform PEM +openssl ec -in ecc_sm2_private.pem -aes128 -out ecc_sm2_private_enc_aes128.pem -passout 'pass:secret' -outform PEM +openssl ec -in ecc_sm2_private.pem -aes192 -out ecc_sm2_private_enc_aes192.pem -passout 'pass:secret' -outform PEM +openssl ec -in ecc_sm2_private.pem -aes256 -out ecc_sm2_private_enc_aes256.pem -passout 'pass:secret' -outform PEM +openssl ec -in ecc_sm2_private.pem -aes-256-gcm -out ecc_sm2_private_enc_aes256_gcm.pem -passout 'pass:secret' -outform PEM + +# Public key +openssl ec -in ecc_sm2_private.pem -pubout -out ecc_sm2_public.pem +openssl ec -pubin -in ecc_sm2_public.pem -outform DER -out ecc_sm2_public.der +openssl ec -pubin -in ecc_sm2_public.pem -outform DER -conv_form compressed -out ecc_sm2_public_compressed.der +openssl ec -pubin -in ecc_sm2_public.pem -outform PEM -conv_form compressed -out ecc_sm2_public_compressed.pem + +# X.509 cert +openssl req -new -key ecc_sm2_private.pem -days 365 -x509 -out ecc_sm2_x509.pem -subj '/C=GB/CN=example.com' +openssl x509 -in ecc_sm2_x509.pem -out ecc_sm2_x509.der -outform DER diff --git a/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/openssl_version_sm2.txt b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/openssl_version_sm2.txt new file mode 100644 index 000000000..e3703dacd --- /dev/null +++ b/test_vectors/pycryptodome_test_vectors/PublicKey/ECC/openssl_version_sm2.txt @@ -0,0 +1 @@ +OpenSSL 1.1.1s 1 Nov 2022