当前位置: 首页 > 工具软件 > gmssl-python > 使用案例 >

国密算法:利用python进行sm2非对称算法的实现,国密算法库gmssl的使用

干永丰
2023-12-01

我们继续来进行国密算法的演示。
本篇演示sm2非对称算法的实现,国密算法库gmssl的使用。

一 sm2算法的特点:

  • sm2: 即椭圆曲线公钥密码算法,是由国家密码管理局发布的;
  • 非对称加密算法,即有一对不一样的密钥:公钥和私钥,公钥用来加密,私钥用来解密;
  • 公钥和私钥:公钥,可以公开。私钥:不对外公开;
  • 同一个明文,同一个公钥,每次加密结果不相等;
  • 密码复杂度高,更先进,更安全,性能更快;
  • 用于替换RSA算法。很多软件都在进行国密改造,指的就是用sm1/sm2/sm3/sm4替换掉原有的加解密算法。

二sm2算法的演示:

1. 定义一个通用sm2算法类

# -*- coding: utf-8 -*-

import binascii
import re
import requests
import logging

from gmssl import sm2, func

class Sm2Tools:
    """
    通用sm2算法类
    """
    class KeyStore:
        """
        SM2 密钥对类,包含密钥对生成、获取方法
        """
        _PRIVATE_KEY = ""
        _PUBLIC_KEY = ""

        def __init__(self) -> None:
            pass

        def setKey(self, priKey: str, pubKey: str) -> bool:
            """
            简单判断密钥对格式
            :param priKey: 私钥
            :param pubKey: 公钥
            :return: bool
            """
            result = re.match(r"^[a-fA-F\d]{64}$", priKey)
            if result is None:
                logging.error("KeyStore.setKey() -> priKey is invalid.")
                return False
            result = re.match(r"^[a-fA-F\d]{128}$", pubKey)
            if result is None:
                logging.error("KeyStore.setKey() -> pubKey is invalid.")
                return False
            self._PRIVATE_KEY = priKey
            self._PUBLIC_KEY = pubKey
            return True

        def createLocal(self) -> bool:
            """
            本地创建密钥对
            :return: bool
            """

            class _Generate_SM2_Key(sm2.CryptSM2):

                #初始化
                def __init__(self, private_key=None, public_key=None, ecc_table=sm2.default_ecc_table):
                    super().__init__(private_key, public_key, ecc_table)

                #获取私钥
                def get_private_key(self):
                    if self.private_key is None:
                        self.private_key = func.random_hex(self.para_len)  # d∈[1, n-2]
                    return self.private_key

                #获取共钥
                def get_public_key(self):
                    if self.public_key is None:
                        self.public_key = self._kg(int(self.get_private_key(), 16), self.ecc_table['g'])  # P=[d]G
                    return self.public_key

            try:
                _sm2Generator = _Generate_SM2_Key()
                self._PRIVATE_KEY = _sm2Generator.get_private_key()
                self._PUBLIC_KEY = _sm2Generator.get_public_key()
                return True
            except:
                logging.error("KeyStore.createLocal() can't create the correct keys. ",
                              "Please call the Lib's Designer. ")
                return False

        def getSelf(self) -> dict:
            """
            获取创建的密钥对
            :return: dict: keyStore 格式:
            {
                "PRIVATE_KEY": "",
                "PUBLIC_KEY": ""
            }
            """
            return {
                "PRIVATE_KEY": self._PRIVATE_KEY,
                "PUBLIC_KEY": self._PUBLIC_KEY
            }

        def getPrivateKey(self) -> str:
            """
            返回公钥
            :return: str
            """
            return self._PRIVATE_KEY

        def getPublicKey(self) -> str:
            """
            返回私钥
            :return: str
            """
            return self._PUBLIC_KEY

    class SM2_Util(Exception):
        """
        SM2 加解密类
        """

        _SM2_Util = None

        def __init__(self, exception="") -> None:
            """
            构造函数
            :param exception: 默认参数,用于自定义异常
            """

            self._EXCPTION = None
            self._INIT_FLAG = False

        def setKey(self, keyStore: dict) -> bool:
            """
            初始化密钥对
            :param keyStore: dict: keyStore 格式:
                {
                    "PRIVATE_KEY": "",
                    "PUBLIC_KEY": ""
                }
            :return: bool
            """
            try:
                # 判断是否为全为英文和数字,且是 16 个字符的字符串
                # 不是,则抛出异常
                if re.match(r"^[a-fA-F\d]{64}$", keyStore["PRIVATE_KEY"]) is None:
                    raise Sm2Tools.SM2_Util(exception="SM2_Util.setKey() -> PRIVATE_KEY is invalid.")
                if re.match(r"^[a-fA-F\d]{128}$", keyStore["PUBLIC_KEY"]) is None:
                    raise Sm2Tools.SM2_Util(exception="SM2_Util.setKey() -> PUBLIC_KEY is invalid.")
            except Sm2Tools.SM2_Util as e:
                logging.error(e._EXCPTION)
                return False
            self._SM2_Util = sm2.CryptSM2(public_key=keyStore["PUBLIC_KEY"], private_key=keyStore["PRIVATE_KEY"])
            self._INIT_FLAG = True
            return True

        def getSelf(self) -> sm2.CryptSM2:
            """
            获取加解密类对象
            :return: sm2.CryptSM2 类实例
            """
            return self._SM2_Util

        def encrypt(self, data: str):
            """
            进行 SM2 加密操作
            :param data: String 格式的原文 data
            :return: String 格式的密文 enc_data
            """
            data_utf8 = data.encode("utf-8")
            enc_data = self._SM2_Util.encrypt(data_utf8)
            enc_data = binascii.b2a_hex(enc_data).decode("utf-8")
            return enc_data

        def decrypt(self, enc_data: str):
            """
            进行 SM2 解密操作
            :param enc_data: String 格式的密文 enc_data
            :return: String 格式的原文 data
            """
            enc_data = binascii.a2b_hex(enc_data.encode("utf-8"))
            dec_data = self._SM2_Util.decrypt(enc_data)
            dec_data = dec_data.decode("utf-8")
            return dec_data

