【Java】国密SM3/SM4(附工具类)

目录

  • 前言
  • 国密算法
    • SM1对称加密算法
      • SM1算法的基本原理
      • SM1算法的应用场景
      • SM1算法的优势
      • 代码示例
    • SM2非对称加密算法
      • SM2算法的基本原理
      • SM2算法的应用场景
      • SM2算法的优势
      • 代码示例
        • 依赖
        • 代码
    • SM3杂凑算法
    • SM4分组密码算法
  • SM3、SM4工具类示例
    • 依赖
    • SM3工具类
    • SM4工具类
      • CBC
      • ECB

前言

  • 目前形式国内都在推行国产化,例如:国产化数据库,国产化服务器等。
  • 我上家公司其中一条产品线是做电网项目的,其中加密的方式就要求使用国密加密算法,SM3和SM4,所以说国产化应该是一个趋势。
  • 国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。

国密算法

  • 国密算法,全称为中国密码算法国家标准,是由中国国家密码管理局主导制定的一套密码算法标准。
  • 国密算法包括以下四种:
    • SM1对称加密算法
    • SM2非对称加密算法
    • SM3杂凑算法
    • SM4分组密码算法
  • 国密算法在国家信息安全领域得到了广泛应用,被用于政务通信、金融支付、电子商务、云计算等领域。
  • 其目的是为了保护国家信息安全和个人隐私,增强国内密码产品和系统的自主可控能力。

SM1对称加密算法

  • SM1对称加密算法是一种高效的分组密码算法,适用于对称加密和消息认证码,其安全性与国际上的AES算法相近。

SM1算法的基本原理

  • SM1算法是一种分组密码,采用对称密钥方式,将明文按照固定长度分组,然后对每个分组进行加密和解密。
  • 该算法的关键在于密钥的生成和密钥的长度。
  • SM1算法的密钥长度为128位,密钥生成过程中采用了多种随机数生成器,保证了密钥的随机性和安全性。

SM1算法的应用场景

  1. 电子政务:SM1算法可以用于电子政务中的公文传输、公文存储和电子签章等场景,保证数据的机密性和完整性。
  2. 金融行业:SM1算法可以用于金融行业中的网上银行、移动支付和电子钱包等场景,保护用户的个人信息和资金安全。
  3. 医疗卫生:SM1算法可以用于医疗卫生中的电子病历、远程医疗和医疗数据存储等场景,确保医疗信息的机密性和完整性。
  4. 物联网:SM1算法可以用于物联网中的传感器网络、智能家居和智能交通等场景,保障物联网设备的通信安全和数据隐私。
  5. 云计算:SM1算法可以用于云计算中的数据加密、云存储和虚拟化等场景,保证云服务的安全性和可靠性。

SM1算法的优势

  1. 高安全性:SM1算法的密钥长度为128位,相比其他对称加密算法具有更高的安全性。此外,该算法的密钥生成过程中采用了多种随机数生成器,保证了密钥的随机性和安全性。
  2. 高效性:SM1算法的加解密速度较快,适用于大规模的数据加解密和安全通信同。时,该算法的软硬件实现成本较低,方便在各种设备上应用。
  3. 广泛适用性:SM1算法适用于各种不同的应用场景,包括电子政务、金融行业、医疗卫生、物联网和云计算等。该算法的应用范围广泛,可以满足不同领域的安全需求。
  4. 国家标准:SM1算法是中国的国家密码标准之一,被广泛应用于国家重要信息系统的数据加密和安全通信领域。该算法得到了国家的支持和认可,具有较高的可靠性和安全性。

代码示例

