GMSSL 库应用:国密算法的 ThinkPHP8 与 Python3、Node.js 脚本开发

国密SM2算法介绍及使用

国密算法简介

国密算法是国家商用密码算法的简称。自2012年以来,国家密码管理局以《中华人民共和国密码行业标准》的方式,陆续公布了SM2/SM3/SM4等密码算法标准及其应用规范。其中"SM"代表"商密",即用于商用的、不涉及国家秘密的密码技术。

SM2、SM3、SM4是国密算法体系中三类不同用途的密码算法,由于设计目标和应用场景不同,其安全性的核心考量维度、安全基础及潜在威胁存在显著差异。以下从安全性角度对比三者的核心区别:

一、算法类型与安全基础不同

三者的本质差异源于算法类型,而不同类型的密码算法,其安全性的数学基础完全不同:

算法 类型 核心安全基础 核心功能
SM2 非对称加密算法(椭圆曲线密码,ECC) 基于椭圆曲线离散对数问题(ECDLP):在特定椭圆曲线上,已知基点 ( G ) 和点 ( kG ),求解整数 ( k ) 是计算困难的 数字签名、密钥交换、公钥加密(如身份认证、敏感信息加密)
SM3 密码哈希算法 基于抗碰撞性:难以找到两个不同的输入,使其哈希结果相同(抗碰撞);难以从哈希结果反推原始输入(抗原像) 数据完整性校验、数字签名的摘要生成(如文件校验、签名验证)
SM4 对称分组密码算法 基于混淆与扩散原理:通过复杂的轮函数变换,使明文、密钥与密文之间的关系足够复杂,难以通过密文推导明文或密钥 数据加密(如存储加密、传输加密)

二、安全强度的量化指标不同

由于算法类型不同,安全强度的衡量方式和量化标准也不同:

  • SM2 :安全强度由椭圆曲线参数决定,推荐的 SM2P256V1 曲线提供256位安全强度,相当于 3072 位 RSA 的安全级别(远高于 1024 位 RSA,后者已被认为不安全)。其安全强度主要体现在"求解椭圆曲线离散对数"的计算复杂度上。

  • SM3 :输出长度为 256 位,提供256位哈希安全强度,与 SHA-256 相当。其安全强度核心是"抗碰撞能力"------目前尚未发现有效的碰撞攻击(即找不到两个不同输入得到相同哈希值)。

  • SM4 :分组长度和密钥长度均为 128 位,提供128位对称安全强度,与 AES-128 相当。其安全强度体现在"密钥破解难度"上------暴力破解 128 位密钥需要 ( 2^{128} ) 次尝试,当前计算能力无法实现。

三、潜在安全威胁与攻击面不同

三者面临的主要安全威胁因算法特性而异:

  • SM2 的威胁

    • 核心风险并非算法本身,而是实现缺陷:如随机数生成器不安全(导致私钥可预测)、椭圆曲线参数被篡改(引入后门)、签名/加密流程不规范(如重复使用随机数)。
    • 长期威胁可能来自量子计算:虽然目前量子算法对 ECDLP 的攻击仍需亚指数时间(慢于对 RSA 的多项式时间攻击),但未来强量子计算机可能削弱其安全性。
  • SM3 的威胁

    • 核心风险是密码分析攻击:若未来发现高效的碰撞攻击算法(类似 SHA-1 被破解的方式),可能导致其失去完整性校验能力。
    • 误用风险:如将哈希值直接作为加密密钥(哈希算法不具备密钥拉伸能力)、未加盐存储哈希值(易受彩虹表攻击)。
  • SM4 的威胁

    • 核心风险是密钥管理漏洞:对称算法的安全性完全依赖密钥保密性,一旦密钥泄露,所有加密数据将被破解;此外,密钥重复使用、密钥分发不安全也会导致风险。
    • 模式误用风险:如在 ECB 模式下加密重复明文(会暴露明文规律)、CBC 模式未使用随机 IV(初始化向量)等。

四、安全性的"不可比性":场景决定价值

三者的安全性无法直接比较"强弱",因为它们服务于不同场景:

  • SM2 解决"非对称场景"的安全问题(如无预先共享密钥的加密、身份认证),其价值在于用短密钥实现高安全强度;
  • SM3 解决"完整性校验"问题,其价值在于高效生成不可逆的摘要;
  • SM4 解决"对称加密"问题,其价值在于高效加密大量数据(速度远快于非对称算法)。

