加密与安全_三种方式实现基于国密非对称加密算法的加解密和签名验签

文章目录

  • 国际算法
  • 基础概念
  • 常见的加密算法及分类
  • 签名和验签
    • 基础概念
    • 常见的签名算法
    • 应用场景
  • 国密算法
    • 对称加密(DES/AES⇒SM4)
    • 非对称加密(RSA/ECC⇒SM2)
    • 散列(摘要/哈希)算法(MD5/SHA⇒SM3)
  • Code
    • 方式一 使用Bouncy Castle库实现国密SM2算法的加解密和签名验签功能
    • 方式二 基于Kona库从证书里读取公钥进行加解密和签名验签
    • 方式三 使用基于Bouncy Castle库封装的gm-java库
      • 密码算法
      • 证书
      • 密钥协商
      • 实现

在这里插入图片描述


国际算法

基础概念

  • 加密:将明文转换为密文,以保护数据的机密性。
  • 解密:将密文还原为明文,以便数据可被读取。

常见的加密算法及分类

加密算法主要分为对称加密和非对称加密两大类。

  1. 对称加密

    • 概念:使用相同的密钥进行加密和解密。
    • 优点:加密速度快,适合大数据量加密。
    • 缺点:密钥分发困难,密钥管理复杂。
    • 常见算法
      • AES(高级加密标准):广泛应用于各类数据加密。
      • DES(数据加密标准):已被认为不够安全,逐渐被淘汰。
      • 3DES(三重数据加密标准):通过三次加密提高安全性,但速度较慢。
  2. 非对称加密

    • 概念:使用一对公钥和私钥,其中公钥用于加密,私钥用于解密。
    • 优点:解决了密钥分发问题,公钥可以公开,而私钥需要保密。
    • 缺点:加密和解密速度较慢,通常用于加密小数据或密钥交换。
    • 常见算法
      • RSA:基于大素数分解,广泛用于数字签名和密钥交换。
      • ECC(椭圆曲线密码学):相对于RSA,提供更高的安全性和效率。

签名和验签

基础概念

  • 数字签名:生成消息摘要并使用私钥对摘要进行加密,确保消息的完整性和发送者的身份。
  • 验签:使用发送者的公钥解密消息摘要,并与接收到的消息计算出的摘要进行比较,验证消息的完整性和发送者的身份。

常见的签名算法

  • RSA:常用的数字签名算法,基于公钥和私钥对消息摘要进行加密和解密。
  • DSA(数字签名算法):专为数字签名设计,使用SHA-1或SHA-2生成消息摘要。
  • ECDSA(椭圆曲线数字签名算法):基于椭圆曲线密码学,提供更高效的签名和验证过程。

应用场景

  • 数据传输安全:SSL/TLS协议通过加密和签名技术确保数据传输的机密性和完整性。
  • 身份验证:数字签名用于验证身份,防止数据被篡改。
  • 电子邮件安全:PGP和S/MIME通过加密和签名保护电子邮件内容。
  • 区块链和加密货币:使用数字签名验证交易的合法性。

国密算法

在这里插入图片描述

国产密码算法(国密算法)是指国家密码局认定的国产商用密码算法,在一般信息化系统开发中主要使用公开的SM2(非对称)、SM3(摘要)、SM4(对称)三类算法。

Base64是一种编码格式,并不属于加密,常用于数据传输、兼容性问题。Base64编码本质上是一种将二进制数据转成文本数据的方案,将一些不适合传输的数据内容进行编码来适合传输。

对称加密(DES/AES⇒SM4)

🔸基本特点:

  • 同一个秘钥进行加密、解密。因此秘钥的保密性就很重要,不能泄漏。
  • 计算量小、效率高。

🔸应用场景:

  • 数据加密存储。
  • 加密通信,如HTTPS、SSL、VPN,会与其他加密算法混合使用。

非对称加密(RSA/ECC⇒SM2)

🔸基本特点:

  • 密钥配对:一个私钥、一个公钥,用私钥加密,用公钥解密。注意每一个密钥对都是独一无二、天生一对的,只能配对的秘钥加密、解密。简单来说,公钥加密的数据,只能配对的私钥才能解密。
  • 安全性高,但计算量大。
  • 基本原理:利用某一数学公式,正向计算容易,反向推理则非常难。

🔸应用场景:

  • HPPTS、SSH协议,如Git的ssh认证。
  • HTTPS的安全传输就是混合了非对称加密、对称加密,非对称加密协商会话秘钥,用会话秘钥对称加密传输数据。
  • 敏感数据的加密传输,如客户端登录时传输用户名、密码信息时,采用公钥加密数据,服务端私钥解密。
  • 对数据进行签名、验签,保障数据的完整性,同时验证身份。

散列(摘要/哈希)算法(MD5/SHA⇒SM3)

🔸基本特点:

  • 无需秘钥,“加密”后的数据不可逆。所以这也不算是“加密”,一般称为哈希(Hash)。
  • 任何长度的数据生成的哈希值长度都固定。
  • 相同数据每次生成的哈希值相同,不同的数据则不同。

🔸应用场景:

  • 数据摘要/哈希,验证数据是否被篡改、或数据丢失,保障数据的完整性、不可篡改性。
  • 单向加密保存数据,如密码的保存,密码的存储普遍都是存的哈希值,登录时比较其hash值即可。

🔸彩虹表破解:

由于散列算法的特点(同一数据生成哈希值始终一样),如果存储了大量(海量)字符内容的哈希值,就很容易进行查询破解了,这就是彩虹表,暴力破解也是一样的道理。常用的6位数字密码是相当容易破解的,如CMD5这个网站就利用存储的大量密文字典,反向查询破解。怎么解决呢?

  • 提升散列算法的安全性,常用方法就是加“盐”,核心思想就是在哈希过程中添加一些自定义的内容、规则,仅自己知道,从而避免被字典破解。

  • 最简单的比如在密文中某一位置添加一串随机字符,只有自己知道,使用的时候去掉干扰字符即可。

  • 加盐的具体方式很多,可以自己DIV,常用的一种模式如下图,加盐+双重哈希。 MD5(MD5(password) + salt)

  • 如果加盐的规则被窃取了,对于现代的硬件是挺容易被破解的,只能设置尽量复杂的密码+定期更换了。

📢实际应用中,可能会多种加密算法组合使用。

  • 比如HTTPS的安全数据传输就是同时用了对称加密、非对称加密,用非对称传送(动态)密钥,对称加密传输数据。 《HTTP协议图文简述》

  • 对一个数据进行多重加密,以防被破解


Code

方式一 使用Bouncy Castle库实现国密SM2算法的加解密和签名验签功能

    <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk18on</artifactId><version>1.78.1</version></dependency>
package com.artisan.gmja;import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class Sm2Example {/*** 静态初始化块,在类加载时执行。用于向Java安全提供者列表中添加Bouncy Castle提供者。** Bouncy Castle提供者是一个著名的加密库,添加它是为了支持更多的加密算法和操作。* 这种做法通常用于需要加强加密能力的场景,比如数字签名、加密解密等操作。** 选择在静态初始化块中添加提供者,是因为它在类加载时只执行一次,确保了提供者的添加是全局的和一次性的。* 这样做可以避免在每次使用加密操作时重复添加提供者,提高了代码的效率和可维护性。*/static {Security.addProvider(new BouncyCastleProvider());}/*** 生成SM2密钥对。** @return KeyPair 生成的密钥对,包括公钥和私钥。* @throws Exception 如果密钥对生成过程中发生错误,将抛出异常。*/// 生成密钥对public static KeyPair generateKeyPair() throws Exception {// 实例化KeyPairGenerator对象,并指定算法为EC(椭圆曲线),提供者为BC(Bouncy Castle)KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");// 设置椭圆曲线参数为sm2p256v1,这是SM2算法所使用的特定椭圆曲线ECGenParameterSpec ecSpec = new ECGenParameterSpec("sm2p256v1");// 初始化KeyPairGenerator对象,使用随机数生成器以增加密钥的随机性kpg.initialize(ecSpec, new SecureRandom());// 生成密钥对,并返回return kpg.generateKeyPair();}/*** 使用SM2算法和公钥对数据进行加密。** @param publicKey 公钥,用于加密数据。公钥是密钥对的一部分,用于加密操作,而私钥用于解密。* @param data      待加密的原始明文数据。* @return 加密后的数据以字节数组形式返回。* @throws Exception 如果加密过程中发生错误,将抛出异常。*/// 加密public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {// 实例化Cipher对象,并指定使用SM2算法和BC提供者。Cipher cipher = Cipher.getInstance("SM2", "BC");// 初始化Cipher对象为加密模式,使用给定的公钥。cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 执行加密操作,返回加密后的数据。return cipher.doFinal(data);}/*** 使用SM2算法和私钥对加密数据进行解密。** @param privateKey    解密所需的私钥。私钥是加密过程中使用的公钥的对应部分,*                      只有持有相应私钥的个体才能解密由公钥加密的数据。* @param encryptedData 待解密的加密数据。这些数据是由SM2算法和相应的公钥加密得到的。* @return 返回解密后的原始数据。这些数据在加密前是明文状态,通过解密操作恢复成原始形态。* @throws Exception 如果解密过程中发生错误,例如私钥无效或加密数据格式不正确,将抛出异常。*/// 解密public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws Exception {// 实例化Cipher对象,用于执行解密操作。Cipher是Java加密/解密的核心类。Cipher cipher = Cipher.getInstance("SM2", "BC");// 初始化Cipher对象为解密模式,使用提供的私钥。cipher.init(Cipher.DECRYPT_MODE, privateKey);// 执行解密操作,返回解密后的数据。return cipher.doFinal(encryptedData);}/*** 使用SM2算法和私钥对数据进行数字签名。** @param privateKey 私钥,用于生成数字签名。私钥必须与用于验证签名的公钥匹配。* @param data       待签名的数据,通常为原始消息或消息的哈希值。* @return 返回使用SM2算法和私钥对数据签名后的字节数组。* @throws Exception 如果签名过程中发生错误,将抛出异常。*/// 签名public static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {// 初始化签名对象,指定使用SM3withSM2算法和BC提供者。Signature signature = Signature.getInstance("SM3withSM2", "BC");// 使用私钥初始化签名对象,准备进行签名操作。signature.initSign(privateKey);// 更新签名对象,将待签名的数据加载到签名算法中。signature.update(data);// 执行签名操作,生成数字签名。return signature.sign();}/*** 使用SM2算法和SM3哈希函数验证数据的数字签名。* 此函数用于确认给定的数据是否是由对应的私钥进行签名的,通过公钥进行验证。** @param publicKey      公钥,用于验证签名。* @param data           原始数据,被签名的数据。* @param signatureBytes 数字签名,用于验证数据的真实性和完整性。* @return boolean,如果签名验证成功,则返回true;否则返回false。* @throws Exception 如果在签名验证过程中发生错误,则抛出异常。*/// 验签public static boolean verify(PublicKey publicKey, byte[] data, byte[] signatureBytes) throws Exception {// 实例化签名对象,指定使用SM2算法和SM3哈希函数。Signature signature = Signature.getInstance("SM3withSM2", "BC");// 初始化签名对象为验证模式,使用提供的公钥。signature.initVerify(publicKey);// 更新签名对象,将待验证的数据输入。signature.update(data);// 执行签名验证,返回验证结果。return signature.verify(signatureBytes);}/*** 主函数,用于演示SM2加密算法的使用。* 生成SM2密钥对,并进行加密、解密以及签名、验签操作。** @param args 命令行参数* @throws Exception 如果密钥生成或加解密过程中发生错误*/public static void main(String[] args) throws Exception {// 生成SM2密钥对// 生成密钥对KeyPair keyPair = generateKeyPair();// 获取公钥,并将其转换为Base64编码PublicKey publicKey = keyPair.getPublic();String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());// 输出公钥System.out.println("公钥(Base64): " + publicKeyBase64);// 获取私钥,并将其转换为Base64编码PrivateKey privateKey = keyPair.getPrivate();String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());// 输出私钥System.out.println("私钥(Base64): " + privateKeyBase64);// 准备待加密的明文String plaintext = "I'm Artisan ; 加密算法主要分为对称加密和非对称加密两大类";// 使用公钥加密明文byte[] encryptedData = encrypt(publicKey, plaintext.getBytes());// 使用私钥解密密文byte[] decryptedData = decrypt(privateKey, encryptedData);// 输出明文和解密后的明文System.out.println("原文: " + plaintext);System.out.println("解密后: " + new String(decryptedData));// 将加密后的数据转换为Base64编码,方便展示和传输// 加密数据转Base64字符串String encodedData = Base64.getEncoder().encodeToString(encryptedData);// 从Base64编码还原回加密数据,用于解密// 需要时,从Base64字符串还原回字节数组进行解密byte[] decodedData = Base64.getDecoder().decode(encodedData);// 输出密文(Base64编码)System.out.println("密文: " + encodedData);// 使用私钥对明文进行签名byte[] signature = sign(privateKey, plaintext.getBytes());// 使用公钥验证签名的合法性boolean isVerified = verify(publicKey, plaintext.getBytes(), signature);// 输出签名验证结果System.out.println("签名验证结果: " + isVerified);}}

代码演示了如何使用Bouncy Castle库实现国密SM2算法的加解密和签名验签功能。具体流程如下:

  • 生成SM2密钥对。
  • 使用公钥加密数据,私钥解密数据。
  • 使用私钥对数据签名,公钥验证签名。
  • 输出相关的密钥、密文、解密结果和签名验证结果。

在这里插入图片描述


方式二 基于Kona库从证书里读取公钥进行加解密和签名验签

  <!-- https://mvnrepository.com/artifact/com.tencent.kona/kona-crypto --><dependency><groupId>com.tencent.kona</groupId><artifactId>kona-crypto</artifactId><version>1.0.12</version></dependency><!-- https://mvnrepository.com/artifact/com.tencent.kona/kona-pkix --><dependency><groupId>com.tencent.kona</groupId><artifactId>kona-pkix</artifactId><version>1.0.12</version></dependency><!-- https://mvnrepository.com/artifact/com.tencent.kona/kona-provider --><dependency><groupId>com.tencent.kona</groupId><artifactId>kona-provider</artifactId><version>1.0.12</version></dependency><!-- https://mvnrepository.com/artifact/com.tencent.kona/kona-ssl --><dependency><groupId>com.tencent.kona</groupId><artifactId>kona-ssl</artifactId><version>1.0.12</version></dependency>
package com.artisan.kona;import com.tencent.kona.crypto.CryptoInsts;
import com.tencent.kona.crypto.KonaCryptoProvider;
import com.tencent.kona.pkix.KonaPKIXProvider;
import com.tencent.kona.pkix.PKIXInsts;
import com.tencent.kona.ssl.KonaSSLProvider;
import com.tencent.kona.sun.security.x509.SMCertificate;import javax.crypto.Cipher;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/public class GmEnDeUtil {/*** 私钥字符串*/private static String privateKey = "MIGHAgEA省略省略省略-----ODxilTt74";/*** 公钥证书字符串*/private static String publicPEM = "-----BEGIN CERTIFICATE-----\n" +"MII省略省略省略-----d/s8iNVcYJ1\n" +"-----END CERTIFICATE-----\n";/*** 使用EC(椭圆曲线)加密算法进行加解密和数字签名的操作。* 包括了私钥的解码和生成、公钥证书的加载、数据的签名和验证、以及数据的加密和解密。** @param args 命令行参数* @throws Exception 如果操作过程中发生错误*/public static void main(String[] args) throws Exception {// 注册加密、PKIX和SSL提供者,这些提供者为Java加密系统提供了额外的功能和支持。Security.addProvider(new KonaCryptoProvider());Security.addProvider(new KonaPKIXProvider());Security.addProvider(new KonaSSLProvider());// 解码私钥并生成私钥对象,用于后续的签名操作。byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);KeyFactory keyFactory = CryptoInsts.getKeyFactory("EC");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);// 输出私钥的算法和格式信息。System.out.println("私钥算法" + privateKey.getAlgorithm());System.out.println("私钥格式" +privateKey.getFormat());// 对字符串进行签名,证明数据的完整性和来源。String message = "I‘ artisan ,这是基于Tencent的Kona库实现的签名验签";// 私钥签名String sign = sign(message, privateKey);System.out.println("签名:" + sign);// 加载公钥证书,用于验证签名和加密数据。// 加载公钥证书X509Certificate certificate = loadCert(publicPEM, "9876543210");System.out.println("证书主题:" + certificate.getSubjectX500Principal().getName());PublicKey publicKey = certificate.getPublicKey();// 验证签名的有效性。System.out.println("验证结果:" + verify(message, publicKey, sign));// 使用公钥加密字符串。// 加密和解密字符串 (公钥加密,私钥解密)String encryptedString = encrypt(message, publicKey);System.out.println("加密字符串:" + encryptedString);// 使用私钥解密字符串。String decryptedString = decrypt(encryptedString, privateKey);System.out.println("解密字符串:" + decryptedString);}/*** 从PEM格式的字符串加载X.509证书。** @param certPEM 证书的PEM格式字符串。* @param id      证书的唯一标识符,可选。* @return 加载成功的X.509证书。* @throws Exception 如果加载过程中发生错误。*/private static X509Certificate loadCert(String certPEM, String id) throws Exception {// 创建X.509证书工厂CertificateFactory certFactory = PKIXInsts.getCertificateFactory("X.509");// 从PEM格式的字符串生成证书对象X509Certificate x509Cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certPEM.getBytes()));// 如果提供了ID,并且ID不为空,则为证书设置IDif (id != null && !id.isEmpty()) {// 这里假设SMCertificate是X509Certificate的一个子类,且提供了setId方法((SMCertificate) x509Cert).setId(id.getBytes(StandardCharsets.UTF_8));}// 返回加载成功的证书return x509Cert;}/*** 使用SM2私钥对给定字符串进行数字签名。* <p>* 数字签名用于验证消息的完整性和发送者的身份。此方法使用SM2加密算法,* 基于给定的私钥对字符串进行签名,以确保数据在传输过程中的安全性和真实性。** @param str        待签名的字符串。* @param privateKey 用于签名的私钥。* @return 返回经过SM2签名算法处理后的签名字符串,使用Base64编码。* @throws Exception 如果签名过程中发生错误,则抛出异常。*/private static String sign(String str, PrivateKey privateKey) throws Exception {// 获取SM2签名实例Signature signature = CryptoInsts.getSignature("SM2");// 初始化签名过程,使用提供的私钥signature.initSign(privateKey);// 更新待签名的数据signature.update(str.getBytes());// 执行签名操作,并将结果编码为Base64字符串返回return Base64.getEncoder().encodeToString(signature.sign());}/*** 使用SM2公钥验证数据的签名是否有效。** @param str       待验证签名的数据。* @param publicKey 用于验证签名的公钥。* @param sign      待验证的签名字符串。* @return 如果签名验证通过,则返回true;否则返回false。* @throws Exception 如果加密操作失败,抛出异常。*/private static boolean verify(String str, PublicKey publicKey, String sign) throws Exception {// 获取SM2签名实例Signature signature = CryptoInsts.getSignature("SM2");// 初始化签名验证器signature.initVerify(publicKey);// 更新待验证数据signature.update(str.getBytes());// 验证签名,返回验证结果return signature.verify(Base64.getDecoder().decode(sign));}/*** 使用SM2公钥对字符串进行加密。* <p>* SM2是一种基于椭圆曲线密码学的加密算法,适用于我国的加密技术标准。* 本方法通过获取SM2加密实例,使用给定的公钥将原始字符串加密为密文。* 加密后的密文通过Base64编码转换为字符串形式返回,便于存储或传输。** @param str       待加密的原始字符串。* @param publicKey 用于加密的SM2公钥。* @return 加密后的密文,以Base64编码的字符串形式表示。* @throws Exception 如果加密过程中发生错误,将抛出异常。*/private static String encrypt(String str, PublicKey publicKey) throws Exception {// 获取SM2加密实例Cipher cipher = CryptoInsts.getCipher("SM2");// 初始化加密器,设置为加密模式,并使用给定的公钥cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 执行加密操作,将原始字符串转换为加密后的字节数组byte[] encryptedBytes = cipher.doFinal(str.getBytes());// 将加密后的字节数组通过Base64编码转换为字符串形式返回return Base64.getEncoder().encodeToString(encryptedBytes);}/*** 使用SM2私钥解密字符串。* <p>* SM2是一种国密算法,适用于数据解密。本方法接收一个经Base64编码的加密字符串和对应的私钥,* 通过SM2算法解密后返回原始字符串。** @param str        经Base64编码且使用SM2算法加密的字符串。* @param privateKey 解密所需的SM2私钥。* @return 解密后的原始字符串。* @throws Exception 如果解密过程中发生错误,则抛出异常。*/// 使用私钥解密字符串private static String decrypt(String str, PrivateKey privateKey) throws Exception {// 获取SM2加密算法的Cipher实例Cipher cipher = CryptoInsts.getCipher("SM2");// 初始化Cipher为解密模式,使用提供的私钥cipher.init(Cipher.DECRYPT_MODE, privateKey);// 解密Base64编码的字符串,得到原始字节数组byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(str));// 将解密后的字节数组转换为字符串并返回return new String(decryptedBytes);}}

在这里插入图片描述


方式三 使用基于Bouncy Castle库封装的gm-java库

https://gitee.com/RuanKongkong/gm-java

密码算法

  • 对称密码算法 SM4(ECB/CBC/CTR/GCM)
  • 非对称密码算法 SM2(加解密/签名验签)
  • Hash算法 SM3
  • 基于SM3实现的随机数生成器(多线程加速)

证书

  • 证书解析以及证书SHA1指纹计算
  • SM2证书生成

密钥协商

  • 模拟TLS握手协议,通信双方协商会话密钥

实现

  <dependency><groupId>io.github.KongkongRuan</groupId><artifactId>gm-java</artifactId><version>1.0.3</version></dependency>

在这里插入图片描述

package com.artisan.gmja;import com.yxj.gm.SM2.Cipher.SM2Cipher;
import com.yxj.gm.SM2.Key.SM2KeyPairGenerate;
import com.yxj.gm.SM2.Signature.SM2Signature;
import com.yxj.gm.SM3.SM3Digest;
import com.yxj.gm.SM4.SM4Cipher;
import com.yxj.gm.SM4.dto.AEADExecution;
import com.yxj.gm.enums.ModeEnum;
import com.yxj.gm.random.Random;
import org.bouncycastle.util.encoders.Hex;import java.security.KeyPair;
import java.security.SecureRandom;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class GmJavaExample {/*** 主函数,用于演示各种密码学算法的使用,包括SM2加解密、签名验签、SM3摘要计算、SM4加解密。* @param args 命令行参数*/public static void main(String[] args) {// 定义测试消息String msg = "I'm artisan , 使用基于Bouncy Castle库封装的gm-java库";// 生成SM2密钥对KeyPair keyPair = SM2KeyPairGenerate.generateSM2KeyPair();// 使用SM2密钥对进行加密和解密SM2Cipher sm2Cipher = new SM2Cipher();byte[] encrypted = sm2Cipher.SM2CipherEncrypt(msg.getBytes(), keyPair.getPublic().getEncoded());byte[] decrypted = sm2Cipher.SM2CipherDecrypt(encrypted, keyPair.getPrivate().getEncoded());// 输出解密结果System.out.println("SM2解密结果:" + new String(decrypted));// 使用SM2密钥对进行签名和验证SM2Signature signature = new SM2Signature();byte[] signatureBytes = signature.signature(msg.getBytes(), null, keyPair.getPrivate().getEncoded());boolean verificationResult = signature.verify(msg.getBytes(), null, signatureBytes, keyPair.getPublic().getEncoded());// 输出验签结果System.out.println("SM2验签结果:" + verificationResult);// SM3摘要计算示例SM3Digest sm3Digest = new SM3Digest();sm3Digest.update(msg.getBytes());byte[] digest1 = sm3Digest.doFinal();byte[] digest2 = sm3Digest.doFinal(msg.getBytes());sm3Digest.update("gm-java-".getBytes());sm3Digest.update("1.0".getBytes());byte[] digest3 = sm3Digest.doFinal();// 输出摘要的十六进制表示System.out.println(Hex.toHexString(digest1));System.out.println(Hex.toHexString(digest2));System.out.println(Hex.toHexString(digest3));// 通过SM3算法生成随机数byte[] random = Random.RandomBySM3(16);System.out.println(Hex.toHexString(random));// SM4加解密示例,包括ECB、CBC、CTR和GCM模式SecureRandom secureRandom = new SecureRandom();byte[] key = new byte[16];byte[] iv = new byte[16];secureRandom.nextBytes(key);secureRandom.nextBytes(iv);// ECB模式SM4Cipher sm4CipherECB = new SM4Cipher(ModeEnum.ECB);byte[] encryptedECB = sm4CipherECB.cipherEncrypt(key, msg.getBytes(), null);byte[] decryptedECB = sm4CipherECB.cipherDecrypt(key, encryptedECB, iv);System.out.println("ECB明文:" + new String(decryptedECB));// CBC模式SM4Cipher sm4CipherCBC = new SM4Cipher(ModeEnum.CBC);byte[] encryptedCBC = sm4CipherCBC.cipherEncrypt(key, msg.getBytes(), iv);byte[] decryptedCBC = sm4CipherCBC.cipherDecrypt(key, encryptedCBC, iv);System.out.println("CBC明文:" + new String(decryptedCBC));// CTR模式SM4Cipher sm4CipherCTR = new SM4Cipher(ModeEnum.CTR);byte[] encryptedCTR = sm4CipherCTR.cipherEncrypt(key, msg.getBytes(), iv);byte[] decryptedCTR = sm4CipherCTR.cipherDecrypt(key, encryptedCTR, iv);System.out.println("CTR明文:" + new String(decryptedCTR));// GCM模式SM4Cipher sm4_gcm = new SM4Cipher();AEADExecution aeadExecution = sm4_gcm.cipherEncryptGCM(key, msg.getBytes(), new byte[12], "aad".getBytes(), 16);System.out.println("GCM密文:" + Hex.toHexString(aeadExecution.getCipherText()));System.out.println("GCMtag:" + Hex.toHexString(aeadExecution.getTag()));byte[] decryptedGCM = sm4_gcm.cipherDecryptGCM(key, aeadExecution.getCipherText(), new byte[12], "aad".getBytes(), aeadExecution.getTag());System.out.println("GCM明文:" + new String(decryptedGCM));}}

输出如下:

SM2解密结果:I'm artisan , 使用基于Bouncy Castle库封装的gm-java库
SM2验签结果:true
080239d4f27412428a25c1f86d2523e4e9c6ed1d9b94e579632d77bc6d44794f
080239d4f27412428a25c1f86d2523e4e9c6ed1d9b94e579632d77bc6d44794f
cc7e992374984c82ab13f3f117d52849970628d16acf4cc1d9c137953e23a418
c963dee9f6945ec7c0a42379a576dabe
ECB明文:I'm artisan , 使用基于Bouncy Castle库封装的gm-java库
CBC明文:I'm artisan , 使用基于Bouncy Castle库封装的gm-java库
CTR明文:I'm artisan , 使用基于Bouncy Castle库封装的gm-java库
GCM密文:742d77292544e52da4c8f098dd5bd93b3bf8e9fd93a99bba1f0ab61a438074a9389ba6484664bb7dc899592e849b4c5cc2b3db0d9590e0e45b91fad85b
GCMtag:aac12ba04924fef14eaa0e896a346a45
GCM明文:I'm artisan , 使用基于Bouncy Castle库封装的gm-java库

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/863482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧园区综合平台解决方案PPT(75页)

## 智慧园区的理解 ### 从园区1.0到园区4.0的演进 1. 园区1.0&#xff1a;以土地经营为主&#xff0c;成本驱动&#xff0c;提供基本服务。 2. 园区2.0&#xff1a;服务驱动&#xff0c;关注企业成长&#xff0c;提供增值服务。 3. 园区3.0&#xff1a;智慧型园区&#xff…

机器学习引领教育革命:智能教育的新时代

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习在教育中的应用&#x1f31e;个性化学习&#x1f319;评估与反馈的智能化⭐教学资源的优…

spring-boot-configuration-processor注释处理器

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ spring-boot-configuration-processor是springboot提供的一个注释处理器&#xff08;annotation processor&#xff09;,它用于在编译…

Python多线程Concurrent

背景 从 Python3.2 开始&#xff0c;标准库为我们提供了 concurrent.futures 模块&#xff0c;它提供了 ThreadPoolExecutor 和 ProcessPoolExecutor两个类&#xff0c;实现了对 threading 和 multiprocessing 的进一步抽象&#xff08;这里主要关注线程池&#xff09;&#x…

STC89C52RC单片机设计的FM收音机+自动搜台+存储电台(程序+原理图+PCB)

资料下载地址&#xff1a;STC89C52RC单片机设计的FM收音机自动搜台存储电台&#xff08;程序原理图PCB) 1、实物图 2、部分程序 #include <reg52.h> #include "tea5767.h" #include "delay.h" #include "lcd1602.h" //K1:上一台 K2:下一…

mac电脑游戏推荐:NBA 2K24 街机版下载

NBA 2K24 街机版是一款由2K Sports开发并发行的篮球游戏&#xff0c;属于著名的NBA 2K系列。这款游戏为玩家提供了与NBA联赛中真实球员和球队互动的机会&#xff0c;体验篮球比赛的激情与紧张。街机版的NBA 2K24通常会在游戏厅、商场等公共场所设置&#xff0c;供玩家投币游玩。…

ubuntu server的安装

官网&#xff1a;https://ubuntu.com/ 点击 Get Ubuntu,选择Server&#xff0c;点击Get Ubuntu Server,下载iso到本地。 相关资料&#xff1a; Ubuntu Server 20.04详细安装教程虚拟机安装 Ubuntu

c++重载(运算符)

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 对于系统的所有操作符&#xff0c;一般情况下&#xff0c;只支持基本数…

Android Gradle 开发与应用 (二): Android 项目结构与构建配置

目录 1. Android 项目的 Gradle 文件结构 1.1 项目根目录 1.2 模块目录 2. Gradle 构建配置详解 2.1 配置 Android 项目的 build.gradle 2.2 配置模块的 build.gradle 2.3 使用 productFlavors 管理多版本应用 2.4 使用 buildConfigField 注入构建常量 在 Android 开发…

AWTK 用 icon_at 属性设置图标位置

1. style 在 style 文件中通过 icon_at 属性设置图标位置。 <style name"right_bottom" icon_at"right_bottom"><normal icon"unchecked_right_bottom" /><pressed icon"unchecked_right_bottom" /><over i…

redis实战-短信登录

基于session的登录流程 session的登录流程图 1. 发送验证码 用户在提交手机号后&#xff0c;会校验手机号是否合法&#xff0c;如果不合法&#xff0c;则要求用户重新输入手机号 如果手机号合法&#xff0c;后台此时生成对应的验证码&#xff0c;同时将验证码进行保存&#x…

第2章:程序设计语言

第2章&#xff1a;程序设计语言 在源程序中&#xff0c;可由用户&#xff08;程序员&#xff09;为变量、函数和数据类型等命名。 脚本语言一般运行在解释器或虚拟机中&#xff0c;便于移植&#xff0c;开发效率较高。 变量是计算机内存单元的抽象&#xff0c;在程序中表示数据…

1186. 删除一次得到子数组最大和(leetcode)

1186. 删除一次得到子数组最大和&#xff08;leetcode&#xff09; 题目描述 给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和。换句话说&#xff0c;你可以从原数组中选…

第一节:如何开发第一个spring boot3.x项目(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;从今天开始&#xff0c;我会记录每篇我自学spring boot3.x的经验。只要我不偷懒&#xff0c;学完应该很快&#xff0c;哈哈&#xff0c;更新速度尽可能快&#xff0c;想和大佬们一块讨论&#xff0c;如果需要讨论的欢迎一起评论区留…

Pytorch实战(二)

文章目录 前言一、LeNet5原理1.1LeNet5网络结构1.2LeNet网络参数1.3LeNet5网络总结 二、AlexNext2.1AlexNet网络结构2.2AlexNet网络参数2.3Dropout操作2.4PCA图像增强2.5LRN正则化2.6AlexNet总结 三、实战3.1LeNet5模型搭建3.2模型训练 前言 参考原视频&#xff1a;哔哩哔哩。 …

kafka和rabbitmq的区别

1、语言与开发重点 1、Kafka&#xff1a;采用Scala语言开发&#xff0c;主要用于处理活跃的流式数据和大数据量的数据处理。 2、RabbitMQ&#xff1a;由Erlang语言开发&#xff0c;主要用在实时对可靠性要求比较高的消息传递上。 2、结构与交互方式&#xff1a; 1、Kafka&a…

Java中的WebSocket编程详解

Java中的WebSocket编程详解 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在当今互联网应用中&#xff0c;实时通讯变得越来越重要&#xff0c;而WebSocket作为…

【后端面试题】【中间件】【NoSQL】ElasticSearch面试基本思路和高可用方案(限流、消息队列、协调节点、双集群)

基本思路 业务开发面试Elasticsearch的时候基本问的是基础知识以及倒排索引。 Elasticsearch最基本的可用性保障就是分片&#xff0c;而且是主从分片&#xff0c;所以遇到Elasticsearch如何做到高可用这个问题的时候&#xff0c;首先要提到这一点。 Elasticsearch高可用的核心…

【Android】ViewPage2嵌套Fragment+SeekBar横向滑动冲突

问题描述 ViewPage2嵌套FragmentSeekBar&#xff0c;拖动SeekBar的进度条时&#xff0c;触发ViewPage2的滑动。 解决方案&#xff1a; 方案一&#xff1a;通过事件总线ViewPage2的isUserInputEnabled属性 子Fragment&#xff1a; class SeekBarFragment : Fragment() {priv…

手机屏幕贴合项目(ni视觉如何找矩形的角坐标)

首先&#xff0c;我们存储了cg和dito感兴趣八个角图像的模板&#xff0c;用来匹配位置。 cover指的是cg的四个角模板&#xff0c;lcm是dito四个角匹配模板。 其次&#xff0c;我们采集的8副图像&#xff08;m_DlgCCDViewArr[2][4]&#xff09;中一定包含匹配模板的特征。 好&…