import javax.crypto.Cipher;  
import javax.crypto.spec.SecretKeySpec;  
import java.nio.charset.StandardCharsets;  
import java.util.Base64;  public class AESUtil {  private static final String ALGORITHM = "AES";  private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; // 使用ECB模式和PKCS5Padding填充  // 使用AES加密  public static String encrypt(String key, String value) throws Exception {  SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);  Cipher cipher = Cipher.getInstance(TRANSFORMATION);  cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);  byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));  return Base64.getEncoder().encodeToString(encrypted);  }  // 使用AES解密  public static String decrypt(String key, String encrypted) throws Exception {  SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);  Cipher cipher = Cipher.getInstance(TRANSFORMATION);  cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);  byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));  return new String(original, StandardCharsets.UTF_8);  }  // 示例用法  public static void main(String[] args) throws Exception {  String key = "your_16_byte_key_here_for_aes"; // AES密钥需要是16字节(128位)  String value = "Hello, World!";  String encrypted = encrypt(key, value);  System.out.println("Encrypted: " + encrypted);  String decrypted = decrypt(key, encrypted);  System.out.println("Decrypted: " + decrypted);  }  
}

SM2非对称加密算法

  • SM2非对称加密算法是基于椭圆曲线密码体制的数字签名算法和密钥交换协议,安全性较高。

SM2算法的基本原理

  • SM2使用非对称密钥加密体制,包括公钥和私钥。
  • 公钥用于加密数据和验证数字签名,私钥用于解密数据和生成数字签名。

SM2算法的应用场景

  1. 数据加密:
    • SM2算法可用于加密和解密数据,保障数据传输的安全性。它利用公钥进行加密,私钥进行解密,确保数据在传输过程中的机密性。
    • 在网络安全领域,SM2算法常被用于保护敏感信息的传输,如电子邮件加密、文件传输加密等。
  2. 数字签名:
    • SM2算法可用于生成数字签名,验证文档或数据的完整性和真实性。通过私钥对消息进行签名,利用公钥进行验证,确保数据在传输过程中未被篡改,并验证发送方的身份。
    • 数字签名在电子认证、电子合同、电子票据等领域具有广泛应用,如网上银行交易、电子政务等。
  3. 身份认证:
    • SM2算法可用于身份认证,验证用户的身份信息。通过公钥和私钥的配对使用,可以确保用户身份的真实性和可信度。
    • 在网络安全领域,SM2算法常被用于用户登录、权限管理等场景,保障系统的安全性和可信度。
  4. 密钥交换:
    • SM2算法支持密钥交换功能,通过公钥和私钥的配对使用,可以安全地协商出共享密钥,用于后续的对称加密通信。
    • 密钥交换在网络安全通信中具有重要意义,可以确保通信双方之间密钥的安全传输和共享。
  5. 国家安全领域:
    • 作为中国国家密码管理局颁布的国家标准,SM2算法在中国国内得到广泛应用,特别是在政府机构和企业的信息安全领域。
    • 它符合国家密码管理政策,有利于保障国家信息安全,防止外部攻击和数据泄露。
  6. 国际认可:
    • 虽然SM2是中国的国家标准,但它在一定程度上也获得了国际认可。部分国际组织和标准化机构也开始考虑将其作为一种可选的加密算法。

SM2算法的优势

  1. 安全性高:
    • SM2算法基于椭圆曲线离散对数难题,这一数学问题的复杂性保证了算法的安全性。
    • 与RSA算法相比,SM2算法在同等安全水平下,所需的密钥长度和签名长度更短,从而降低了被破解的风险。
    • SM2算法被认为在经典计算机和量子计算机的攻击下都是安全的。
  2. 效率高:
    • SM2算法具有较高的运算效率,特别是在加密、解密和数字签名方面,性能优于RSA算法。
    • 它适合高并发场景,满足大量数据加密、解密和数字签名的需求。
    • SM2算法的CPU占用少、内容使用少、网络消耗低,特别适用于移动设备和资源受限的环境。
  3. 灵活性好:
    • SM2算法支持多种密钥长度,可以根据实际需求灵活选择密钥长度,适用于不同的应用场景。
  4. 自主创新:
    • 它符合国家密码管理政策,有利于保障国家关键信息系统的信息安全。
  5. 技术特点:
    • SM2算法基于椭圆曲线密码学,具备ECC算法的性能特点并实现优化改进。
    • 它采用了一系列安全性增强措施,如密钥派生函数和随机数生成算法,以防止各种攻击。

代码示例