2. 通用sm2算法类的调用

def test_sm2():
    # """
    # SM2 test
    # """
    keyStore = Sm2Tools.KeyStore()
    SM2_Util = Sm2Tools.SM2_Util()
    if keyStore.createLocal():
        keysDict = keyStore.getSelf()
        SM2_Util.setKey(keysDict)
        data = "哈哈,我的国密算法改造,已完成了!!!"
        print("data: " + data)
        enc_data = SM2_Util.encrypt(data)
        print("encode_data: " + enc_data)
        dec_data = SM2_Util.decrypt(enc_data)
        print("decode_data: " + dec_data)
        if data == dec_data:
            print("data == decode_data: True")
    else:
        print("create fail")

# main 
if __name__ == '__main__':
    print("main begin");
    test_sm2();
    print("main end");

运行结果:

% python3 sm2_t2.py
main begin
data: 哈哈,我的国密算法改造,已完成了!!!
encode_data: 4c37771377ad989fbe4c405a0893f8cc1ee79dc5200dc8c9a6df7eddeb90fb8b210bea842d411700c31da4470c6387bd52f1ff25bbe777f36745cc5cf70e9e5fa40a0831f5951182fe8db50c9f3350c5a68466af218b2589f05227804d3ce53ceb44a85ea52fadfc6116956dd5d5c1ee0ceb44558acc3a07fffaeb4bc8b2d93f627f360df247f57c667b0e18c72d4c9677a7deec3ba54e1533
decode_data: 哈哈,我的国密算法改造,已完成了!!!
data == decode_data: True
main end

 类似资料: