国密算法简介

前言

加密是通过“加密算法”将明文加密成密文,可以通过“密钥”和“解密算法”将密文还原成明文。

密码学中应用最为广泛的三类算法:

  • 对称算法(分组密码算法):AES/DES/SM4

  • 非对称算法(公钥密码算法):RSA/SM2

  • 摘要算法(杂凑算法):MD5/SHA-I/SM3

一.国密算法概述

国密算法是我国自主研发创新的一套数据加密处理系列算法。从SM1-SM4分别实现了对称、非对称、摘要等算法功能。特别适合应用于嵌入式物联网等相关领域,完成身份认证和数据加解密等功能。当然,默认的前提条件是算法密钥必须保证安全性,因此要将国密算法嵌入到硬件加密芯片中结合使用。

二.国密算法介绍

国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。

SM1:为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。

SM2:非对称加密,基于ECC(椭圆加密算法)。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC256位(SM2采用的就是ECC256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。即SM2>RSA2048,安全度高且运算速度块。

SM3:消息摘要,可以用MD5作为对比理解。该算法已公开。校验结果为256位。

SM4:对称加密,密钥长度和分组长度均为128位。无线局域网标准的分组数据算法。

由于SM1、SM4加解密的分组大小为128bit,故对消息进行加解密时,若消息长度过长,需要进行分组,要消息长度不足,则要进行填充。

三.加密算法安全性比较

  • SM2和RSA

256位的SM2>2048位的RSA

  • SM3/MD5/SHA-1

MD5输出长度128bit

SHA-1输出长度160bit

SM3输出长度256bit

输出长度越长,安全性越高,所以SM3>SHA-1>MD5

  • SM4/AES/3DES

对称加密算法用于实现数据的加密和解密运算。要保证一个对称加密算法的安全性的基本条件是其具备氹的密钥长度,SM4密钥长度为128bit,分组长度为128bit。所以安全性:SM4>AES>3DES

参考文章:

国密算法介绍:

https://www.cnblogs.com/kaleidoscope/p/15038050.html

国密算法的实现

基于BC实现

一、pom文件引用

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.58</version>
</dependency>

二、SM2实现工具类

import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec; import java.security.*;
import java.security.spec.ECGenParameterSpec; /**
@author WangJing
@Description SM2实现工具类
@date 2021/11/24 16:10
*/
public class Sm2Util { static {
Security.addProvider(new BouncyCastleProvider());
} /**
* 生成国密公私钥对
*
* @return
* @throws Exception
*/
public static KeyPair createECKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = null;
SecureRandom secureRandom = new SecureRandom();
ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
keyPairGenerator = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
keyPairGenerator.initialize(sm2Spec);
keyPairGenerator.initialize(sm2Spec, secureRandom);
return keyPairGenerator.generateKeyPair();
} /**
* 根据publicKey对原始数据data,使用SM2加密
*
* @param data
* @param publicKey
* @return
*/
public static byte[] encrypt(byte[] data, PublicKey publicKey) {
ECPublicKeyParameters localECPublicKeyParameters = null; if (publicKey instanceof BCECPublicKey) {
BCECPublicKey localECPublicKey = (BCECPublicKey) publicKey;
ECParameterSpec localECParameterSpec = localECPublicKey.getParameters();
ECDomainParameters localECDomainParameters = new ECDomainParameters(localECParameterSpec.getCurve(), localECParameterSpec.getG(), localECParameterSpec.getN());
localECPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), localECDomainParameters);
}
SM2Engine localSM2Engine = new SM2Engine();
localSM2Engine.init(true, new ParametersWithRandom(localECPublicKeyParameters, new SecureRandom()));
byte[] arrayOfByte2;
try {
arrayOfByte2 = localSM2Engine.processBlock(data, 0, data.length);
return arrayOfByte2;
} catch (InvalidCipherTextException e) { e.printStackTrace();
return null;
}
} /**
* 根据privateKey对加密数据encodedata,使用SM2解密
*
* @param encodedata
* @param privateKey
* @return
*/
public static byte[] decrypt(byte[] encodedata, PrivateKey privateKey) {
SM2Engine localSM2Engine = new SM2Engine();
BCECPrivateKey sm2PriK = (BCECPrivateKey) privateKey;
ECParameterSpec localECParameterSpec = sm2PriK.getParameters();
ECDomainParameters localECDomainParameters = new ECDomainParameters(localECParameterSpec.getCurve(), localECParameterSpec.getG(), localECParameterSpec.getN());
ECPrivateKeyParameters localECPrivateKeyParameters = new ECPrivateKeyParameters(sm2PriK.getD(), localECDomainParameters);
localSM2Engine.init(false, localECPrivateKeyParameters);
try {
byte[] arrayOfByte3 = localSM2Engine.processBlock(encodedata, 0, encodedata.length);
return arrayOfByte3;
} catch (InvalidCipherTextException e) {
e.printStackTrace();
return null;
}
} /**
* 私钥签名
*
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static byte[] signByPrivateKey(byte[] data, PrivateKey privateKey) throws Exception {
Signature sig = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);
sig.initSign(privateKey);
sig.update(data);
byte[] ret = sig.sign();
return ret;
} /**
* 公钥验签
*
* @param data
* @param publicKey
* @param signature
* @return
* @throws Exception
*/
public static boolean verifyByPublicKey(byte[] data, PublicKey publicKey, byte[] signature) throws Exception {
Signature sig = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), BouncyCastleProvider.PROVIDER_NAME);
sig.initVerify(publicKey);
sig.update(data);
boolean ret = sig.verify(signature);
return ret;
} }