依赖
<dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcprov-jdk15on</artifactId>  <version>最新版本</version>  
</dependency>
代码
import org.bouncycastle.crypto.CipherParameters;  
import org.bouncycastle.crypto.engines.SM2Engine;  
import org.bouncycastle.crypto.params.ECPublicKeyParameters;  
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;  
import org.bouncycastle.crypto.params.SM2PrivateKeyParameters;  
import org.bouncycastle.crypto.params.SM2PublicKeyParameters;  
import org.bouncycastle.jce.ECNamedCurveGenParameterSpec;  
import org.bouncycastle.jce.ECNamedCurveTable;  
import org.bouncycastle.jce.provider.BouncyCastleProvider;  
import org.bouncycastle.jce.spec.ECParameterSpec;  import java.security.KeyPair;  
import java.security.KeyPairGenerator;  
import java.security.PrivateKey;  
import java.security.PublicKey;  
import java.security.Security;  public class SM2Utils {  static {  Security.addProvider(new BouncyCastleProvider());  }  // 生成SM2密钥对  public static KeyPair generateKeyPair() throws Exception {  KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BC");  ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");  keyGen.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1"), new java.security.SecureRandom());  return keyGen.generateKeyPair();  }  // 此处仅为示例,实际使用中需要实现更完整的加密/解密/签名/验签逻辑  // 加密/解密、签名/验签的逻辑将涉及更复杂的参数设置和异常处理  // 注意:Bouncy Castle的org.bouncycastle.crypto包与Java的javax.crypto包不同  // 下面的示例仅为框架,并未包含完整的加密/解密逻辑  public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {  // 需要实现使用SM2公钥的加密逻辑  // ...  return null; // 示例返回null,实际应返回加密后的数据  }  public static byte[] decrypt(PrivateKey privateKey, byte[] cipherText) throws Exception {  // 需要实现使用SM2私钥的解密逻辑  // ...  return null; // 示例返回null,实际应返回解密后的数据  }  public static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {  // 需要实现使用SM2私钥的签名逻辑  // ...  return null; // 示例返回null,实际应返回签名数据  }  public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature) throws Exception {  // 需要实现使用SM2公钥的验签逻辑  // ...  return false; // 示例返回false,实际应返回验签结果  }  // ... 其他辅助方法或工具方法 ...  
}

SM3杂凑算法

  • SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。
  • SM3杂凑算法是一种散列算法,用于将输入的数据转化为固定长度的摘要,具有抗碰撞、抗第二原像和抗预像等特性。
  • SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。
  • 为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。

SM4分组密码算法

  • SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。
  • SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。
  • 要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。

SM3、SM4工具类示例

依赖

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

SM3工具类

package com.mkj.publicservice.utils.smalgorithm;import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;import java.io.UnsupportedEncodingException;/*** @author: mkj*/
public class Sm3Util {/*** SM3加密* @param content  要加密的内容*/public static String  Sm3EncryptText(String content) throws UnsupportedEncodingException {byte[] bytes = content.getBytes();byte[] hash = hash(bytes);String sm3 = ByteUtils.toHexString(hash);System.out.println("[Sm3EncryptText]sm3 hex:" + sm3);return sm3;}public static byte[] hash(byte[] srcData){SM3Digest digest=new SM3Digest();digest.update(srcData,0,srcData.length);byte[] bytes = new byte[digest.getDigestSize()];digest.doFinal(bytes,0);return bytes;}/*** sm3算法通过密钥进行加密,不可逆加密* @param keyText 密钥字符串* @param plainText 需加密的明文字符串* @return 加密后固定长度64的16进制字符串*/public static String encryptByKey(String keyText, String plainText) {return ByteUtils.toHexString(encryptByKey(keyText.getBytes(), plainText.getBytes()));}/*** sm3算法通过密钥进行加密,不可逆加密* @param keyByte 密钥数组* @param plainByte 需加密的明文数组* @return 加密后固定长度64的16进制数组*/public static byte[] encryptByKey(byte[] keyByte, byte[] plainByte) {KeyParameter keyParameter = new KeyParameter(keyByte);SM3Digest sm3Digest = new SM3Digest();HMac hMac = new HMac(sm3Digest);hMac.init(keyParameter);hMac.update(plainByte, 0, plainByte.length);byte[] result = new byte[hMac.getMacSize()];hMac.doFinal(result, 0);return result;}/*** 主函数* @param args*/public static void main(String[] args) throws UnsupportedEncodingException {Sm3EncryptText("ceshi001");System.out.println(encryptByKey("key001","abc"));}}

SM4工具类

  • SM4两种算法,基于ECB和CBC。示例中key都使用了16进制的字符串,有的项目没有需求可以自行去除。看实际情况。

CBC

package com.mkj.publicservice.utils.smalgorithm;import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;/*** @author: mkj*/
public class Sm4CbcUtils {static {Security.addProvider(new BouncyCastleProvider());}private static final String ENCODING = "UTF-8";public static final String ALGORITHM_NAME = "SM4";// 加密算法/分组加密模式/分组填充方式// PKCS5Padding-以8个字节为一组进行分组加密// 定义分组加密模式使用:PKCS5Paddingpublic static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";// 128-32位16进制;256-64位16进制public static final int DEFAULT_KEY_SIZE = 128;/*** 自动生成密钥** @return* @explain*/public static byte[] generateKey() throws Exception {return generateKey(DEFAULT_KEY_SIZE);}/*** 自动生成密钥* @return* @throws Exception*/public static String generateKeyString() throws Exception {return ByteUtils.toHexString(generateKey());}/*** @param keySize* @return* @throws Exception* @explain*/public static byte[] generateKey(int keySize) throws Exception {KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);kg.init(keySize, new SecureRandom());return kg.generateKey().getEncoded();}/*** sm4加密** @param hexKey   16进制密钥(忽略大小写)* @param paramStr 待加密字符串* @return 返回16进制的加密字符串* @throws Exception* @explain 加密模式:CBC*/public static String encrypt(String hexKey, String paramStr) throws Exception {String result = "";// 16进制字符串-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// String-->byte[]byte[] srcData = paramStr.getBytes(ENCODING);// 加密后的数组byte[] cipherArray = encryptCbcPadding(keyData, srcData);// byte[]-->hexStringresult = ByteUtils.toHexString(cipherArray);return result;}/*** 加密模式之CBC** @param key* @param data* @return* @throws Exception* @explain*/public static byte[] encryptCbcPadding(byte[] key, byte[] data) throws Exception {Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/*** 加密模式之CBC* @param algorithmName* @param mode* @param key* @return* @throws Exception*/private static Cipher generateCbcCipher(String algorithmName, int mode, byte[] key) throws Exception {Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);cipher.init(mode, sm4Key, generateIV());return cipher;}/*** 生成iv* @return* @throws Exception*/public static AlgorithmParameters generateIV() throws Exception {//iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0byte[] iv = new byte[16];Arrays.fill(iv, (byte) 0x00);AlgorithmParameters params = AlgorithmParameters.getInstance(ALGORITHM_NAME);params.init(new IvParameterSpec(iv));return params;}/*** sm4解密** @param hexKey 16进制密钥* @param text   16进制的加密字符串(忽略大小写)* @return 解密后的字符串* @throws Exception* @explain 解密模式:采用CBC*/public static String decrypt(String hexKey, String text) throws Exception {// 用于接收解密后的字符串String result = "";// hexString-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// hexString-->byte[]byte[] resultData = ByteUtils.fromHexString(text);// 解密byte[] srcData = decryptCbcPadding(keyData, resultData);// byte[]-->Stringresult = new String(srcData, ENCODING);return result;}/*** 解密** @param key* @param cipherText* @return* @throws Exception* @explain*/public static byte[] decryptCbcPadding(byte[] key, byte[] cipherText) throws Exception {Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}public static void main(String[] args) throws Exception {String str = "Hello, world" ;System.out.println("==========生成密钥==========");String generateKey = generateKeyString();System.out.println(generateKey);System.out.println("==========加密==========");String encrypt = encrypt(generateKey, str);System.out.println(encrypt);System.out.println("==========解密==========");String decrypt = decrypt(generateKey, encrypt);System.out.println(decrypt);}
}