总结:三者的安全性差异源于设计目标------SM2 依赖椭圆曲线难题,SM3 依赖抗碰撞性,SM4 依赖密钥保密性,它们共同构成了国密算法的安全体系,分别保障不同环节的安全需求。

SM2算法的安全性分析

SM2作为中国国家密码管理局颁布的椭圆曲线公钥密码算法(属于非对称加密算法),目前在安全性上仍然足够可靠,主要基于以下几点:

1. 算法设计的安全性基础稳固

SM2基于椭圆曲线离散对数问题(ECDLP) ,其安全性依赖于在特定椭圆曲线上求解离散对数的计算复杂度。目前,SM2推荐使用的椭圆曲线参数(如SM2P256V1)经过严格的密码学分析,尚未发现有效的多项式时间求解算法。

从数学原理上,其安全强度与256位椭圆曲线加密(ECC)相当,相当于3072位RSA加密的安全级别,远高于目前主流的1024位RSA(已被认为不安全),也满足当前大部分场景的安全需求。

2. 尚未出现有效的攻击方法

截至目前,无论是学术研究还是实际攻击案例中,都没有公开的、能有效破解SM2的方法。与RSA等传统非对称算法相比,椭圆曲线密码(包括SM2)在相同安全强度下的密钥更短(256位vs 3072位),但抗攻击能力更强。

近年来,量子计算对传统密码算法的威胁受到关注,但SM2与其他ECC算法一样,对量子计算的抵抗能力优于RSA(量子算法可在多项式时间内破解RSA,但对ECC的攻击仍需亚指数时间)。即使未来量子计算实用化,SM2也比RSA有更长的"安全窗口期"。

3. 广泛的标准化与应用验证

SM2是中国国家标准(GB/T 32918)和国家密码行业标准(GMT 0003)规定的算法,已在金融、政务、通信等关键领域大规模应用(如银行加密传输、电子签名、身份认证等)。

其设计和安全性经过了密码学界和工业界的长期验证,且随着应用范围的扩大,持续接受安全性审查和优化,进一步保障了其可靠性。

4. 安全的关键在于正确实现与使用

SM2的安全性不仅取决于算法本身,更依赖于正确的工程实现和密钥管理

  • 密钥生成必须使用密码学安全的随机数(如gmssl库的内置随机数生成器);
  • 私钥需严格保密,避免泄露或重复使用;
  • 加密/解密过程需遵循标准流程(如正确处理明文编码、密文格式等)。

历史上的密码安全事件,多源于实现漏洞(如随机数生成器不安全)而非算法本身的缺陷,因此规范使用是保障安全的核心。

在当前技术条件下,SM2仍然是一种安全可靠的加密算法,能够满足绝大多数场景的安全需求,尤其适合对安全性要求较高的政务、金融等领域。只要遵循标准实现并做好密钥管理,SM2的安全性可以得到充分保障。

随着密码学研究和计算能力的发展,未来可能需要升级到抗量子密码算法,但就目前而言,SM2仍是主流且安全的选择。

Python GMSSL 库介绍

gmssl是一个开源的Python库,实现了国密SM2、SM3、SM4等算法,提供了简单易用的API,方便开发者在Python项目中集成国密加密功能。

{% tabs test4 %}

Python GMSSL 库介绍

gmssl是一个开源的Python库,实现了国密SM2、SM3、SM4等算法,提供了简单易用的API,方便开发者在Python项目中集成国密加密功能。

SM2算法实现示例-python

SM2加密基于椭圆曲线离散对数问题(ECDLP):在特定椭圆曲线上,已知基点 G 和点 kG,求解整数 k 是计算困难的,主要解决 "非对称场景" 的安全问题(如无预先共享密钥的加密、身份认证),其价值在于用短密钥实现高安全强度;

创建SM2加密需要生成密钥对,合理正确的密钥对为hex格式或者base64格式,以下采用hex格式进行实验。

1. 配置文件(存储密钥)

创建项目根目录/config/sm2.json文件存储密钥:

json 复制代码
{
  "privateKey": "b909cbc0a0dc8f9c61450756cd6af3156fa58ae49fcc75ba9786721c46cdf9f5",
  "publickey": "04d235a280f0d8d17d09704dabcf0fd8152b1a23a620c561b9e16ebc9cd93901eab28926d8439a758c8f86ed4bfb6a3f8e20b23a949ba28013a92db40582f3b29f"
}

