首页 > 其他分享 >js加密双重保障之sm2国密

js加密双重保障之sm2国密

时间:2023-09-21 22:32:54浏览次数:79  
标签:ciphertext 加密 plaintext SM2 len sm2 国密 new js

前言

最近看到一些项目里边有用到sm2/3/4国密加密算法,这里给大家简单介绍一下。

知识科普

SM2(国密算法)是一种非对称加密算法,由中国国家密码管理局(NCC)制定,并被广泛应用于中国的信息安全领域。它基于椭圆曲线密码学,主要用于数字签名和数据加密。以下是SM2国密算法的一些关键特点:

  1. 安全性:SM2被设计为一种安全的非对称加密算法,基于椭圆曲线离散对数问题。目前,它被认为在经典计算机和量子计算机的攻击下都是安全的。
  2. 高效性:相对于传统的RSA算法,SM2在加解密和签名验证方面具有更高的性能和效率,特别适用于移动设备和资源受限的环境。
  3. 国家标准:SM2是中国国家密码管理局颁布的国家标准,作为中国政府机构和企业的信息安全标准,它在中国国内得到广泛应用。
  4. 数字签名:SM2可以用于生成数字签名,用于验证数据的完整性和身份认证。它在电子认证、电子合同等领域具有广泛应用。
  5. 数据加密:SM2也可用于数据加密,用于保护敏感信息的隐私性。在安全通信和数据保护方面具有重要作用。
  6. 密钥管理:SM2支持公钥和私钥的生成、存储和管理,确保密钥的安全性和可用性。
  7. 国际化:尽管SM2是中国的国家标准,但它也在一定程度上获得了国际认可,部分国际组织和标准化机构也开始考虑将其作为一种可选的加密算法。

总之,SM2国密算法在中国是一种重要的信息安全标准,具有强大的安全性和高效性,适用于多种应用场景,尤其在数字签名、数据加密、电子认证等领域有广泛的应用。

成熟的第三方开源地址

  1. Bouncy Castle:Bouncy Castle是一个流行的Java加密库,提供了对SM2的支持。您可以使用Bouncy Castle库来进行SM2加密、签名和密钥管理等操作。
    GitHub存储库:https://github.com/bcgit/bc-java
  2. GMSSL:GMSSL是一个由中国国家密码管理局开发的密码库,提供了对国密算法(包括SM2)的支持。它提供了C语言和Java语言的接口。
    GitHub存储库:https://github.com/guanzhi/GmSSL
  3. jsrsasign:这是一个JavaScript库,提供了对SM2的支持,特别适用于前端开发。您可以使用它在浏览器中执行SM2加密和签名操作。
    GitHub存储库:https://github.com/kjur/jsrsasign

代码案例

1. 使用Bouncy Castle(Java)

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

import java.security.Security;

public class SM2Example {

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // 生成密钥对
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(
                ECNamedCurveTable.getParameterSpec("sm2p256v1"), null);
        keyPairGenerator.init(keyGenParams);
        AsymmetricCipherKeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 明文
        String plaintext = "Hello, SM2!";

        // 加密
        SM2Engine engine = new SM2Engine();
        CipherParameters params = new ParametersWithRandom(keyPair.getPublic(), null);
        engine.init(true, params);
        byte[] ciphertext = engine.processBlock(plaintext.getBytes(), 0, plaintext.getBytes().length);

        // 解密
        engine.init(false, keyPair.getPrivate());
        byte[] decryptedText = engine.processBlock(ciphertext, 0, ciphertext.length);

        System.out.println("加密前: " + plaintext);
        System.out.println("加密后: " + Base64.toBase64String(ciphertext));
        System.out.println("解密后: " + new String(decryptedText));
    }
}

2. 使用GMSSL(C语言)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sm2.h>

int main() {
    const char *plaintext = "Hello, SM2!";
    size_t plaintext_len = strlen(plaintext);

    // 生成密钥对
    EC_KEY *ec_key = EC_KEY_new();
    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);
    EC_KEY_set_group(ec_key, group);
    EC_KEY_generate_key(ec_key);

    // 加密
    size_t ciphertext_len = plaintext_len + EVP_MAX_BLOCK_LENGTH;
    unsigned char *ciphertext = (unsigned char *)malloc(ciphertext_len);
    int len = SM2_encrypt(NID_sm2p256v1, NULL, NULL, EC_KEY_get0_public_key(ec_key),
                          plaintext, plaintext_len, ciphertext, &ciphertext_len);

    // 解密
    unsigned char *decrypted_text = (unsigned char *)malloc(ciphertext_len);
    int decrypted_len = SM2_decrypt(NID_sm2p256v1, NULL, NULL, ec_key,
                                    ciphertext, ciphertext_len, decrypted_text, &ciphertext_len);

    printf("加密前: %s\n", plaintext);
    printf("加密后: ");
    for (int i = 0; i < len; i++) {
        printf("%02x", ciphertext[i]);
    }
    printf("\n");
    printf("解密后: %s\n", decrypted_text);

    free(ciphertext);
    free(decrypted_text);
    EC_KEY_free(ec_key);
    EC_GROUP_free(group);

    return 0;
}