ECB

package com.mkj.publicservice.utils.smalgorithm;import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;/*** @author: mkj*/
public class Sm4EcbUtils {static {Security.addProvider(new BouncyCastleProvider());}private static final String ENCODING = "UTF-8";public static final String ALGORITHM_NAME = "SM4";// 加密算法/分组加密模式/分组填充方式// PKCS5Padding-以8个字节为一组进行分组加密// 定义分组加密模式使用:PKCS5Paddingpublic static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";// 128-32位16进制;256-64位16进制public static final int DEFAULT_KEY_SIZE = 128;/*** 自动生成密钥** @return* @explain*/public static String generateKey() throws Exception {return new String(Hex.encode(generateKey(DEFAULT_KEY_SIZE)));}/*** @param keySize* @return* @throws Exception* @explain*/public static byte[] generateKey(int keySize) throws Exception {KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);kg.init(keySize, new SecureRandom());return kg.generateKey().getEncoded();}/*** 生成ECB暗号** @param algorithmName 算法名称* @param mode          模式* @param key* @return* @throws Exception* @explain ECB模式(电子密码本模式:Electronic codebook)*/private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);cipher.init(mode, sm4Key);return cipher;}/*** sm4加密* @param hexKey   16进制密钥(忽略大小写),也可自定义,注意如果不需要转化16进制,自行修改代码。*                 byte[] keyData = ByteUtils.fromHexString(hexKey);*                 改为*                 byte[] srcData = hexKey.getBytes(ENCODING);*                 验证方法为同样的道理* @param paramStr 待加密字符串* @return 返回16进制的加密字符串* @explain 加密模式:ECB* 密文长度不固定,会随着被加密字符串长度的变化而变化*/public static String encryptEcb(String hexKey, String paramStr) {try {String cipherText = "";// 16进制字符串-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// String-->byte[]byte[] srcData = paramStr.getBytes(ENCODING);// 加密后的数组byte[] cipherArray = encryptEcbPadding(keyData, srcData);// byte[]-->hexStringcipherText = ByteUtils.toHexString(cipherArray);return cipherText;} catch (Exception e) {return paramStr;}}/*** 加密模式之Ecb** @param key* @param data* @return* @throws Exception* @explain*/public static byte[] encryptEcbPadding(byte[] key, byte[] data) throws Exception {Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/*** sm4解密** @param hexKey     16进制密钥* @param cipherText 16进制的加密字符串(忽略大小写)* @return 解密后的字符串* @throws Exception* @explain 解密模式:采用ECB*/public static String decryptEcb(String hexKey, String cipherText) {// 用于接收解密后的字符串String decryptStr = "";// hexString-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// hexString-->byte[]byte[] cipherData = ByteUtils.fromHexString(cipherText);// 解密byte[] srcData = new byte[0];try {srcData = decryptEcbPadding(keyData, cipherData);// byte[]-->StringdecryptStr = new String(srcData, ENCODING);} catch (Exception e) {e.printStackTrace();}return decryptStr;}/*** 解密** @param key* @param cipherText* @return* @throws Exception* @explain*/public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) throws Exception {Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}/*** 校验加密前后的字符串是否为同一数据** @param hexKey     16进制密钥(忽略大小写)* @param cipherText 16进制加密后的字符串* @param paramStr   加密前的字符串* @return 是否为同一数据* @throws Exception* @explain*/public static boolean verifyEcb(String hexKey, String cipherText, String paramStr) throws Exception {// 用于接收校验结果boolean flag = false;// hexString-->byte[]byte[] keyData = ByteUtils.fromHexString(hexKey);// 将16进制字符串转换成数组byte[] cipherData = ByteUtils.fromHexString(cipherText);// 解密byte[] decryptData = decryptEcbPadding(keyData, cipherData);// 将原字符串转换成byte[]byte[] srcData = paramStr.getBytes(ENCODING);// 判断2个数组是否一致flag = Arrays.equals(decryptData, srcData);return flag;}public static void main(String[] args) {try {String paramStr = "Hello, world";System.out.println("==========加密前源数据==========");System.out.println(paramStr);// 生成32位16进制密钥String key = generateKey();System.out.println("==========生成key==========");System.out.println(key);String cipher = encryptEcb(key, paramStr);System.out.println("==========加密串==========");System.out.println(cipher);System.out.println("==========是否为同一数据==========");System.out.println(verifyEcb(key, cipher, paramStr));paramStr = decryptEcb(key, cipher);System.out.println("==========解密后数据==========");System.out.println(paramStr);} catch (Exception e) {e.printStackTrace();}}
}

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

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