2. 配置加载工具

创建与/config同级目录/utils,增加方法获取sm2.json文件内容,命名为loadConfig.py

注:这份代码的主要目的是通过中间件进行读取,后续可扩展增加记录服务器、token的ACL策略及缓存节点等功能

python 复制代码
import os
import json

def load_sm2_config(config_path=None):
    if config_path is None:
        current_dir = os.path.dirname(os.path.abspath(__file__))
        config_path = os.path.join(current_dir, '..', 'config', 'sm2.json')

    try:
        with open(config_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
            return config
    except Exception as e:
        print(f"配置文件异常或者服务处于故障: {e}")
        return None

3. SM2加解密工具类

/utils目录下创建类文件gmsm2.py,实现加解密功能:

python 复制代码
from gmssl import sm2
from loadConfig import load_sm2_config


class GmSm2:
    def __init__(self):
        self.sm2_data = load_sm2_config()
        self.sm2_public_key = self.sm2_data['publickey']
        self.sm2_private_key = self.sm2_data['privateKey']

        self.sm2_crypt = sm2.CryptSM2(
            public_key=self.sm2_public_key,
            private_key=self.sm2_private_key
        )

    def encrypt(self, plain_text):
        if not plain_text:
            raise ValueError("明文不能为空")

        data = plain_text.encode('utf-8')
        encrypt_data = self.sm2_crypt.encrypt(data)
        return encrypt_data.hex()

    def decrypt(self, cipher_text_hex):
        if not cipher_text_hex:
            raise ValueError("密文不能为空")

        try:
            cipher_text = bytes.fromhex(cipher_text_hex)
            decrypt_data = self.sm2_crypt.decrypt(cipher_text)
            return decrypt_data.decode('utf-8')
        except Exception as e:
            raise ValueError(f"解密失败: {str(e)}")


# 使用示例
if __name__ == "__main__":
    try:
        sm2_util = GmSm2()
        test_text = "202019"
        print(f"=============加密前{test_text}=============\n\n\n")

        encrypted = sm2_util.encrypt(test_text)

        print(f"=============加密后{encrypted}=============\n\n\n")
        decrypted = sm2_util.decrypt(encrypted)
        print(f"=============解密后{decrypted}=============\n\n\n")

        assert test_text == decrypted, "加密解密不一致"
        print("加密解密验证成功")
    except Exception as e:
        print(f"发生错误: {e}")

运行结果

plaintext 复制代码
72a71b6c50833ab41b1daba8e95c5c6a83463679710e25ab7865e6277d523e86d91d60f8ef7185a082aa597d570f4da1015c589a1115e622ca6af926855f9222c5661ab1c5151835b87bce12a8abde5e87b038e293cf1cfd33890bd92a31897d07227a28137a

SM2算法实现示例-Thinkphp8

环境准备

  • 安装 php-8.1 以及 composer
bash 复制代码
apt install php && apt install composer
  • 安装thinkphp8环境
bash 复制代码
composer create-project topthink/think tp
  • 安装国密加密需要的库

请注意在项目根目录执行

bash 复制代码
sudo apt install php8.1-gmp && composer require lpilp/guomi

创建配置文件

创建项目根目录/config/sm2.php(需要手动创建):

php 复制代码
<?php
// +----------------------------------------------------------------------
// | SM2配置
// +----------------------------------------------------------------------

return [
    // 公钥
    'publickey' => "04d235a280f0d8d17d09704dabcf0fd8152b1a23a620c561b9e16ebc9cd93901eab28926d8439a758c8f86ed4bfb6a3f8e20b23a949ba28013a92db40582f3b29f",
    // 私钥
    'privatekey' => "b909cbc0a0dc8f9c61450756cd6af3156fa58ae49fcc75ba9786721c46cdf9f5"
];

创建公共函数文件

由于加密是常用功能,利用tp8的common方法定义公共函数,文件路径:/项目根目录/app/common.php

php 复制代码
<?php
// 应用公共文件
use Rtgm\sm\RtSm2;
use think\facade\Config;
use think\response\Json;


/**
 * SM2加密函数
 * @param string $msg 需要加密的内容
 * @return Json 返回JSON响应
 */
function sm2Encrypt(string $msg): Json
{
    $sm2 = new RtSm2();
    $public_key = Config::get("sm2.publickey");
    $encrypted = $sm2->doEncrypt($msg, $public_key);
    
    if (empty($encrypted)) {
        throw new \Exception("加密结果为空");
    }
    
    return Json([
        'code'  => 200,
        'data'  => [
            'e_msg' => $encrypted,
            'msg'   => "加密成功"
        ]
    ]);
}


/**
 * SM2解密函数
 * @param string $e_msg 需要解密的内容
 * @return Json 返回JSON响应
 */
function sm2Decrypt(string $e_msg): Json
{
    $sm2 = new RtSm2();
    $private_key = Config::get("sm2.privatekey");
    $decrypted = $sm2->doDecrypt($e_msg, $private_key);
    return Json([
        'code'  => 200,
        'data'  => [
            'e_msg' => $decrypted,
            'msg'   => "解密成功"
        ]
    ]);
}

创建控制器

创建控制器类实现加解密接口:

php 复制代码
<?php

namespace app\controller;

use app\BaseController;
use think\facade\Request;

class Index extends BaseController
{
    /**
     * 加密接口
     */
    public function encryp()
    {
        $msg = Request()->param("msg");
        $e_msg = sm2Encrypt($msg);
        return $e_msg;
    }

    /**
     * 解密接口
     */
    public function decryp()
    {
        $msg = Request()->param("msg");
        $d_msg = sm2Decrypt($msg);
        return $d_msg;
    }
}

接口测试结果

加密测试

json 复制代码
{
  "code": 200,
  "data": {
    "e_msg": "e27c3780e7069bda7082a23a489d77587ce309583ed99253f66e1d9833ed1a1d0b5ce86dc6714e9974cf258589139d7b1855e8c9fa2f2c1175ee123a95a23e9b7a394ee3a1cf399400f88e15dec5321911e79baf3390b35a9a49a3833cd6f97724342852beb5",
    "msg": "加密成功"
  }
}

解密测试

json 复制代码
{
  "code": 200,
  "data": {
    "e_msg": "202019",
    "msg": "加密成功"
  }
}

SM2算法实现示例-Node.js-gm-crypto

  • nvm 版本号0.39.7
  • node 版本号 v20.10.0

安装库

首先在你的项目根目录下执行

bash 复制代码
npm install gm-crypto && touch sm2Encrypt.js

代码如下

javascript 复制代码
const { SM2 } = require('gm-crypto');


function encryptWithPublicKey(publicKey, plaintext) {
  try {
    const ciphertext = SM2.encrypt(plaintext, publicKey, {
      inputEncoding: 'utf8',
      outputEncoding: 'base64'
    });
    return ciphertext;
  } catch (error) {
    console.error('加密失败:', error.message);
    throw error;
  }
}



function decryptWithPrivateKey(privateKey, ciphertext) {
  try {
    const plaintext = SM2.decrypt(ciphertext, privateKey, {
      inputEncoding: 'base64',
      outputEncoding: 'utf8'
    });
    return plaintext;
  } catch (error) {
    console.error('解密失败:', error.message);
    throw error;
  }
}




async function main() {
  const publicKey = '04d235a280f0d8d17d09704dabcf0fd8152b1a23a620c561b9e16ebc9cd93901eab28926d8439a758c8f86ed4bfb6a3f8e20b23a949ba28013a92db40582f3b29f';  // 例如:'04d1a1...'(长度较长,具体以你的实际公钥为准)
  const privateKey = 'b909cbc0a0dc8f9c61450756cd6af3156fa58ae49fcc75ba9786721c46cdf9f5'; 
  
  console.log('使用的密钥对:');
  console.log('公钥:', publicKey);
  console.log('私钥:', privateKey);
  
  const originalData = '202019';
  console.log('\n原始数据:', originalData);
  
  const encryptedData = encryptWithPublicKey(publicKey, originalData);
  console.log('加密后的数据:', encryptedData);
  


  const decryptedData = decryptWithPrivateKey(privateKey, encryptedData);
  console.log('解密后的数据:', decryptedData);
  


  if (originalData === decryptedData) {
    console.log('\n加密解密验证成功');
  } else {
    console.log('\n加密解密验证失败');
  }
}

main().catch(console.error);

解密如图

{% endtabs %}

一、SM2加密核心总结

SM2作为国密体系中的非对称椭圆曲线加密算法,核心价值在于以256位密钥长度实现相当于3072位RSA的安全强度,兼顾安全性与性能。其加密过程基于椭圆曲线离散对数问题(ECDLP),通过公钥加密、私钥解密的非对称机制,解决无预先共享密钥场景下的安全通信问题(如敏感信息加密、身份认证等)。

从实现角度,SM2加密需依赖密码学安全的随机数生成(确保加密过程的唯一性)、规范的密钥格式(通常为十六进制或Base64),以及符合国密标准的椭圆曲线参数(如SM2P256V1)。无论是Python的gmssl库还是ThinkPHP8中使用的lpilp/guomi库,核心流程均为:明文编码→公钥加密→密文编码(如十六进制),解密则反之。

二、重要补充内容

1. 密钥管理是安全核心

SM2的安全性高度依赖密钥管理:

  • 密钥生成 :必须使用密码学安全的随机数生成器(如gmssl内置的CSPRNG),禁止使用伪随机数(如基于系统时间的简单随机数),否则可能导致私钥可预测。
  • 密钥存储:私钥需加密存储(可结合SM4对称加密),避免明文写入配置文件或数据库;公钥可公开,但需确保来源可信(防止中间人替换公钥)。
  • 密钥轮换:定期更新密钥对(如每3-6个月),降低密钥泄露后的风险扩散范围。
2. 加密场景的局限性与配合策略

SM2作为非对称算法,加密速度慢于对称算法(如SM4),因此实际应用中通常采用"混合加密"策略:

  • 用SM2加密对称密钥(如SM4的128位密钥),而非直接加密大文件或长文本;
  • 对称密钥用于加密实际数据,通过SM2实现密钥的安全分发,兼顾效率与安全性。
3. 除加解密外的核心功能:数字签名

SM2不仅支持加密,还具备数字签名功能(符合GB/T 32918标准),可用于数据完整性校验与身份认证:

  • 签名过程:用私钥对数据哈希(通常结合SM3)进行签名;

  • 验签过程:用公钥验证签名有效性,确保数据未被篡改且来源于合法发送方。

  • 示例(Python gmssl):

    python 复制代码
    # 签名
    sign = sm2_crypt.sign(data, random_hex_str)  # random_hex_str为随机数
    # 验签
    verify = sm2_crypt.verify(sign, data)  # 返回True/False
4. 合规性与标准化要求

在政务、金融等关键领域,SM2的使用需符合国家密码管理局规范:

  • 必须使用推荐的曲线参数(SM2P256V1),禁止自定义未认证的曲线;
  • 加密/签名流程需严格遵循《GMT 0003-2012 SM2椭圆曲线公钥密码算法》,避免因流程简化导致安全漏洞(如签名时重复使用随机数)。
5. 跨语言实现的兼容性注意

不同语言库(如Python gmssl与PHP lpilp/guomi)实现SM2时,需确保:

  • 密钥格式一致(如公钥是否带前缀04,私钥是否为纯整数十六进制);
  • 密文编码格式统一(如均使用十六进制或Base64);
  • 随机数生成策略兼容(避免因随机数格式差异导致解密失败)。

三、总结

SM2作为国密体系的核心非对称算法,在安全性、性能与合规性上均能满足关键场景需求。其正确应用的核心在于:规范的密钥管理、符合标准的实现流程、与对称算法的合理配合 。开发者在集成时,需优先使用经过验证的库(如gmssllpilp/guomi),并关注密钥生命周期管理与跨平台兼容性,以充分发挥其安全价值。

相关推荐
猿与禅1 个月前
系统安全-主流密码加密算法BCrypt 和PBKDF2详解
系统安全·加密·密码
Yisitelz2 个月前
签名、杂凑、MAC、HMAC
mac·密码·数据完整性·密评
码农康康2 个月前
【国密证书】CentOS 7 安装 GmSSL 并生成国密证书
linux·ssl·国密·国密证书
openHiTLS密码开源社区3 个月前
【密码学实战】国密TLCP协议简介及代码实现示例
密码学·国密·sm2·sm3·sm4·openhitls·tlcp
卡西里弗斯奥5 个月前
【达梦数据库】忘记SYSDBA密码处理方法-已适配
数据库·达梦·密码·sysdba
skywsp7 个月前
SpringBoot集成国密算法
spring boot·国密·springsecurity
christine-rr7 个月前
密码学基础——分组密码的运行模式
网络·密码学·密码
christine-rr7 个月前
密码学基础——DES算法
安全·网络安全·密码学·密码
Web极客码10 个月前
初学者如何保护WordPress网站内容
安全·wordpress·密码