3. 使用jsrsasign(JavaScript)

<!DOCTYPE html>
<html>
<head>
  <title>SM2 Encryption Example</title>
  <script src="jsrsasign-all-min.js"></script>
</head>
<body>
  <textarea id="plaintext" rows="4" cols="50">Hello, SM2!</textarea><br><br>
  <button onclick="encryptText()">加密</button><br><br>
  <div id="encryptedText"></div><br>
  <div id="decryptedText"></div>

  <script>
    function encryptText() {
      var plaintext = document.getElementById("plaintext").value;
      var publicKeyHex = "公钥十六进制字符串"; // 替换成实际的公钥

      var sm2 = new KJUR.crypto.SM2({ 'publicKeyHex': publicKeyHex });
      var encryptedText = sm2.doEncrypt(plaintext);

      document.getElementById("encryptedText").textContent = "加密后: " + encryptedText;

      // 解密示例(仅供参考,实际解密需要私钥)
      // var decryptedText = sm2.doDecrypt(encryptedText);
      // document.getElementById("decryptedText").textContent = "解密后: " + decryptedText;
    }
  </script>
</body>
</html>

注意:上列示例中敏感数据都是虚假的哦,自己用的话建议替换成自己的。

收尾

一般来说前端保护方案一直都是有限的,我建议的是用jsjiami.v7/v6在线一键加密,配合aes/国密这种对接口安全进行保护。

标签:ciphertext,加密,plaintext,SM2,len,sm2,国密,new,js
From: https://blog.51cto.com/u_15785573/7557956

相关文章

  • JS逆向
    场景:登录时账号或密码被加密而无法爆破或Fuzz的情况,如果是前端加密可以尝试js逆向,搭配phantomjs(JavaScriptAPI)和bp插件JSEncryptr进行爆破一、https://my.sto.cn/1.点击登录,可见发送了一个数据包LoginResult,地址是/Vip/LoginResult2.ctrl+shift+f全局查找/Vip/LoginRe......
  • 一些H5对接微信JSSDK的问题记录
    这里给大家分享我在实际生活中总结出来的一些知识,希望对大家有所帮助一.SDK引入这里提供两套引入流程,一套是vue2.0及其他h5项目,一套是vue3.0的引入流程不懂的也可以看我之前的一篇详细流程记录--微信调用jssdk全流程详解1.js引入直接在你的页面里引入js文件就行<scriptsr......
  • Swagger生产nodejs后台代码(nestia框架)
    Swagger文档生产nestia框架代码#SETUPGLOBALLYnpminstall-g@nestia/migrate#DOMIGRATEnpx@nestia/migrateswagger.jsonoutput_directoryNPM是一个Node包管理器,NPX是一个Node包执行器。npm查看全局安装的包npmls-g......
  • Windows 下更新 node.js
    一、node.js更新(一)查询node.js版本node-v(二)查询node.js安装位置wherenode(三)官网下载安装包https://nodejs.org/dist/下载对应版本的msi文件(四)安装到原位置,覆盖旧版本如:D:\ProgramFiles\nodejs\二、npm更新(一)查看版本npm-v(二)更新版本npmup......
  • js,格式化long类型日期封装
    /***扩展date函数*author:c3gen*/Date.prototype.format=function(format){varo={"M+":this.getMonth()+1,"d+":this.getDate(),"h+":this.getHours(),"m+":......
  • JS 对象(Object)和字符串(String)互转
    利用原生JSON对象,将对象转为字符串1.varjsObj={};2.jsObj.testArray=[1,2,3,4,5];3.jsObj.name='CSS3';4.jsObj.date='8May,2011';5.varstr=JSON.stringify(jsObj);6.alert(str);从JSON字符串转为对象1.varjsObj={};2.jsObj.......
  • js触发事件备忘
    一般事件事件浏览器支持描述onClick: 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击onDblClick: 鼠标双击事件onMouseDown: 鼠标上的按钮被按下了onMouseUp: 鼠标按下后,松开时激发的事件onMouseOver: 当鼠标移动到某对象范围的上方时触发的事件onMouseMove:......
  • web开发:详细讲解jsp的内置对象
    1.request对象   客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。序号方法说明1objectgetAttribute(Stringname)返回指定属性的属性值2EnumerationgetAttributeNames()返回所有可用属性名的......
  • js 应用点滴
    [web编程]document对象详解document文挡对象-JavaScript脚本语言描述---------------------------------------------------------------------注:页面上元素name属性和JavaScript引用的名称必须一致包括大小写   否则会提......
  • js select 应用
    js 代码//1.判断select选项中是否存在Value="paraValue"的ItemfunctionjsSelectIsExitItem(objSelect,objItemValue){varisExit=false;for(vari=0;i<objSelect.options.length;i++){if(objSelect.o......