openssl+SM2开发实例一(含源码)

这篇具有很好参考价值的文章主要介绍了openssl+SM2开发实例一(含源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、SM2算法介绍

SM2(国密算法2) 是中国国家密码管理局(CNCA)颁布的椭圆曲线密码算法标准,属于非对称加密算法。它基于椭圆曲线离散对数问题,提供了安全可靠的数字签名、密钥交换和公钥加密等功能。SM2被设计为适用于各种场景下的密码学应用,包括数字证书、数据加密、数字签名、身份认证等。

以下是SM2算法的一些关键特点和概要介绍:

  1. 非对称加密算法: SM2是一种非对称加密算法,意味着它使用两个密钥:公钥和私钥。公钥用于加密数据和验证签名,而私钥用于解密数据和生成签名。

  2. 椭圆曲线密码学: SM2基于椭圆曲线密码学(Elliptic Curve Cryptography,ECC),使用椭圆曲线上的点运算来实现加密和签名操作。

  3. 安全性: SM2采用了高强度的椭圆曲线参数,保障了算法的安全性。在适当的参数选择下,SM2被认为是安全可靠的。

  4. 性能优越: 与传统的RSA算法相比,SM2在相同安全性水平下使用更短的密钥长度,提供了更高的性能。

  5. 国家标准: SM2是中国国家密码算法标准,适用于中国国内的各种密码学应用,包括政府、金融、电信等领域。

  6. 数字签名和密钥交换: SM2可以用于生成数字签名,验证签名的有效性,以及进行安全的密钥交换,用于建立安全的通信通道。

由于SM2是中国的国家密码标准,它在中国国内得到了广泛的应用。SM2不仅提供了高度的安全性,还具备较好的性能,适用于多种密码学场景。

二、SM2代码实例

2.1 SM2加密 / SM2解密

以下是一个简单的C++代码示例,演示了如何使用OpenSSL库进行SM2加密和解密。在这个示例中,我们将SM2加密和解密的功能拆分为两个函数:sm2_encrypt()sm2_decrypt()

请注意,使用此示例代码前,请确保你的系统已经安装了OpenSSL库,并且链接时正确引入了OpenSSL的库文件。该示例仅供学习和参考,实际应用中,你需要根据你的需求和安全性要求进行更严格的错误处理和参数验证。

#include <openssl/evp.h>
#include <openssl/sm2.h>
#include <iostream>
#include <string>

std::string sm2_encrypt(const std::string &plaintext, EVP_PKEY *pubkey) {
    EVP_PKEY_CTX *ctx;
    unsigned char *ciphertext = nullptr;
    size_t ciphertext_len;

    // 创建EVP_PKEY_CTX
    ctx = EVP_PKEY_CTX_new(pubkey, nullptr);
    if (!ctx) {
        std::cerr << "Error creating EVP_PKEY_CTX for encryption" << std::endl;
        return "";
    }

    // 初始化加密操作
    if (EVP_PKEY_encrypt_init(ctx) <= 0) {
        std::cerr << "Error initializing encryption operation" << std::endl;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 设置加密参数(这里可以设置一些参数,例如填充方式)
    // EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);

    // 计算加密后的长度
    if (EVP_PKEY_encrypt(ctx, nullptr, &ciphertext_len, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length()) <= 0) {
        std::cerr << "Error computing ciphertext length" << std::endl;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 分配内存并执行加密操作
    ciphertext = new unsigned char[ciphertext_len];
    if (EVP_PKEY_encrypt(ctx, ciphertext, &ciphertext_len, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length()) <= 0) {
        std::cerr << "Error encrypting data" << std::endl;
        delete[] ciphertext;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 释放资源
    EVP_PKEY_CTX_free(ctx);

    // 返回加密后的数据(Base64编码)
    std::string encoded_ciphertext(reinterpret_cast<char*>(ciphertext), ciphertext_len);
    delete[] ciphertext;
    return encoded_ciphertext;
}

std::string sm2_decrypt(const std::string &ciphertext, EVP_PKEY *privkey) {
    EVP_PKEY_CTX *ctx;
    unsigned char *plaintext = nullptr;
    size_t plaintext_len;

    // 创建EVP_PKEY_CTX
    ctx = EVP_PKEY_CTX_new(privkey, nullptr);
    if (!ctx) {
        std::cerr << "Error creating EVP_PKEY_CTX for decryption" << std::endl;
        return "";
    }

    // 初始化解密操作
    if (EVP_PKEY_decrypt_init(ctx) <= 0) {
        std::cerr << "Error initializing decryption operation" << std::endl;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 计算解密后的长度
    if (EVP_PKEY_decrypt(ctx, nullptr, &plaintext_len, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length()) <= 0) {
        std::cerr << "Error computing plaintext length" << std::endl;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 分配内存并执行解密操作
    plaintext = new unsigned char[plaintext_len];
    if (EVP_PKEY_decrypt(ctx, plaintext, &plaintext_len, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length()) <= 0) {
        std::cerr << "Error decrypting data" << std::endl;
        delete[] plaintext;
        EVP_PKEY_CTX_free(ctx);
        return "";
    }

    // 释放资源
    EVP_PKEY_CTX_free(ctx);

    // 返回解密后的数据
    std::string decrypted_plaintext(reinterpret_cast<char*>(plaintext), plaintext_len);
    delete[] plaintext;
    return decrypted_plaintext;
}

int main() {
    EVP_PKEY *pubkey = nullptr;
    EVP_PKEY *privkey = nullptr;

    // 生成SM2密钥对
    if (!EVP_PKEY_keygen_SM2(&pubkey, &privkey)) {
        std::cerr << "Error generating SM2 key pair" << std::endl;
        return 1;
    }

    std::string plaintext = "Hello, SM2!";
    std::string ciphertext = sm2_encrypt(plaintext, pubkey);
    std::string decrypted_text = sm2_decrypt(ciphertext, privkey);

    std::cout << "Original Text: " << plaintext << std::endl;
    std::cout << "Encrypted Text: " << ciphertext <<

 std::endl;
    std::cout << "Decrypted Text: " << decrypted_text << std::endl;

    EVP_PKEY_free(pubkey);
    EVP_PKEY_free(privkey);

    return 0;
}

请确保在实际使用时对错误进行适当处理,并根据实际需求进行参数配置。此示例中,使用了OpenSSL提供的SM2密钥生成函数,加密和解密操作的结果以字符串形式输出。在实际应用中,你可能需要对加密后的数据进行Base64编码以方便传输。

2.2 SM2签名

2.2.1 SM2签名步骤

SM2签名的过程通常包括以下步骤:

  1. 生成密钥对: 签名方首先需要生成自己的SM2公钥和私钥。公钥用于验证签名,私钥用于生成签名。

  2. 计算消息的哈希值: 对待签名的消息进行哈希操作,通常使用SM3算法生成消息的摘要(哈希值)。

  3. 生成随机数: 生成一个随机数(称为k),该随机数需要满足一定的条件,以保障签名的安全性。在SM2中,k的生成需要满足一定的随机性和不可预测性。

  4. 计算椭圆曲线点: 使用随机数k计算椭圆曲线上的点(k * G,其中G是椭圆曲线的基点),得到一个椭圆曲线点(x1, y1)。

  5. 计算r值: 将椭圆曲线点的横坐标x1对一个固定数取模,得到一个整数r。如果r等于0,则需要重新选择随机数k并重新计算。

  6. 计算s值: 计算签名的另一个部分s,公式为: s = ( ( h a s h + r ⋅ d ) / k ) m o d    n s = ((hash + r \cdot d) / k) \mod n s=((hash+rd)/k)modn 其中,hash是消息的哈希值,d是私钥,n是椭圆曲线的阶数。

  7. 验证rsrs作为签名的两个组成部分,并与消息一起发送给验证方。验证方使用签名者的公钥、消息的哈希值、rs进行验证。验证的详细步骤包括使用公钥计算椭圆曲线点,验证r的范围和计算(s \cdot G + r \cdot PK)等。如果验证通过,则签名有效。

在SM2签名过程中,随机数k的选择和签名的正确性非常关键,不当的随机数选择可能导致签名的不安全性。因此,在实际应用中,随机数的生成需要特别注意,通常使用专门的随机数生成库或硬件随机数生成模块来确保随机性和不可预测性。

2.2.2 SM2签名C++开发实例

2.3 SM2密钥交换

2.3.1 SM2密钥交换步骤

是的,SM2算法可以用于密钥交换。在SM2中,密钥交换是通过Diffie-Hellman密钥交换协议的椭圆曲线密码学版本来实现的。SM2密钥交换的过程基于椭圆曲线离散对数问题,该问题在椭圆曲线密码学中是困难的,因此使得SM2密钥交换具备了很高的安全性。

SM2密钥交换的流程通常包括以下步骤:

  1. 生成临时密钥对: 通信双方分别生成自己的临时私钥和对应的临时公钥。这两个临时密钥对仅在当前密钥交换会话中使用。

  2. 计算共享秘密: 通信双方分别使用自己的临时私钥和对方的临时公钥,通过椭圆曲线上的点运算计算出一个共享的秘密值。

  3. 生成共享密钥: 使用共享的秘密值作为密钥生成算法的输入,生成对称密钥,该密钥可以用于后续的加密和解密通信内容。

  4. 销毁临时密钥: 在生成共享密钥之后,临时私钥和临时公钥可以被销毁,因为它们不再需要。

SM2密钥交换的安全性建立在椭圆曲线离散对数问题的困难性上,确保了在不共享密钥的情况下,通信双方可以协商出一个共享密钥,从而实现了安全的密钥交换。文章来源地址https://www.toymoban.com/news/detail-758187.html

三、openssl SM2 命令操作

3.1 openssl SM2 加密

3.2 openssl sm2 解密

3.3 openssl SM2 签名

3.3 openssl SM2 验签(签名校验)

到了这里,关于openssl+SM2开发实例一(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • openssl生成SM2公私钥对命令详解

            (1)获得openssl支持椭圆曲线算法列表         命令:openssl ecparam -list_curves         返回结果:   secp112r1 : SECG/WTLS curve over a 112 bit prime field   secp112r2 : SECG curve over a 112 bit prime field   secp128r1 : SECG curve over a 128 bit prime field   secp128r2 : SECG curve over a 128 bit pr

    2024年02月05日
    浏览(48)
  • OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)

    openssl 3 默认废弃了 旧版本 (opessl 1.x) 的部分api 导致部分旧ecc 代码无法使用(可以通过配置编译选项打开) ,这里展示如何使用新接口用ECC 进行加密解密。 新接口是真的方便,基本上你都不需要懂啥密码学知识,对我们这种密码白痴来说太好了 头文件 生成密钥对 导出公

    2024年02月05日
    浏览(61)
  • C++调用openssl实现国标sm2签名算法的使用

    SM2算法基于ECC椭圆曲线算法,广泛用于区块链、HTTPS 等需要非对称加密的场景。是基于椭圆曲线数学理论实现的一种非对称加密算法。相比RSA,ECC优势是可以使用更短的密钥,来实现与RSA相当或更高的安全。 下面链接可以了解一些关于SM2的基础知识。 椭圆曲线加密算法(E

    2024年01月24日
    浏览(37)
  • 基于openssl国密算法SM2搭建CA及颁发证书

    一、环境说明: 1.操作系统:CentOS 7.9 2.openssl : OpenSSL 1.1.1q  5 Jul 2022 二、搭建私有CA 1. 创建CA目录,在目录下创建相关目录如下: 在CA下生成证书索引库文件: 指定颁发第一个证书的序列号: 2. 生成SM2私钥 生成证书: 3.ca自签名证书生成完毕。将该证书后缀改为crt,导入到

    2024年02月12日
    浏览(47)
  • openssl SM2(ECC)自签服务端和客户端证书

    参考文章:https://www.golinuxcloud.com/openssl-generate-ecc-certificate/#5_Create_CA_certificate_with_ECC_Key (228条消息) openssl 制作SM2多级证书链_酷ying的博客-CSDN博客_openssl sm2 sm3 csr 1、在当前目录创建存储证书文件夹,配置openssl.cnf所需要的文件,将openssl.cnf文件放到当前目录(编译openssl源码包会

    2024年02月11日
    浏览(42)
  • 【vue+sm2】前端使用国密sm2,加解密

    1.第一步就是安装依赖 2.导入sm2 3.先定义私钥或者公钥,私钥是解密,公钥是加密 4.设置加密模式 5.解密的使用全码 6.加密的实现全码

    2024年02月16日
    浏览(50)
  • SM2工具类SM2Utils(java)

    话不多说直接上代码。 SM2 密钥在线生成工具

    2024年02月11日
    浏览(32)
  • 国密SM2/SM3算法

    分类 1、SM1是一种分组加密算法 对称加密算法中的分组加密算法,其分组长度、秘钥长度都是128bit,算法安全保密强度跟 AES 相当,但是算法不公开,仅以IP核的形式存在于芯片中,需要通过加密芯片的接口进行调用。 采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙

    2024年02月05日
    浏览(66)
  • golang使用SM2(SM2withSM3)签名、验签数据

    对接招行支付 私钥:Hex格式,SM2标准秘钥格式,私钥为32字节字节流,转换为HEX格式为64字节 公钥:base64格式,并且符合ANS1标准,base64编码后总长度为124字节 SM2标准公钥头:3059301306072A8648CE3D020106082A811CCF5501822D03420004 数字签名采用SM2withSM3签名算法,签名方式为PKCS#1裸签名,签

    2024年02月13日
    浏览(37)
  • sm2签名与sm4加密(三)

    二简单介绍了一下理论,三来简单说下sm2签名的实现, 首先因为openssl太复杂没搞懂,就去看gmssl的代码,gmssl的密钥结构体很简单,长这个样子: 很明显公钥是一个点由xy两个坐标组成,私钥是一个长串。 sm2签名过程可以大体上分成三步,生成公私钥——(交换密钥)——使

    2024年01月18日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包