相关文章

[论文笔记]Mixtral of Experts

引言 今天带来大名鼎鼎的Mixtral of Experts的论文笔记&#xff0c;即Mixtral-8x7B。 作者提出了Mixtral 8x7B&#xff0c;一种稀疏专家混合(Sparse Mixture of Experts&#xff0c;SMoE)语言模型。Mixtral与Mistral 7B具有相同的架构&#xff0c;不同之处在于每个层由8个前馈…

SpringCache 缓存 - @Cacheable、@CacheEvict、@CachePut、@Caching、CacheConfig 以及优劣分析

目录 SpringCache 缓存 环境配置 1&#xff09;依赖如下 2&#xff09;配置文件 3&#xff09;设置缓存的 value 序列化为 JSON 格式 4&#xff09;EnableCaching 实战开发 Cacheable CacheEvict CachePut Caching CacheConfig SpringCache 的优势和劣势 读操作…

Flask 实现增改及分页查询的完整 Demo

Flask 实现增改及分页查询的完整 Demo 简介 本文将通过一个 Flask Demo 来展示如何使用 Flask 框架实现 RESTful API&#xff0c;包括增加、修改用户信息以及分页查询功能。我们将使用 Flask 的扩展 SQLAlchemy 来处理数据库操作。 环境准备 首先&#xff0c;确保你已安装 …

【Android面试题】请你分别采用递归和非递归对二叉树进行遍历?

请你分别采用递归和非递归对二叉树进行遍历? 这道题想考察什么? 1、二叉树的基本原理和遍历的方法? 考察的知识点 二叉树遍历的基本概念、二叉树的基本原理 考生如何回答 二叉树的基本概念 当然可以! 二叉树是一种常见的数据结构,它由一组称为节点的元素构成。每个…

地平线x3派开启core文件存储奔溃日志

开发环境 ubuntu22 ros humble c11 程序奔溃后core文件存储设置 1. 确保系统允许生成core文件 首先&#xff0c;检查和设置系统的core文件生成限制&#xff1a; 检查当前core文件大小限制 使用以下命令检查当前core文件大小限制&#xff1a; ulimit -c如果输出为 0&am…

reduce过滤递归符合条件的数据

图片展示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><…

Python 实现乘数加密法

乘数加密是简单代替密码的一种。乘数加密法脱胎于凯撒加密法,加密和解密符号设计把他们转换成数字,加上或者减去密钥,然后把新的数字转换回符号,当我们把加减密钥变成乘以密钥,就是乘法加密法。有关凯撒加密法可以看之前的文章《Python实现凯撒加解密》。 加密过程 乘数加…

力扣hot100:25. K 个一组翻转链表

LeetCode&#xff1a;25. K 个一组翻转链表 这个题很像24. 两两交换链表中的节点 和 206. 反转链表 的合并体。 在力扣hot100&#xff1a;24. 两两交换链表中的节点中我们使用递归来实现这个问题是很方便的&#xff0c;使用迭代在k个结点一组时就不太好使了&#xff0c;我们可…

【攻击绕过】IP速率限制绕过

【攻击绕过】IP速率限制绕过 1.探测对应功能的API接口2.在代码或参数中插入空白字符3.通过标头操纵IP来源4.修改其他标头5.利用代理网络6.利用 API 网关行为 1.探测对应功能的API接口 应尝试对目标功能的API接口执行暴力攻击&#xff0c;例如/api/v3/sign-up&#xff0c;包括/…

鸿蒙轻内核M核源码分析系列六 任务及任务调度(3)任务调度模块

调度&#xff0c;Schedule也称为Dispatch&#xff0c;是操作系统的一个重要模块&#xff0c;它负责选择系统要处理的下一个任务。调度模块需要协调处于就绪状态的任务对资源的竞争&#xff0c;按优先级策略从就绪队列中获取高优先级的任务&#xff0c;给予资源使用权。本文我们…

nc翻译公式注意事项

nc翻译公式注意事项 翻译3个及以上条件&#xff08;里面加引号的是表名和表中字段&#xff0c;没加引号的是VO中的字段&#xff0c;没加引号的不能是getcolvalue后的字段&#xff09; "pzh->getColValueMore(\"voucherref_view\",\"pk_voucher\"…

关于map并发读写问题的解决方案考虑小计

叠甲&#xff1a;未详细看底层实现&#xff0c;只是大概看了一下涉及的api的源码&#xff0c;理解错的地方勿喷 问题背景 公司业务中用到了一个map&#xff0c;作用是存储需要屏蔽的数据&#xff0c;请求打过来后会去其中匹配 若命中则直接退出 该map的使用有以下几个特点&am…

ffmpeg视频编码原理和实战-(4)H264原始码流分析

H.264是一种广泛使用的视频编码标准&#xff0c;它采用一种分层结构&#xff0c;其中最重要的一个层是NAL&#xff08;网络抽象层&#xff09;。在H.264编码中&#xff0c;原始码流&#xff08;bitstream&#xff09;是由多个NALU&#xff08;NAL Units&#xff09;组成的。了解…

欧洲历史的五个阶段

欧洲的历史基本上都是分裂的&#xff0c;大致可以分为五个时期&#xff0c;分别为古希腊时代、罗马帝国时代、中世纪时代&#xff0c;文艺复兴时代、工业革命时代。 一&#xff0c;古希腊时代 古希腊是西方文明的源头&#xff0c;也是最重要和最直接的文明起源&#xff0c;首…

Python编程学习第一篇——Python零基础快速入门(五)—字典

上期我们学习了List结构&#xff0c;今天大家一起来学习字典。Python中的字典是一种无序的数据类型&#xff0c;用于存储键值对(key-value)。它是一种可变的数据结构&#xff0c;可以在其中添加、删除和修改元素。字典中的键必须是唯一的&#xff0c;而值可以重复。 下面我们以…

前端想学习后端需要下载那些东西

前端想学习后端需要下载那些东西 需要下载的软件如下&#xff1a; 1、JDK的下载2、Tomcat的下载 3、MySQL的下载4、Navicat的下载 5、Maven的下载6、IDEA的下载下载教程&#xff1a;点击→此处 进入

【学习笔记】java SPI机制

目录 实现&#xff1a;示例&#xff1a;注意事项&#xff1a; Java SPI (Service Provider Interface) 是 Java 提供的一套用来发现和加载第三方服务的机制。SPI 的主要目的是为了解耦框架与插件&#xff08;服务提供商&#xff09;之间的依赖关系&#xff0c;使得框架能够灵活…

nexus搭建npm前端项目的私服

一、为什么要搭建私库 节省外网带宽加速maven构建部署第三方构件&#xff08;特别是无法从公共仓库下载的构件&#xff09;提高稳定性&#xff08;内网部署&#xff0c;更少地依赖外网&#xff09;降低中央仓库的负荷 构件&#xff0c;好比我们的藏书&#xff0c;去书店或商城…

深度学习——TensorBoard的使用

官方文档torch.utils.tensorboard — PyTorch 2.3 documentation TensorBoard简介 TensorBoard是一个可视化工具&#xff0c;它可以用来展示网络图、张量的指标变化、张量的分布情况等。特别是在训练网络的时候&#xff0c;我们可以设置不同的参数&#xff08;比如&#xff1…