三、Sm2Util 的测试类

import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.util.encoders.Hex; import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64; /**
@author WangJing
@Description Sm2Util 的测试类
@date 2021/11/24 16:10
*/
public class Sm2UtilTest { private static String testStr = "wangjing"; public static void main(String[] args) throws Exception {
//生成公私钥对
KeyPair ecKeyPair = Sm2Util.createECKeyPair(); System.out.println("原始字符串:" + testStr); PublicKey publicKey = ecKeyPair.getPublic();
if (publicKey instanceof BCECPublicKey) {
//获取64字节非压缩缩的十六进制公钥串(0x04)
String publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
System.out.println("SM2公钥:" + publicKeyHex);
} PrivateKey privateKey = ecKeyPair.getPrivate();
if (privateKey instanceof BCECPrivateKey) {
//获取32字节十六进制私钥串
String privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
System.out.println("SM2私钥:" + privateKeyHex);
} byte[] encrypt = Sm2Util.encrypt(testStr.getBytes(), publicKey);
String encryptBase64Str = Base64.getEncoder().encodeToString(encrypt);
System.out.println("加密数据:" + encryptBase64Str); byte[] decode = Base64.getDecoder().decode(encryptBase64Str);
byte[] decrypt = Sm2Util.decrypt(decode, privateKey);
System.out.println("解密数据:" + new String(decrypt)); byte[] sign = Sm2Util.signByPrivateKey(testStr.getBytes(), privateKey);
System.out.println("数据签名:" + Base64.getEncoder().encodeToString(sign)); boolean b = Sm2Util.verifyByPublicKey(testStr.getBytes(), publicKey, sign);
System.out.println("数据验签:" + b);
}
}

四、执行效果

原始字符串:wangjing
SM2公钥:043d622a934fdcd8d062cbbd3171708f6a600bc0965209d69058310a23538c3133a82fad956ecb23274bc16446f3912b928b9e2e5b66c1ad794481b83bf7606a8c
SM2私钥:400e1d2a80324015e6dd4eaf5ce6e3e235e6fde8d4e7f64082800d78b17d13d1
加密数据:BLy9P5a9Lqo6ltsOYUwMrh3tQ5tBWSq02iShaiHJCaWvn7A0pyLy0AoWcl96dwY08vqmsLyJvQDJ9RnTIDpJntVAVHenOU5Vvug4+t2bQDY0RyLxGvz8bdMop8iNXlV7WoLVTCNrBngq
解密数据:wangjing
数据签名:MEYCIQC2v8X9D88OR8Gpp4UIzV6/KKF2oGuepjtWr4RoZZ/sZQIhAMsi0nNkU8K5neinsDagDTuKkktGX8fH+Ag06hyrpHhT
数据验签:trueAI写代码

