国密算法SM2,SM3,SM4简单比较,以及基于Java的SM4(ECB模式,CBC模式)对称加解密实现

本文主要是介绍国密算法SM2,SM3,SM4简单比较,以及基于Java的SM4(ECB模式,CBC模式)对称加解密实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

常用的国密算法包含SM2,SM3,SM4。以下针对每个算法使用场景进行说明以比较其差异

  • SM2:非对称加密算法,可以替代RSA
    • 数字签名,SM2为非对称加密,加解密使用一对私钥和公钥,只有签名发行者拥有私钥,可用于加密,其他需要验证解密或验签者使用公钥进行。如果使用公钥可以成功解密,则可以确定数据、文档或其他数字资产的拥有者。
    • 因性能问题,根据实际需要常用于小体积数据加密,例如对密钥或SM3生成的hash进行加密。针对SM3生成的hash值进行加密也是一种常用的签名方式,一般先对需要签名的数据、文档或数字资产使用SM3生成hash再用SM2进行签名。

             注:

             如果用于加密,那么加密是用公钥进行的,解密是用私钥进行的。

             如果用于数字签名,那么签名是用私钥进行的,验证签名则使用公钥。

  • SM3:散列哈希算法
    • 数据库中用户密码的保存,获取用户输入明文密码后,进行SM3生成hash值,再与数据库中保存的已经过SM3计算后的密码值进行比对。
    • 数据完整性验证,针对数据、文件或数据资产进行SM3生成hash并保存,在需要验证数据是否被修改时重新生成hash并与之前保存的hash值进行比对,一旦文件有被修改则会生成不同的hash值。例如可以针对数据库中关键数据字段进行hash,并保存。然后可以通过遍历定期验证hash是否一致,来发现被篡改的数据。
  • SM4:对称加密算法,性能比SM2好
    • 可以用于一般数据的加密与解密,例如可以在需要网络传输的数据发送前进行加密,对方收到数据后使用相同密钥进行解密获得明文。

基于Java的SM4(ECB模式,CBC模式)对称加解密实现

简单说明:加密算法依赖了groupId:org.bouncycastle中的bcprov-jdk15to18,Bouncy Castle (bcprov-jdk15to18)提供了JDK 1.5 to 1.8可使用的大量标准加密算法实现,其中包含了SM2,SM3,SM4。在这个类库基础上实现了一个SM4Util加解密工具类。注意: 此版本我在JDK1.8环境下,不同版本JDK需要找到匹配的依赖版本1.8及以上可以使用bcprov-jdk18on。Bouncy Castle同时也提供了bcutil-jdk15to18可以实现SM4加解密。

方式一:依赖bcprov-jdk15to18(以ECB模式为例)

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.77</version>
</dependency>
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;public class Sm4Utils {static {Security.addProvider(new BouncyCastleProvider());}private static final String ENCODING = "UTF-8";public static final String ALGORIGTHM_NAME = "SM4";public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";public static final int DEFAULT_KEY_SIZE = 128;private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {Cipher cipher = Cipher.getInstance(algorithmName, "BC");Key sm4Key = new SecretKeySpec(key, ALGORIGTHM_NAME);cipher.init(mode, sm4Key);return cipher;}public static byte[] generateKey(String keyString) throws Exception {// Use SHA-256 to hash the string and then take first 128 bits (16 bytes)MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] hash = digest.digest(keyString.getBytes(StandardCharsets.UTF_8));byte[] key = new byte[16];System.arraycopy(hash, 0, key, 0, 16);return key;}public static String encryptEcb(String key, String paramStr, String charset) throws Exception {String cipherText = "";if (null != paramStr && !"".equals(paramStr)) {byte[] keyData = generateKey(key);charset = charset.trim();if (charset.length() <= 0) {charset = ENCODING;}byte[] srcData = paramStr.getBytes(charset);byte[] cipherArray = encryptEcbPadding(keyData, srcData);cipherText = ByteUtils.toHexString(cipherArray);}return cipherText;}public static byte[] encryptEcbPadding(byte[] key, byte[] data) throws Exception {Cipher cipher = generateEcbCipher("SM4/ECB/PKCS7Padding", Cipher.ENCRYPT_MODE, key);byte[] bs = cipher.doFinal(data);return bs;}public static String decryptEcb(String key, String cipherText, String charset) throws Exception {String decryptStr = "";byte[] keyData = generateKey(key);byte[] cipherData = ByteUtils.fromHexString(cipherText);byte[] srcData = decryptEcbPadding(keyData, cipherData);charset = charset.trim();if (charset.length() <= 0) {charset = ENCODING;}decryptStr = new String(srcData, charset);return decryptStr;}public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) throws Exception {Cipher cipher = generateEcbCipher("SM4/ECB/PKCS7Padding", Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}public static void main(String[] args) {try {String json = "311111190001010001";String key = "test";String cipher = encryptEcb(key, json, ENCODING);System.out.println(cipher);System.out.println(decryptEcb(key, cipher, ENCODING));} catch (Exception var5) {var5.printStackTrace();}}
}

方式二:依赖bcprov-jdk15to18(以CBC模式为例),代码根据GPT-4生成修改调试,可运行。

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

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.CBCModeCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.jce.provider.BouncyCastleProvider;import java.security.Security;
import java.util.Arrays;public class SM4Example {static {Security.addProvider(new BouncyCastleProvider());}public static byte[] encrypt(byte[] key, byte[] iv, byte[] data) throws Exception {SM4Engine engine = new SM4Engine();CBCModeCipher cbcBlockCipher = CBCBlockCipher.newInstance(engine);PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(cbcBlockCipher);CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);cipher.init(true, params);byte[] temp = new byte[cipher.getOutputSize(data.length)];int len = cipher.processBytes(data, 0, data.length, temp, 0);len += cipher.doFinal(temp, len);byte[] out = new byte[len];System.arraycopy(temp, 0, out, 0, len);return out;}public static byte[] decrypt(byte[] key, byte[] iv, byte[] data) throws Exception {SM4Engine engine = new SM4Engine();CBCModeCipher cbcBlockCipher = CBCBlockCipher.newInstance(engine);PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(cbcBlockCipher);CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);cipher.init(false, params);byte[] temp = new byte[cipher.getOutputSize(data.length)];int len = cipher.processBytes(data, 0, data.length, temp, 0);len += cipher.doFinal(temp, len);byte[] out = new byte[len];System.arraycopy(temp, 0, out, 0, len);return out;}public static void main(String[] args) throws Exception {byte[] key = "0123456789abcdef".getBytes(); // 16-byte key for SM4byte[] iv = "abcdef9876543210".getBytes(); // 16-byte IV for CBC modebyte[] dataToEncrypt = "Hello, Bouncy Castle SM4!".getBytes();byte[] encryptedData = encrypt(key, iv, dataToEncrypt);System.out.println("Encrypted Data: " + java.util.Base64.getEncoder().encodeToString(encryptedData));byte[] decryptedData = decrypt(key, iv, encryptedData);System.out.println("Decrypted Data: " + new String(decryptedData));}
}

这篇关于国密算法SM2,SM3,SM4简单比较,以及基于Java的SM4(ECB模式,CBC模式)对称加解密实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory