赞
踩
加密和解密使用相同的秘钥,常见算法有DES、TDES、AES、SM4、RC2/4
加密和解密使用不同的秘钥,公钥加密私钥解密,私钥加密公钥解密。常见算法有RSA、SM2、ECC
类似于hash,不可逆。常见的信息摘要算法有:MD2/4/5、SHA1/SHA224/SHA256/SHA384、SM3算法、MAC算法等
【数字签名】主要解决了两个核心问题:发送的消息是完整的,未被篡改的;接收的消息一定就是对应发送者发送的,别人无法仿制。前者体现的是数据的完整性,后者体现的是数据的不可抵赖性
数字签名的应用公式如下所示,其中M表示消息原文,S表示数字签名,P表示非对称算法的私钥运算,D表示信息摘要算法的运算。
P(D(M [with any length])) = S [with fixed length]
具体来说,发送方产生一个数据签名,需要经过以下几个步骤:
经过以上的步骤后,发送方就成功将信息原文和对应的数字签名,传递给了接收方;剩余的事,就是接收方对数据的验签操作。
接收方收到发送方发送的数据报文(信息原文+数字签名)后,需要经历以下步骤来完成对报文消息的验签操作:
首先,对数据报文进行分解,提取出信息原文部分和数字签名部分;
与产生数字签名流程一样,使用相同的信息摘要算法对信息原文做摘要运算,得出消息原文的摘要D1;
与产生数字签名流程相反,使用【非对称加密算法】中签名私钥对应的公钥对数字签名部分做解密 运算,解密后得到原始发送方发送的经填充后的摘要D2;
与产生数字签名流程相反,使用相同的数据填充标准对摘要D2做去填充操作,得到原始消息的附带的摘要D3;
比较D3和D1;如果两者相等,则表示对数字签名的验签是OK的,消息原文的数据是可信任的;反之,若D3不等于D1,则可以认为消息原文是不可信任的,数字签名中的【完整性】和【不可抵赖性】可能遭到了破坏;我们应该摒弃信息原文。
数字签名算法,就是使用RSA、MD5、SM2、SHA、SM3等非对称算法和信息摘要算法进行混搭组合。数字签名算法的基本表示格式为:xxxWithYYYEncryption,其中xxx表示信息摘要算法,yyy表示非对称加密算法。常见有的以下几种:
private static SecretKey generateKey() throws NoSuchAlgorithmException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128); // 秘钥长度为 128 位 SecretKey secretKey = keyGenerator.generateKey(); return secretKey; } /** * 二进制byte[]转十六进制string */ public static String byteToHexString(byte[] bytes){ StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { String strHex=Integer.toHexString(bytes[i]); if(strHex.length() > 3){ sb.append(strHex.substring(6)); } else { if(strHex.length() < 2){ sb.append("0" + strHex); } else { sb.append(strHex); } } } return sb.toString(); } public static void main(String[] args) { SecretKey secretKey = generateKey(); System.out.println(byteToHexString(secretKey.getEncoded())); // b30957dc3e032f462866c917ff461088 }
// 使用hutool工具类
String aesKey = "b30957dc3e032f462866c917ff461088";
AES aes = SecureUtil.aes(aesKey.getBytes());
// 加密 encrpy = 9OqWLbnVeW/EsL6nevQfZQ==
String encrypt = aes.encryptBase64("你好");
// 解密 decrypt = 你好
String decrypt = aes.decryptStr(encrypt);
public static void genKeyPair() { try { // 生成RSA密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); // 设置密钥长度 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 获取公钥和私钥 PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); java.util.Base64.Encoder encoder = java.util.Base64.getEncoder(); String publicKeyStr = encoder.encodeToString(publicKey.getEncoded()); String privateKeyStr = encoder.encodeToString(privateKey.getEncoded()); // 打印公钥和私钥 System.out.println("公钥: " + publicKeyStr); System.out.println("私钥: " + privateKeyStr); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpG4FQWx7NMG8DQF1VJNegLBxtsyGjvQGdoMDl0mXnZT7eU+DrJ0G5nKdKI+CWr+1tvSR/1dIblYsJK+M1cotSjUN9l4qraxnFha5Js1ldfxcTlJuWOBgWAWVJ+C3hZGkzAo8F+0CCtwij9dpLd+5kbHpdBd9Vh3V0WgiBY2M3nQIDAQAB
私钥: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKkbgVBbHs0wbwNAXVUk16AsHG2zIaO9AZ2gwOXSZedlPt5T4OsnQbmcp0oj4Jav7W29JH/V0huViwkr4zVyi1KNQ32XiqtrGcWFrkmzWV1/FxOUm5Y4GBYBZUn4LeFkaTMCjwX7QIK3CKP12kt37mRsel0F31WHdXRaCIFjYzedAgMBAAECgYBOwnOwtC+dSzB46DJP5G/Utpaq9OH2+6FUA7mzkBFL+xiTvackfk0bIH29hwYjyF4hXRUxwKkxla2CoQEaNHX0Q6MX8LxdbEGzHypLuaB+gNQSbWT41AVLB+GmikLc6yaNKAbr6/rdGWCIYVzzf4XuH8FI4d0Zr2HV7vBeBCeV9QJBANu9LkT7+8VRI8fq/XE9gsMPQSO5gBqBprPvag32wwiP3Hsv/9BYs7BbvQASijgqzuoC74YJioPi66kyWS8XFjcCQQDFA2hCQjYHd6rzkjWBL707+scl4ddfIccl1YBE2fyM2djXzZEVkgqW4NILIZC3nMEvGoBiympdelnq7n0LQzbLAkEAwCosaZW4M3HnCbFenQZ+8VjIzZYvCn8xqxAHvlh7bWRqG6z5WVoJIoTHv2V3TPFa7FlO4Pg9E2OCVgA68CyPdwJAK9OVNuApysF5OxP0aReonhYshSXXVmdaOPVkwmxHvUGc9mzZcJX7WxMKRsWhvubVJthbZR6oSME2DYgeMwoxvwJAaxrWhkBVde5L1/nFaN19Yb4w82/z+lmjd2itjLybhe62Z1HqS86pc4rZKOaoegBeHT0omcCBMnGxYnYlYlgWpg==
package com.echo.java8.encipher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Base64Utils; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Objects; /** * RSA签名,加解密处理核心文件,注意:密钥长度1024 */ public class RSAHelper { @SuppressWarnings("unused") private static Logger LOGGER = LoggerFactory.getLogger(RSAHelper.class); /* * 签名算法 */ public static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; /* * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /* * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; /* * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; public static void genKeyPair() { try { // 生成RSA密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); // 设置密钥长度 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 获取公钥和私钥 PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); java.util.Base64.Encoder encoder = java.util.Base64.getEncoder(); String publicKeyStr = encoder.encodeToString(publicKey.getEncoded()); String privateKeyStr = encoder.encodeToString(privateKey.getEncoded()); // 打印公钥和私钥 System.out.println("公钥: " + publicKeyStr); System.out.println("私钥: " + privateKeyStr); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * 签名字符串 * * @param text 需要签名的字符串 * @param privateKey 私钥(BASE64编码) * @param charset 编码格式 * @return 签名结果(BASE64编码) * @throws Exception */ public static String sign(String text, String privateKey, String charset) throws Exception { return sign(text, privateKey, charset, SIGNATURE_ALGORITHM); } public static String sign(String text, String privateKey, String charset, String signatureAlgorithm) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory; try { keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(signatureAlgorithm); signature.initSign(privateK); signature.update(getContentBytes(text, charset)); return Base64Utils.encodeToString(signature.sign()); } catch (Exception e) { throw new Exception("RSA sign exception:" + e.getMessage()); } } /** * 验签字符串 * * @param text 需要签名的字符串 * @param sign 客户签名结果 * @param publicKey 公钥(BASE64编码) * @param charset 编码格式 * @return 验签结果 * @throws Exception */ public static boolean verify(String text, String sign, String publicKey, String charset) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory; try { keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(getContentBytes(text, charset)); return signature.verify(Base64Utils.decodeFromString(sign)); } catch (Exception e) { LOGGER.warn("RSA verify exception", e); throw new Exception("RSA verify exception:" + e.getMessage()); } } /** * <P> * 私钥解密 * </p> * * @param encryptedData 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } public static String decryptByPublicKey(String encryptedData, String publicKey) throws Exception { byte[] bytes = decryptByPublicKey(Base64Utils.decodeFromString(encryptedData), publicKey); return new String(bytes); } /** * <p> * 公钥解密 * </p> * * @param encryptedData 已加密数据 * @param publicKey 公钥(BASE64编码) * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * <p> * 公钥加密 * </p> * * @param data 源数据 * @param publicKey 公钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPublicKey(byte[] data, String publicKey, String cipherArgs) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); // 对数据加密 Cipher cipher = null; if (Objects.isNull(cipherArgs)) { cipher = Cipher.getInstance(keyFactory.getAlgorithm()); } else { cipher = Cipher.getInstance(cipherArgs); } cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * <p> * 私钥加密 * </p> * * @param data 源数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decodeFromString(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** * @param content * @param charset * @return * @throws SignatureException * @throws UnsupportedEncodingException */ private static byte[] getContentBytes(String content, String charset) { if (charset == null || "".equals(charset)) { return content.getBytes(); } try { return content.getBytes(charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException("签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset); } } public static void main(String[] args) throws Exception { String text = "hello"; // rsaKeyGenerate("test"); String publicKeyStr = " MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLSTLXzr70geYHPD8uSLj8it7LvdZRz4hhYPHPQ6MvdJ9mLuooiXtXEwOgTWAIWtXXWL2EYoIo/AhaE3B91hpkIsXtdlotaMJSLv3vilZnd6nLISJXQiWJ7IKOShAByXJFGr8aT+blTQOwYUayKKXycXL1Sg1KINjJSiNKfZF+KwIDAQAB"; String privateKeyStr = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAItJMtfOvvSB5gc8Py5IuPyK3su91lHPiGFg8c9Doy90n2Yu6iiJe1cTA6BNYAha1ddYvYRigij8CFoTcH3WGmQixe12Wi1owlIu/e+KVmd3qcshIldCJYnsgo5KEAHJckUavxpP5uVNA7BhRrIopfJxcvVKDUog2MlKI0p9kX4rAgMBAAECgYB7YDxEAqMMq99Yu1nvooURVeUhracg0maocxneELiEeZYUCixp+dWh/HqyzLbqz6MpXDaLBELtEMpJF30GSdcXWh+/9kN7IeWnlTZxmpc4FxeQydCGOJdgLv+GsR0ulYp4vH8L5cEDy6TZ4C7AHRv8KZOzrwBkZSTL1UayzIDncQJBAM267L4Tz51G/pxXsxjzMfM1mzgr/SvsWlj5OpwECYm7s2kGVxrVtdsCMj2rSYbjrR0TCZe7cKIXRR0lARIxTikCQQCtUfnBqoFHny5twGD/HlvDYoalnxxCYJJg+mBdR5s5ElMzkpjuKRWrvxTeroY+vPpL+7RHSU0qNCpXTvqmDQwzAkAVU817Hv6k5Vk7x/OvIHcLKYF/3z+NsCDlnGCxD9IVTzoYJyochA8oNyASOJGUxEGMBA84hZv1kcf+b3me8zGRAkBrC89jAskYEEOfu4rs5rYsRcT9s/jDMlwWE23DDv/azuueVbOonK1qxvi/1DDLvPImTc55nNdQ8qkYBYqfVj2rAkAnHEKLtgxWXreWRAbujoMgLOR2AEUyG7Vbw+0s/JPSU04DGex3Wj6/+bJQdejAiXUTJSTJjE69aHKwPKBx3fBN"; byte[] bytes = encryptByPrivateKey(text.getBytes("UTF-8"), privateKeyStr); String s = Base64Utils.encodeToString(bytes); System.out.println("s:"+s); String sign = sign(s, privateKeyStr, "UTF-8"); System.out.println(sign); System.out.println(verify(s, sign, publicKeyStr, "UTF-8")); System.out.println(decryptByPublicKey(s, publicKeyStr)); } }
openssl生成RSA证书对,证书生成参考 密码:zsqq
// 将公钥文件转化为字符串 public static String parsePubStr( String publicFile) throws Exception { InputStream is = new FileInputStream(publicFile); CertificateFactory cf = CertificateFactory.getInstance("x509"); X509Certificate cerCert = (X509Certificate) cf.generateCertificate(is); // 生成PublicKey PublicKey publicKey = cerCert.getPublicKey(); BASE64Encoder base64Encoder = new BASE64Encoder(); String publicKeyString = base64Encoder.encode(publicKey.getEncoded()); return publicKeyString; } // 将私钥文件转化为字符串 public static String parsePriStr( String privateFile) throws Exception { InputStream is = new FileInputStream(privateFile); KeyStore tKeyStore = KeyStore.getInstance("PKCS12"); tKeyStore.load(is, "ht123456".toCharArray()); Enumeration e = tKeyStore.aliases(); String tAliases = null; while (e.hasMoreElements()) { tAliases = (String) e.nextElement(); break; } PrivateKey privateKey = (PrivateKey) tKeyStore.getKey(tAliases, "ht123456".toCharArray()); Base64.Encoder encoder = Base64.getEncoder(); String s = encoder.encodeToString(privateKey.getEncoded()); return s; }
加密、加签、验签、解密
package com.echo.java8.encipher; import cn.hutool.core.codec.Base64; import lombok.extern.slf4j.Slf4j; 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 org.bouncycastle.jce.spec.ECPrivateKeySpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.ECFieldFp; import java.security.spec.EllipticCurve; /** * @description: * @author: echo * @Date: 2023/10/10 11:02 * @Version: 1.0.0 */ @Slf4j public class SmUtils { // 添加 Bouncy Castle 提供者 static { Security.addProvider(new BouncyCastleProvider()); } /** * 以下为SM2推荐曲线参数 */ public static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); public static final BigInteger SM2_ECC_P = CURVE.getQ(); public static final BigInteger SM2_ECC_A = CURVE.getA().toBigInteger(); public static final BigInteger SM2_ECC_B = CURVE.getB().toBigInteger(); public static final BigInteger SM2_ECC_N = CURVE.getOrder(); public static final BigInteger SM2_ECC_H = CURVE.getCofactor(); public static final BigInteger SM2_ECC_GX = new BigInteger( "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); public static final BigInteger SM2_ECC_GY = new BigInteger( "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); public static final org.bouncycastle.math.ec.ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY); public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT, SM2_ECC_N, SM2_ECC_H); public static final EllipticCurve JDK_CURVE = new EllipticCurve(new ECFieldFp(SM2_ECC_P), SM2_ECC_A, SM2_ECC_B); public static final java.security.spec.ECPoint JDK_G_POINT = new java.security.spec.ECPoint( G_POINT.getAffineXCoord().toBigInteger(), G_POINT.getAffineYCoord().toBigInteger()); public static final java.security.spec.ECParameterSpec JDK_EC_SPEC = new java.security.spec.ECParameterSpec( JDK_CURVE, JDK_G_POINT, SM2_ECC_N, SM2_ECC_H.intValue()); public static final String SM3_SM2 = "SM3withSM2"; private static String encoding = "GBK"; private static final String BC = "BC"; /** * 字符串转PublicKey * @param publicString * @return */ public static BCECPublicKey stringToPublic(String publicString) { try { String publicKeyHex = ByteUtils.toHexString(Base64.decode(publicString.getBytes(StandardCharsets.UTF_8))); BouncyCastleProvider provider = new BouncyCastleProvider(); // 椭圆曲线参数规格 ECParameterSpec ecParameterSpec = new ECParameterSpec(CURVE, G_POINT, SM2_ECC_N, SM2_ECC_H); // 将私钥HEX字符串转换为X值 BigInteger bigInteger = new BigInteger(publicKeyHex, 16); // 将公钥HEX字符串转换为椭圆曲线对应的点 ECPoint ecPoint = CURVE.decodePoint(bigInteger.toByteArray()); // 获取椭圆曲线KEY生成器 KeyFactory keyFactory = KeyFactory.getInstance("EC", provider); // 将椭圆曲线点转为公钥KEY对象 return (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec)); } catch (Exception e) { log.error("", e); throw new RuntimeException("字符串转公钥失败"); } } /** * 字符串转PrivateKey * @param privateString * @return */ public static BCECPrivateKey stringToPrivate(String privateString) { try { String privateHex = ByteUtils.toHexString(Base64.decode(privateString.getBytes(StandardCharsets.UTF_8))); BouncyCastleProvider provider = new BouncyCastleProvider(); BigInteger bigInteger = new BigInteger(privateHex, 16); // 将X值转为私钥KEY对象 KeyFactory keyFactory = KeyFactory.getInstance("EC", provider); return (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, new ECParameterSpec(CURVE, G_POINT, SM2_ECC_N))); } catch (Exception e) { log.error("", e); throw new RuntimeException("字符串转私钥失败"); } } private static String encrypt(String data, String publicKeyString) { BCECPublicKey bcecPublicKey = stringToPublic(publicKeyString); ECPublicKeyParameters pubKeyParameters = convertPublicKeyToParameters(bcecPublicKey); SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2); ParametersWithRandom pwr = new ParametersWithRandom(pubKeyParameters, new SecureRandom()); engine.init(true, pwr); try { return Base64.encode(engine.processBlock(data.getBytes(), 0, data.getBytes().length)); } catch (Exception e) { log.error("", e); throw new RuntimeException("加密失败"); } } private static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) { ECParameterSpec parameterSpec = ecPubKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters); } private static String signSm3WithSm2(String privateKeyString, String data) { try { PrivateKey privateKey = stringToPrivate(privateKeyString); Signature signature = Signature.getInstance(SM3_SM2, BC); signature.initSign(privateKey); signature.update(data.getBytes(encoding)); byte signed[] = signature.sign(); byte sign_asc[] = new byte[signed.length * 2]; hex2Ascii(signed.length, signed, sign_asc); return new String(sign_asc); } catch (Exception e) { log.error("", e); throw new RuntimeException("加签失败"); } } public static boolean verifySign(String publicKeyString,String signedStr,String data) throws Exception{ BCECPublicKey bcecPublicKey = stringToPublic(publicKeyString); Signature signature = Signature.getInstance(SM3_SM2, BC); signature.initVerify(bcecPublicKey); byte signedData[] = new byte[signedStr.length() / 2]; ascii2Hex(signedStr.length(), signedStr.getBytes(encoding), signedData); signature.update(data.getBytes(encoding)); return signature.verify(signedData); } public static String decrypt(String encryptData, String privateString) { BCECPrivateKey privateKey = stringToPrivate(privateString); byte[] decode = Base64.decode(encryptData.getBytes()); ECPrivateKeyParameters priKeyParameters = convertPrivateKeyToParameters(privateKey); SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2); engine.init(false, priKeyParameters); try { return new String(engine.processBlock(decode, 0, decode.length)); } catch (Exception e) { log.error("", e); throw new RuntimeException("解密失败"); } } private static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) { ECParameterSpec parameterSpec = ecPriKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters); } /** * 将十六进制数据转换成ASCII字符串 * * @param len 十六进制数据长度 * @param data_in 待转换的十六进制数据 * @param data_out 已转换的ASCII字符串 */ private static void hex2Ascii(int len, byte data_in[], byte data_out[]) { byte temp1[] = new byte[1]; byte temp2[] = new byte[1]; for (int i = 0, j = 0; i < len; i++) { temp1[0] = data_in[i]; temp1[0] = (byte) (temp1[0] >>> 4); temp1[0] = (byte) (temp1[0] & 0x0f); temp2[0] = data_in[i]; temp2[0] = (byte) (temp2[0] & 0x0f); if (temp1[0] >= 0x00 && temp1[0] <= 0x09) { (data_out[j]) = (byte) (temp1[0] + '0'); } else if (temp1[0] >= 0x0a && temp1[0] <= 0x0f) { (data_out[j]) = (byte) (temp1[0] + 0x57); } if (temp2[0] >= 0x00 && temp2[0] <= 0x09) { (data_out[j + 1]) = (byte) (temp2[0] + '0'); } else if (temp2[0] >= 0x0a && temp2[0] <= 0x0f) { (data_out[j + 1]) = (byte) (temp2[0] + 0x57); } j += 2; } } /** * 将ASCII字符串转换成十六进制数据 * * @param len ASCII字符串长度 * @param data_in 待转换的ASCII字符串 * @param data_out 已转换的十六进制数据 */ private static void ascii2Hex(int len, byte data_in[], byte data_out[]) { byte[] temp1 = new byte[1]; byte[] temp2 = new byte[1]; for (int i = 0, j = 0; i < len; j++) { temp1[0] = data_in[i]; temp2[0] = data_in[i + 1]; if (temp1[0] >= '0' && temp1[0] <= '9') { temp1[0] -= '0'; temp1[0] = (byte) (temp1[0] << 4); temp1[0] = (byte) (temp1[0] & 0xf0); } else if (temp1[0] >= 'a' && temp1[0] <= 'f') { temp1[0] -= 0x57; temp1[0] = (byte) (temp1[0] << 4); temp1[0] = (byte) (temp1[0] & 0xf0); } if (temp2[0] >= '0' && temp2[0] <= '9') { temp2[0] -= '0'; temp2[0] = (byte) (temp2[0] & 0x0f); } else if (temp2[0] >= 'a' && temp2[0] <= 'f') { temp2[0] -= 0x57; temp2[0] = (byte) (temp2[0] & 0x0f); } data_out[j] = (byte) (temp1[0] | temp2[0]); i += 2; } } public static void main(String[] args) throws Exception { String publicKeyString = "BM6zmWApBExWzuVezdk3QwdE8PTzUBW/6JadWgAbq0XYNzcQcefZmknBZW0Cvo5GvMjDJeOUYYKuyzELNOCNfPQ="; String privateKeyString = "AKELqaUjpIrFu3S5xRhWZ1BIXnSosZQ+vKCjzQ47pJJT"; String dataStr = "张晓慧"; // 加密 String encrypt = encrypt(dataStr, publicKeyString); System.out.println("加密后数据:"+encrypt); String decrypt = decrypt(encrypt, privateKeyString); System.out.println("机密后数据:"+decrypt); // 加签 String sign = signSm3WithSm2(privateKeyString, encrypt); System.out.println("加密后数据加签:"+sign); // 验签 boolean verifySign = verifySign(publicKeyString, sign, encrypt); System.out.println("是否验签成功:"+verifySign); // 打印数据 // 加密后数据:BLmEbT49DDfVT5IHvRcP+4yTGfLSfSbSo1U0hgUuKLWKYS6zkpIvaAurNSNG9KrfqXZInZJDUqw6W2jN82nJwcPbzECtaBmkgvXjaPRq5pG/kjBqfonSEF+hU7CUuRq0RdB39aP1Srl82g== // 机密后数据:张晓慧 // 加密后数据加签:304502207c01cc3feef31f4a8b0ea1c5b9f45464e6ab6cd02dae6225f9d4c9ec0a4ddffc022100df39ee367d893d774f8529412698fd60c13bb1f5d97f85dbf62122a9a1d87f50 // 是否验签成功:true } }
参考文档:https://blog.csdn.net/rtthreadiotos/article/details/121033533
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。