参考文章:

国密算法SM2 的JAVA实现(基于BC实现):

https://blog.csdn.net/wang_jing_jing/article/details/121518561

国密算法SM2 的JAVA实现(基于BC实现) 转载:

https://blog.51cto.com/xiaohaiwa/5378757 (内容基本相同,此文章类的封装更好一些)

基于Hutool的实现

一、pom文件引用

<!--        bouncycastle:SM2国密加密-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency> <!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>

二、非对称加密SM2

  1. 使用随机生成的密钥对加密或解密

String text = "我是一段测试aaaa";
SM2 sm2 = SmUtil.sm2();
// 公钥加密,私钥解密
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  1. 使用自定义密钥对加密或解密
String text = "我是一段测试aaaa";
KeyPair pair = SecureUtil.generateKeyPair("SM2");
byte[] privateKey = pair.getPrivate().getEncoded();
byte[] publicKey = pair.getPublic().getEncoded();
SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
// 公钥加密,私钥解密
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));san

三、SM2签名和验签

String content = "我是Hanley.";
final SM2 sm2 = SmUtil.sm2();
String sign = sm2.signHex(HexUtil.encodeHexStr(content));
// true
boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sign);

当然,也可以自定义密钥对:

String content = "我是Hanley.";
KeyPair pair = SecureUtil.generateKeyPair("SM2");
final SM2 sm2 = new SM2(pair.getPrivate(), pair.getPublic());
byte[] sign = sm2.sign(content.getBytes());
// true
boolean verify = sm2.verify(content.getBytes(), sign);

参考文章:

Hutool国密算法工具-SmUtil官方文档:

https://hutool.cn/docs/#/crypto/国密算法工具-SmUtil

java/vue使用国密sm2、sm3、sm4进行数据加密:

https://blog.csdn.net/qq243920161/article/details/127865091

国密算法简介与实现(转载_记录_Java)的更多相关文章

  1. Hyperledger Fabric密码模块系列之BCCSP(五) - 国密算法实现

    Talk is cheap, show me your code. 代码也看了,蛋也扯了,之后总该做点什么.响应国家政策,把我们的国密算法融合进去吧--  先附两张bccsp下国密算法的设计实现图. ...

  2. 关于国密算法 SM1,SM2,SM3,SM4 的笔记

    国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接 ...

  3. 20155206赵飞 基于《Arm试验箱的国密算法应用》课程设计个人报告

    20155206赵飞 基于<Arm试验箱的国密算法应用>课程设计个人报告 课程设计中承担的任务 完成试验箱测试功能1,2,3 . 1:LED闪烁实验 一.实验目的  学习GPIO原理  ...

  4. 《基于Arm实验箱的国密算法应用》课程设计 结题报告

    <基于Arm实验箱的国密算法应用>课程设计 结题报告 小组成员姓名:20155206赵飞 20155220吴思其 20155234昝昕明 指导教师:娄嘉鹏 设计方案 题目要求:基于Arm实 ...

  5. 2015520吴思其 基于《Arm试验箱的国密算法应用》课程设计个人报告

    20155200吴思其 基于<Arm试验箱的国密算法应用>课程设计个人报告 课程设计中承担的任务 完成试验箱测试功能4,5,6以及SM3加密实验的实现 测试四 GPIO0按键中断实验 实验 ...

  6. 20155234 昝昕明《基于ARM实验箱的国密算法应用》课程设计个人报告

    20155234 昝昕明<基于ARM实验箱的国密算法应用>课程设计个人报告 个人贡献 参与课设题目讨论及完成全过程: 资料收集: SM1算法及和ARM之间通信 负责串口代码调试: 协调完成 ...

  7. java sm4国密算法加密、解密

      java sm4国密算法加密.解密 CreationTime--2018年7月5日09点20分 Author:Marydon 1.准备工作 所需jar包: bcprov-jdk15on-1.59. ...

  8. 国密算法--Openssl 实现国密算法(基础介绍和产生秘钥对)

    国密非对称加密算法 又称sm2,它是采取了ECC(曲线加密算法)中的一条固定的曲线,实际上就是ECC算法. 因为openssl里面不包含sm2算法,所以就要重新进行封装-. - 对于ECC算法我就不介 ...

  9. SM系列国密算法(转)

    原文地址:科普一下SM系列国密算法(从零开始学区块链 189) 众所周知,为了保障商用密码的安全性,国家商用密码管理办公室制定了一系列密码标准,包括SM1(SCB2).SM2.SM3.SM4.SM7. ...

  10. 国产芯片任重道远 国科微SSD主控芯片的“追赶之路”(不能只提供一颗芯片,而是要将芯片、国密算法、固件Firmware、BIOS和操作系统紧密联系在一起,变成完整解决方案交给行业用户,才能真正体现自身的价值)

    集微网消息,“中国芯”战略之路道阻且长,踏入这个赛道的攻坚者们需要十年如一日的技术突破,需要集合产业势能,共同协作,方能建立中国核心技术真正的竞争力. 国产化之路任重道远,SSD芯片初见成效 信息时代 ...

