1. pom依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.66</version>
</dependency>
2. SM3封装
package com.yl.encrypt.sm;
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;
public class SM3Util {
public static String encryptHexString(String paramStr) {
byte[] resultHash = hash(paramStr.getBytes());
return ByteUtils.toHexString(resultHash);
}
private static byte[] hash(byte[] srcData) {
SM3Digest digest = new SM3Digest();
digest.update(srcData, 0, srcData.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
return hash;
}
public static byte[] hashByKey(byte[] keyBytes, byte[] srcData) {
KeyParameter keyParameter = new KeyParameter(keyBytes);
SM3Digest digest = new SM3Digest();
HMac mac = new HMac(digest);
mac.init(keyParameter);
mac.update(srcData, 0, srcData.length);
byte[] result = new byte[mac.getMacSize()];
mac.doFinal(result, 0);
return result;
}
public static void main(String[] args) {
String encrypt = encryptHexString("都开始考虑时空裂缝看了看");
System.out.println(encrypt);
byte[] SM4_KEY_IV = { 1, 3, 5, 7, 9, 11 };
byte[] hashByKey = hashByKey(SM4_KEY_IV, "I Love You Every Day".getBytes());
String hexString = ByteUtils.toHexString(hashByKey);
System.out.println(hexString);
}
}
3. SM4封装
package com.yl.encrypt.sm;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
public class SM4Util {
private static synchronized BouncyCastleProvider getProviderInstance() {
BouncyCastleProvider provider = null;
if(provider == null){
provider = new BouncyCastleProvider();
}
return provider;
}
public static final int SM4_KEY_SIZE = 128;
public static final int SM4_KEY_LENGTH = 16;
public static final String ALGORITHM_NAME = "SM4";
public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
public static final byte[] SM4_KEY_IV = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 };
public static byte[] createSm4Key() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_NAME, getProviderInstance());
keyGenerator.init(SM4_KEY_SIZE, new SecureRandom());
return keyGenerator.generateKey().getEncoded();
}
public static byte[] generateSm4Cipher(String algorithmName, int mode, byte[] plainBytes, byte[] sm4KeyBytes) throws Exception {
Cipher cipher = Cipher.getInstance(algorithmName, getProviderInstance());
Key secretKey = new SecretKeySpec(sm4KeyBytes, ALGORITHM_NAME);
if(algorithmName.contains("ECB")) {
cipher.init(mode, secretKey);
}else {
IvParameterSpec ivParameterSpec = new IvParameterSpec(SM4_KEY_IV);
cipher.init(mode, secretKey, ivParameterSpec);
}
return cipher.doFinal(plainBytes);
}
public static void main(String[] args) throws Exception {
byte[] plainText = "I Love You Every Day".getBytes();
byte[] sm4Key = Hex.decode("64EC7C763AB7BF64E2D75FF83A319918");
byte[] cipherText = generateSm4Cipher(ALGORITHM_NAME_ECB_PADDING, 1, plainText, sm4Key);
System.out.println(Hex.toHexString(cipherText));
byte[] decryptText = generateSm4Cipher(ALGORITHM_NAME_ECB_PADDING, 2, cipherText, sm4Key);
System.out.println(new String(decryptText));
byte[] cipherText2 = generateSm4Cipher(ALGORITHM_NAME_CBC_PADDING, 1, plainText, sm4Key);
System.out.println(Hex.toHexString(cipherText2));
byte[] decryptText2 = generateSm4Cipher(ALGORITHM_NAME_CBC_PADDING, 2, cipherText2, sm4Key);
System.out.println(new String(decryptText2));
}
}
4. SM2封装
package com.cmbchina.encrypt.sm;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class SM2Util {
private static final String USER_ID = "1234567812345678";
public static synchronized ECDomainParameters getECDomainParameters() {
ECDomainParameters domainParameters = null;
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
if (domainParameters == null) {
domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
}
return domainParameters;
}
public static Map<String, String> createKeyPair() {
Map<String, String> map = new HashMap<String, String>();
try {
ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
keyPairGenerator.init(new ECKeyGenerationParameters(getECDomainParameters(), SecureRandom.getInstance("SHA1PRNG")));
AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
map.put("privateKey", ByteUtils.toHexString(privatekey.toByteArray()));
map.put("publicKey", ByteUtils.toHexString(ecPoint.getEncoded(false)));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return map;
}
public static String encrypt(byte[] msg, String publicKey, int modeType) throws IOException {
SM2Engine.Mode mode;
if (modeType == 1) {
mode = SM2Engine.Mode.C1C3C2;
} else {
mode = SM2Engine.Mode.C1C2C3;
}
ECDomainParameters domainParameters = getECDomainParameters();
ECPoint pukPoint = domainParameters.getCurve().decodePoint(ByteUtils.fromHexString(publicKey));
ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
SM2Engine sm2Engine = new SM2Engine(mode);
sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
byte[] arrayOfBytes = null;
try {
arrayOfBytes = sm2Engine.processBlock(msg, 0, msg.length);
} catch (Exception e) {
log.error("SM2加密时出现异常:", e);
}
return ByteUtils.toHexString(arrayOfBytes);
}
public static String decrypt(byte[] cipherDataByte, String privateKeyHex, int modeType) throws InvalidCipherTextException {
SM2Engine.Mode mode;
if (modeType == 1) {
mode = SM2Engine.Mode.C1C3C2;
} else {
mode = SM2Engine.Mode.C1C2C3;
}
BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);
ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, getECDomainParameters());
SM2Engine sm2Engine = new SM2Engine(mode);
sm2Engine.init(false, privateKeyParameters);
try {
byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
return new String(arrayOfBytes, "utf-8");
} catch (Exception e) {
log.error("SM2解密时出现异常:", e);
}
return null;
}
private static synchronized BouncyCastleProvider getProviderInstance() {
BouncyCastleProvider provider = null;
if(provider == null){
provider = new BouncyCastleProvider();
}
return provider;
}
public static void main(String[] args) throws Exception {
String privateKeyHex = "6ab376dea8a49f57b98639fff3d80bf380014b38403224c4b62b752f3aaf74fa";
String publicKey = "045c3a43e62d68bdff904bb6ce62b8acf50ca9ed6a80af22f9a78a6f2b6a4e0c57774d8eb9a05af7d3494afb0ff698c3f87000ae824c482402754d531222eadff1";
String text = "微微儿";
String encrypt = encrypt(text.getBytes(), publicKey, 1);
System.out.println(encrypt);
String decrypt = decrypt(Hex.decode(encrypt), privateKeyHex, 1);
System.out.println(decrypt);
}
}
5. vue版本实现
https://gitee.com/bestman_456/sm2_sm3_sm4.git, vue版本和java版本,前后端完美匹配