PKI - 一文读懂SM1、SM2、SM3、SM4等国密算法

2024-03-21 23:30

本文主要是介绍PKI - 一文读懂SM1、SM2、SM3、SM4等国密算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Pre
  • 概述
  • S1
  • SM2
  • SM3
  • SM4
  • SM9
  • 使用经验
  • 国密算法的安全性
    • SM2算法的安全性
    • SM3算法的安全性
    • SM4算法的安全性
  • 在Java中使用
    • 引入Bouncy Castle依赖
    • 非对称加密SM2
      • 使用随机生成的密钥对加密或解密
      • 使用自定义密钥对加密或解密
      • SM2签名和验签
      • 自定义密钥对
      • 使用SM2曲线点构建SM2
      • 使用私钥D值签名
      • 使用公钥Q值验证签名
    • 其他格式的密钥
    • 摘要加密算法SM3
    • 对称加密SM4

在这里插入图片描述

Pre

Java - 深入理解加密解密和签名算法


概述

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

国密算法是指国家密码管理局认定的一系列国产密码算法,包括SM1-SM9以及ZUC等。其中

  • SM1、SM4、SM5、SM6、SM7、SM8、ZUC等属于对称密码,
  • SM2、SM9等属于公钥密码 (非对称加密)
  • SM3属于单向散列函数。

目前我国主要使用公开的SM2、SM3、SM4作为商用密码算法。

其中SM1、SM7算法不公开,调用该算法时,需要通过加密芯片的接口进行调用

  • SM2是基于椭圆曲线的公钥密码算法,包括用于数字签名的SM2-1、用于密钥交换的SM2-2和用于公钥密码的SM2-3。

  • SM3是能够计算出256比特的散列值的单向散列函数,主要用于数字签名和消息认证码。

  • SM4是属于对称密码的一种分组密码算法,分组长度和密钥长度均为128比特。

国密算法从SM1-SM4分别实现了对称、非对称、摘要等算法功能,目前已普遍应用于日常工作生活中的各个方面,如工作中使用的VPN,金融业务中的资金流转、刷卡支付,以及门禁设施、身份认证等。


S1

SM1 算法是分组密码算法,分组长度为128位,密钥长度都为 128 比特,算法安全保密强度及相关软硬件实现性能与 AES 相当,算法不公开,仅以IP核的形式存在于芯片中。

采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品,广泛应用于电子政务、电子商务及国民经济的各个应用领域(包括国家政务通、警务通等重要领域)。


SM2

可以理解为国产RSA。非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。

SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高,但运算速度快于RSA。

SM3

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

SM4

可以理解为国产AES。无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

SM9

一种标识密码(IBE)算法,由国家密码管理局于2016年3月28日发布,相关标准为“GM/T 0044-2016 SM9标识密码算法”。主要用于用户的身份认证。SM9的加密强度等同于3072位密钥的RSA加密算法。


使用经验

一般数据发送端都是用SM4对数据内容加密,使用SM3对内容进行摘要,再使用SM2对摘要进行签名。

一般接收端,先用SM2对摘要进行验签,验签成功后就做到了防抵赖,对发送过来的内容进行SM3摘要,看下生成的摘要和验签后的摘要是否一致,用于防篡改。


另外SM4在加密解密需要相同的密钥,这个我们可以通过编写密钥交换模块实现生成相同的密钥。用于SM4对称加密。

关于非对称还要注意几点:

(1)公钥是通过私钥产生的;

(2)公钥加密,私钥解密是加密的过程

(3)私钥加密,公钥解密是签名的过程;

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


国密算法的安全性

国密算法,作为国家层面推广的密码算法标准,其安全性经过了严格的审查和评估。

以下是对SM2、SM3和SM4算法安全性的进一步分析:

SM2算法的安全性

SM2算法是一个基于椭圆曲线的公钥密码算法,其安全性主要依赖于椭圆曲线离散对数问题的难度。与RSA算法相比,SM2算法在相同的安全强度下,所需的密钥长度更短,因此,在加密和签名速度上具有一定的优势。此外,SM2算法在设计时也考虑了多种攻击手段,并采用了相应的防护措施,从而确保了其在实际应用中的安全性。

SM3算法的安全性

SM3算法是一个密码杂凑算法,主要用于数字签名和消息认证等场景。其安全性主要体现在以下几个方面:

  1. 输出长度:SM3算法的输出长度为256比特,相比MD5(128比特)和SHA-1(160比特)算法,其输出长度更长,因此具有更高的安全性。

  2. 碰撞攻击:SM3算法在设计时考虑了碰撞攻击的问题,并采用了相应的防护措施。目前,尚未有公开的针对SM3算法的碰撞攻击方法。

  3. 雪崩效应:SM3算法具有雪崩效应,即输入数据的微小变化会导致输出结果的巨大差异。这一特性使得攻击者难以通过猜测或穷举的方式来破解SM3算法。

SM4算法的安全性

SM4算法是一个分组密码算法,主要用于数据的加密和解密。其安全性主要体现在以下几个方面:

  1. 密钥长度:SM4算法的密钥长度为128比特,与AES算法相同。这一长度的密钥足以抵抗目前已知的所有密码攻击方法。

  2. 分组长度:SM4算法的分组长度也为128比特,这意味着每次加密或解密的数据块大小为128比特。这一分组长度可以确保数据的机密性和完整性。

  3. 加密轮数:SM4算法采用了多轮加密的方式,每轮加密都使用了不同的密钥和加密函数。这种加密方式可以使得攻击者难以通过分析加密过程来破解算法。

  4. 安全性评估:SM4算法已经经过了多轮的安全性评估和审查,其安全性得到了广泛的认可。目前,尚未有公开的针对SM4算法的有效攻击方法。

