From 03b62074a8834264e60de78c2213efe76ca108e2 Mon Sep 17 00:00:00 2001 From: "YiLin.Li" Date: Wed, 28 Dec 2022 16:05:58 +0800 Subject: [PATCH] src/OpenSSL/crypto.py: support SM2 sign with OpenSSL 1.1.1x In openssl 1.1.1 docs/man3/EVP_PKEY_set1_RSA.pod (https://github.com/openssl/openssl/blob/OpenSSL_1_1_1/doc/man3/EVP_PKEY_set1_RSA.pod) The EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) API is possible to convert it to using SM2 algorithms After loading an ECC key. Besides, pyca/cryptography support to export `The EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) API` in https://github.com/pyca/cryptography/commit/c28bfb352ab1f390900ef92856a9570aadd5fe2c . So in pyopenssl, we can support SM2 sign with OpenSSL 1.1.1x and pyca/cryptography. Signed-off-by: YiLin.Li --- src/OpenSSL/crypto.py | 19 +++++++++++++++++++ tests/test_crypto.py | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py index 8b1276906..cd7a4e356 100644 --- a/src/OpenSSL/crypto.py +++ b/src/OpenSSL/crypto.py @@ -97,6 +97,9 @@ TYPE_DH: int = _lib.EVP_PKEY_DH TYPE_EC: int = _lib.EVP_PKEY_EC +NID_sm2 = 1172 +EVP_PKEY_SM2 = NID_sm2 + class Error(Exception): """ @@ -3104,6 +3107,22 @@ def sign(pkey: PKey, data: Union[str, bytes], digest: str) -> bytes: if digest_obj == _ffi.NULL: raise ValueError("No such digest method") + if ( + _lib.OPENSSL_VERSION_NUMBER < 0x30000000 + and _lib.EVP_PKEY_id(pkey._pkey) == _lib.EVP_PKEY_EC + ): + if ( + _lib.EC_GROUP_get_curve_name( + _lib.EC_KEY_get0_group(_lib.EVP_PKEY_get1_EC_KEY(pkey._pkey)) + ) + == NID_sm2 + ): + if hasattr(_lib, "EVP_PKEY_set_alias_type"): + _lib.EVP_PKEY_set_alias_type(pkey._pkey, EVP_PKEY_SM2) + else: + print("The SM2 Signing isn't enable in current OpenSSL 1.1.x") + return b"" + md_ctx = _lib.EVP_MD_CTX_new() md_ctx = _ffi.gc(md_ctx, _lib.EVP_MD_CTX_free) diff --git a/tests/test_crypto.py b/tests/test_crypto.py index 4b63fa2c0..a865bcffa 100644 --- a/tests/test_crypto.py +++ b/tests/test_crypto.py @@ -787,6 +787,15 @@ def normalize_privatekey_pem(pem): Td8GMrwKz0557OxxtKN6uVVy4ACFMqEw0zN/KJI1vxc9 -----END CERTIFICATE-----""" +sm2_root_key_pem = b"""-----BEGIN EC PARAMETERS----- +BggqgRzPVQGCLQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEII/sRQnfpXCVx5kjmRbPp7KGgwJlOCx0kBX2Tr2lXrM2oAoGCCqBHM9V +AYItoUQDQgAEkZX7gPPNGa0uwJMjTCBgVxlTD2krqPL1rZg2z9HLg3wnH06IxQ8r +3su/VOmyoYBLBYcEjI7GSzvBy6ynX1ZDwA== +-----END EC PRIVATE KEY-----""" + rsa_p_not_prime_pem = """ -----BEGIN RSA PRIVATE KEY----- MBsCAQACAS0CAQcCAQACAQ8CAQMCAQACAQACAQA= @@ -4397,6 +4406,20 @@ def test_sign_verify_ecdsa(self): sig = sign(priv_key, content, "sha256") verify(cert, sig, content, "sha256") + def test_sign_sm2(self): + """ + `sign` generates a SM2 cryptographic signature + """ + content = ( + b"It was a bright cold day in April, and the clocks were striking " + b"thirteen. Winston Smith, his chin nuzzled into his breast in an " + b"effort to escape the vile wind, slipped quickly through the " + b"glass doors of Victory Mansions, though not quickly enough to " + b"prevent a swirl of gritty dust from entering along with him." + ) + priv_key = load_privatekey(FILETYPE_PEM, sm2_root_key_pem) + _ = sign(priv_key, content, "sm3") + def test_sign_nulls(self): """ `sign` produces a signature for a string with embedded nulls.