随机推荐

  1. kettle介绍-Step之Write to log

    Write to log写日志介绍 写日志步骤是将输入步骤的信息打印在日志窗口,供用户直接查看 Step name:步骤的名称,在单一转换中,名称必须唯一. Log level:设置日志的显示级别. ...

  2. 有的时候,给指定的控件,追加一个装饰器Adorner,备注下

    有的时候,给指定的控件,追加一个装饰器Adorner,备注下 比如给某个图片加个工具条等等...都可以采用装饰器的方式来实现,复用性高,易维护,特此备注下 整体效果如下: 1 <Window x ...

  3. crypto14解题思路

    crypto14解题思路 ##二进制 001100110011001100100000001101000011010100100000001101010011000000100000001100100 ...

  4. Ubuntu 使用crontab定时备份log

    rsyslog 在Linux上,默认情况下,所有日志文件都位于/var/log目录下,有几种类型的日志文件存储不同的消息,可以是cron,内核,安全性,事件,用户,这些日志文件大多由rsyslog服务 ...

  5. 【代码】Processing笔触手写板笔刷代码合集(包含流速、毛笔笔触、压感笔触等多种)

    代码来源于openprocessing,考虑到国内不是很好访问,我把我找到的比较好的搬运过来! @ 目录 合集1 笔触4(流速笔触,速写) 笔触5(流速笔触,晕染) 笔触6(流速笔触,毛笔) 合集2 ...

  6. Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染

    介绍 字节跳动近期开源的跨平台框架Lynx被视为一项重要的技术创新.相较于市场上已有的解决方案如React Native (RN) 和Flutter,Lynx具有独特的特性. 首先,Lynx采用轻量级 ...

  7. Advanced pandas

    Advanced pandas import numpy as np import pandas as pd Categorical Data This section introduces the ...

  8. CV中常用Backbone-3:Clip/SAM原理以及代码操作

    前面已经介绍了简单的视觉编码器,这里主要介绍多模态中使用比较多的两种backbone:1.Clip:2.SAM.对于这两个backbone简单介绍基本原理,主要是讨论使用这个backbone. 1.C ...

  9. 异步日志监控:FastAPI与MongoDB的高效整合之道

    title: 异步日志监控:FastAPI与MongoDB的高效整合之道 date: 2025/05/27 17:49:39 updated: 2025/05/27 17:49:39 author: ...

  10. [VulnHub]DC-3靶场全过程

    DC-3 靶机部署 下载好DC-3,直接导入 可以生成一个mac地址,方便我们确认主机 信息收集 获取靶机ip(arp-scan/nmap) arp-scan -l nmap 192.168.190. ...