综上所述,国密算法中的SM2、SM3和SM4算法都具有较高的安全性,可以满足不同场景下的密码应用需求。在实际应用中,可以根据具体的需求和场景选择合适的算法进行使用。

在这里插入图片描述


在Java中使用

Hutool针对Bouncy Castle做了简化包装,用于实现国密算法中的SM2、SM3、SM4。

国密算法工具封装包括:

  • 非对称加密和签名:SM2
  • 摘要签名算法:SM3
  • 对称加密:SM4

国密算法需要引入Bouncy Castle库的依赖。

使用

引入Bouncy Castle依赖

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.69</version>
</dependency>

说明 bcprov-jdk15to18的版本请前往Maven中央库搜索,查找对应JDK的最新版本。

非对称加密SM2

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

String text = "我是一段测试aaaa";SM2 sm2 = SmUtil.sm2();
// 公钥加密,私钥解密
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));

使用自定义密钥对加密或解密

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));

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);

使用SM2曲线点构建SM2

使用曲线点构建中的点生成和验证见:https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg

String privateKeyHex = "FAB8BBE670FAE338C9E9382B9FB6485225C11A3ECB84C938F10F20A93B6215F0";
String x = "9EF573019D9A03B16B0BE44FC8A5B4E8E098F56034C97B312282DD0B4810AFC3";
String y = "CC759673ED0FC9B9DC7E6FA38F0E2B121E02654BF37EA6B63FAF2A0D6013EADF";// 数据和ID此处使用16进制表示
String data = "434477813974bf58f94bcf760833c2b40f77a5fc360485b0b9ed1bd9682edb45";
String id = "31323334353637383132333435363738";final SM2 sm2 = new SM2(privateKeyHex, x, y);
// 生成的签名是64位
sm2.usePlainEncoding();final String sign = sm2.signHex(data, id);
// true
boolean verify = sm2.verifyHex(data, sign)

使用私钥D值签名

//需要签名的明文,得到明文对应的字节数组
byte[] dataBytes = "我是一段测试aaaa".getBytes();
//指定的私钥
String privateKeyHex = "1ebf8b341c695ee456fd1a41b82645724bc25d79935437d30e7e4b0a554baa5e";// 此构造从5.5.9开始可使用
final SM2 sm2 = new SM2(privateKeyHex, null, null);
sm2.usePlainEncoding();
byte[] sign = sm2.sign(dataBytes, null);

使用公钥Q值验证签名

//指定的公钥
String publicKeyHex ="04db9629dd33ba568e9507add5df6587a0998361a03d3321948b448c653c2c1b7056434884ab6f3d1c529501f166a336e86f045cea10dffe58aa82ea13d725363";
//需要加密的明文,得到明文对应的字节数组
byte[] dataBytes = "我是一段测试aaaa".getBytes();
//签名值
String signHex ="2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a";final SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKeyHex));
sm2.usePlainEncoding();// true
boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex));

其他格式的密钥

在SM2算法中,密钥的格式分以下几种:

私钥:

  • D值 一般为硬件直接生成的值
  • PKCS#8 JDK默认生成的私钥格式
  • PKCS#1 一般为OpenSSL生成的的EC密钥格式

公钥:

  • Q值 一般为硬件直接生成的值
  • X.509 JDK默认生成的公钥格式
  • PKCS#1 一般为OpenSSL生成的的EC密钥格式

在新版本的Hutool中,SM2的构造方法对这几类的密钥都做了兼容,即用户无需关注密钥类型:

摘要加密算法SM3

//结果为:136ce3c86e4ed909b76082055a61586af20b4dab674732ebd4b599eef080c9be
String digestHex = SmUtil.sm3("aaaaa");

对称加密SM4

String content = "test中文";
SymmetricCrypto sm4 = SmUtil.sm4();String encryptHex = sm4.encryptHex(content);
String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);

在这里插入图片描述

这篇关于PKI - 一文读懂SM1、SM2、SM3、SM4等国密算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/834092

相关文章

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

一文详解如何从零构建Spring Boot Starter并实现整合

《一文详解如何从零构建SpringBootStarter并实现整合》SpringBoot是一个开源的Java基础框架,用于创建独立、生产级的基于Spring框架的应用程序,:本文主要介绍如何从... 目录一、Spring Boot Starter的核心价值二、Starter项目创建全流程2.1 项目初始化(

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

一文详解kafka开启kerberos认证的完整步骤

《一文详解kafka开启kerberos认证的完整步骤》这篇文章主要为大家详细介绍了kafka开启kerberos认证的完整步骤,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、kerberos安装部署二、准备机器三、Kerberos Server 安装1、配置krb5.con

一文详解Nginx的强缓存和协商缓存

《一文详解Nginx的强缓存和协商缓存》这篇文章主要为大家详细介绍了Nginx中强缓存和协商缓存的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、强缓存(Strong Cache)1. 定义2. 响应头3. Nginx 配置示例4. 行为5. 适用场景二、协商缓存(协