Skip to content

Conversation

@hustliyilin
Copy link
Contributor

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.

So the EVP_PKEY_set_alias_type API is important for people who want to use cryptography with using SM2 algorithms. Therefore, we need to export EVP_PKEY_set_alias_type in FUNCTIONS.

Fixes: #7934
Signed-off-by: YiLin.Li [email protected]

@reaperhulk
Copy link
Member

This is failing compilation in openssl 3 as well as boring and libre. However, I don’t really want to add random bindings that we don’t use in cryptography itself. There have been some limited attempts to land explicit SM2 support (#5894) in cryptography in the past and it would be better to do that rather than add bindings that we’re likely to remove in a future release if we aren’t aware of any consumers.

@reaperhulk
Copy link
Member

What’s the correct way to do this in openssl 3? Are you interested in contributing a public SM2 API? Or are you using this within pyopenssl (where we should also have public APIs if needed)?

@hustliyilin
Copy link
Contributor Author

hustliyilin commented Dec 26, 2022

This is failing compilation in openssl 3 as well as boring and libre. However, I don’t really want to add random bindings that we don’t use in cryptography itself. There have been some limited attempts to land explicit SM2 support (#5894) in cryptography in the past and it would be better to do that rather than add bindings that we’re likely to remove in a future release if we aren’t aware of any consumers.

Hi, @reaperhulk ,

Thanks for your review. Now I fix the failing compilation error in openssl 3 as well as boring and libre.

The mainstream cryptography libraries openssl, libgcrypt, cryptcpp, and the Linux kernel all support SM2. SM2 is widely used in China and is mandatory in many scenarios. So It may be necessary for cryptography to support it for python users.

After applying this patch to cryptography with OpenSSL 1.1.1, we can add the following patch in pyopenssl to use SM2 sign

diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py
index eda4af6..6dd1273 100644
--- a/src/OpenSSL/crypto.py
+++ b/src/OpenSSL/crypto.py
@@ -76,6 +76,8 @@ TYPE_DSA = _lib.EVP_PKEY_DSA
 TYPE_DH = _lib.EVP_PKEY_DH
 TYPE_EC = _lib.EVP_PKEY_EC

+NID_sm2 = 1172
+EVP_PKEY_SM2 = NID_sm2

 class Error(Exception):
     """
@@ -3016,6 +3018,9 @@ def sign(pkey, data, digest):
     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 :
+            _lib.EVP_PKEY_set_alias_type(pkey._pkey, EVP_PKEY_SM2)
     md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
     md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)

--
2.31.1

@hustliyilin
Copy link
Contributor Author

hustliyilin commented Dec 26, 2022

What’s the correct way to do this in openssl 3? Are you interested in contributing a public SM2 API? Or are you using this within pyopenssl (where we should also have public APIs if needed)?

Hi @reaperhulk

As for OpenSSL 3.x, The function EVP_PKEY_set_alias_type() was removed in OpenSSL 3.0 according to the document.

C48CAFBB-9382-497b-BF6C-B410B14E6C70

and OpenSSL 3.x can use EVP_PKEY_assign_EC_KEY() to look at the curve name id to determine if the passed EC_KEY is an SM2(7) key, and will set the EVP_PKEY type to EVP_PKEY_SM2 in that case, instead of EVP_PKEY_EC. according to the document.

image

And I'll test it as soon as possible with OpenSSL 3.x and give you answer.

@hustliyilin
Copy link
Contributor Author

What’s the correct way to do this in openssl 3? Are you interested in contributing a public SM2 API? Or are you using this within pyopenssl (where we should also have public APIs if needed)?

Hi @reaperhulk

As for OpenSSL 3.x, The function EVP_PKEY_set_alias_type() was removed in OpenSSL 3.0 according to the document.

C48CAFBB-9382-497b-BF6C-B410B14E6C70

and OpenSSL 3.x can use EVP_PKEY_assign_EC_KEY() to look at the curve name id to determine if the passed EC_KEY is an SM2(7) key, and will set the EVP_PKEY type to EVP_PKEY_SM2 in that case, instead of EVP_PKEY_EC. according to the document.

image

And I'll test it as soon as possible with OpenSSL 3.x and give you answer.

Hi @reaperhulk

With OpenSSL 3.x, we don't need to modify cryptography and pyopenssl any more to use SM2.
You can following the steps

  1. Generate the SM2 key and cert
openssl ecparam -genkey -name SM2 -out private.pem
openssl req -new -x509 -days 36500 -key private.pem -out cert.crt -sm3 -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Alibaba/OU=OS/CN=CA/[email protected]"
  1. Install cryptography and pyopenssl

  2. use the testcase to sign and verify with sm2-with-sm3 using your SM2 key and cert(./test.py [private_key_file] [cert_file])

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys

from OpenSSL.crypto import load_certificate, load_privatekey
from OpenSSL.crypto import FILETYPE_PEM
from OpenSSL.crypto import (
    sign,
    verify,
)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: ./test.py [private_key_file] [cert_file]")
        exit()

    private_key_file = open(sys.argv[1], 'rb')
    if not private_key_file:
        print("fail to open private_key_file")
        exit()
    private_key = private_key_file.read()

    cert_file = open(sys.argv[2], 'rb')
    if not cert_file:
        print("fail to open cert_file")
        exit()
    cert = cert_file.read()

    priv_key = load_privatekey(FILETYPE_PEM, private_key)
    cert = load_certificate(FILETYPE_PEM, cert)
    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."
    )
    sig = sign(priv_key, content, "sm3")
    verify(cert, sig, content, "sm3")

so we just need to solve the SM2 problem with openssl 1.1.1x. If you have any questions, please let me know.

#if !CRYPTOGRAPHY_IS_LIBRESSL && !CRYPTOGRAPHY_IS_BORINGSSL && \
!CRYPTOGRAPHY_OPENSSL_300_OR_GREATER
int EVP_PKEY_set_alias_type(EVP_PKEY *, int);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be conditionally removed, as you can see right below with scrypt -- you'll also need to edit _conditional.py.

Copy link
Contributor Author

@hustliyilin hustliyilin Dec 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be conditionally removed, as you can see right below with scrypt -- you'll also need to edit _conditional.py.

Thanks for your review. EVP_PKEY_set_alias_type is a function only for OpenSSL 1.1.1, And there are failing compilation in openssl 3 as well as boring and libre . So we need to add some conditions to judge the type of openssl. But after adding the conditional judgment,it can't find the corresponding function symbol(EVP_PKEY_set_alias_type) in _openssl.abi3.so with OpenSSL 1.1.1. Could you give me some advice? Thanks a lot.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our bindings require that you put the declaration in the FUNCTIONS section. CUSTOMIZATIONS is used to handle cases where the declaration may not always work.

You should look at how we do this with Cryptography_HAS_SCRYPT. We add EVP_PBE_scrypt to FUNCTIONS, then create Cryptography_HAS_SCRYPT and set its value based on whether the function is available or not (along with a null func ptr declaration if it is not), and then we have a section in _conditional.py that removes the symbol from the Python object if it is unavailable.

Copy link
Contributor Author

@hustliyilin hustliyilin Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our bindings require that you put the declaration in the FUNCTIONS section. CUSTOMIZATIONS is used to handle cases where the declaration may not always work.

You should look at how we do this with Cryptography_HAS_SCRYPT. We add EVP_PBE_scrypt to FUNCTIONS, then create Cryptography_HAS_SCRYPT and set its value based on whether the function is available or not (along with a null func ptr declaration if it is not), and then we have a section in _conditional.py that removes the symbol from the Python object if it is unavailable.

Thank you very much for your help @reaperhulk . Now I have modified the codes according to your suggestion, and I can see the function symbol EVP_PKEY_set_alias_type in the _openssl.abi3.so with openssl 1.1.1. Besides, CI/CD shows that it doesn't affect other versions of openssl.

a08236ef69a37cb2362c2384904a58b4

In addition, I will submit the pyopenssl PR mentioned above to pyopenssl as soon as possible in the past two days, and then I will let you know, Thanks again @reaperhulk .

@hustliyilin hustliyilin force-pushed the main branch 4 times, most recently from 66ca192 to 90193f3 Compare December 27, 2022 04:27
@reaperhulk
Copy link
Member

@hustliyilin Do you plan to submit a PR to pyOpenSSL to call this function and add a test to verify it's working as expected? I saw your example code above, but I don't want to merge this unless you plan to finish the work on the other project.

I'd prefer we add SM2 signing to cryptography since we generally tell users to only use pyOpenSSL for non-TLS uses if cryptography is missing a feature, but that's more work.

@hustliyilin
Copy link
Contributor Author

hustliyilin commented Dec 27, 2022

compilation error

@reaperhulk Yes. From the example I gave you can see that I will submit a patch to pyopenssl. However, from the patch I gave, you can see that pyopenssl relies on cryptography, and cryptography needs to provide the function symbol EVP_PKEY_set_alias_type firstly and only then I can initiate the pyopenssl PR.

EVP_PKEY_set_alias_type and other sm2 functions have been implemented in openssl. cryptography can simply export the functions of openssl rather than reimplement them. In other words, all we need to do is exporting corresponding function symbols in _openssl.abi3.so

This is what this PR wants to do. But at present, this PR seems to have some problems, and I am still processing and fixing them

@hustliyilin hustliyilin force-pushed the main branch 2 times, most recently from 89c7012 to b011013 Compare December 28, 2022 03:31
Copy link
Member

@reaperhulk reaperhulk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you need to run black + I have one suggested change.

…IONS

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.

So the EVP_PKEY_set_alias_type API is important for people who want to use cryptography
with using SM2 algorithms. Therefore, we need to export EVP_PKEY_set_alias_type in FUNCTIONS.

Signed-off-by: YiLin.Li <[email protected]>
@hustliyilin
Copy link
Contributor Author

Looks like you need to run black + I have one suggested change.

Thanks a lot. I used black to format the codes and all CI/CDs passed.

@reaperhulk reaperhulk merged commit c28bfb3 into pyca:main Dec 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Export EVP_PKEY_set_alias_type in FUNCTIONS to support to use SM2 algorithms

3 participants