由于在各个地方都有用到加密的工具类,这是我在以往用到的加密工具类进行了一个集合。
- SM2的非对称加解密工具类
SM2的maven依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
java代码:
package com.chj.util;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.ShortenedDigest;
import org.bouncycastle.crypto.generators.KDF1BytesGenerator;
import org.bouncycastle.crypto.params.ISO18033KDFParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;
/**
* @Author Jun
* @Date 2018/9/6 15:45
* @Description SM2的非对称加解密工具类,椭圆曲线方程为:y^2=x^3+ax+b 使用Fp-256
*/
public class SM2Util {
/**
* 素数p
*/
private static final BigInteger p = new BigInteger("FFFFFFFE" + "FFFFFFFF"
+ "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF"
+ "FFFFFFFF", 16);
/**
* 系数a
*/
private static final BigInteger a = new BigInteger("FFFFFFFE" + "FFFFFFFF"
+ "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF"
+ "FFFFFFFC", 16);
/**
* 系数b
*/
private static final BigInteger b = new BigInteger("28E9FA9E" + "9D9F5E34"
+ "4D5A9E4B" + "CF6509A7" + "F39789F5" + "15AB8F92" + "DDBCBD41"
+ "4D940E93", 16);
/**
* 坐标x
*/
private static final BigInteger xg = new BigInteger("32C4AE2C" + "1F198119"
+ "5F990446" + "6A39C994" + "8FE30BBF" + "F2660BE1" + "715A4589"
+ "334C74C7", 16);
/**
* 坐标y
*/
private static final BigInteger yg = new BigInteger("BC3736A2" + "F4F6779C"
+ "59BDCEE3" + "6B692153" + "D0A9877C" + "C62A4740" + "02DF32E5"
+ "2139F0A0", 16);
/**
* 基点G, G=(xg,yg),其介记为n
*/
private static final BigInteger n = new BigInteger("FFFFFFFE" + "FFFFFFFF"
+ "FFFFFFFF" + "FFFFFFFF" + "7203DF6B" + "21C6052B" + "53BBF409"
+ "39D54123", 16);
private static SecureRandom random = new SecureRandom();
private ECCurve.Fp curve;
private ECPoint G;
public static String printHexString(byte[] b) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
builder.append('0' + hex);
hex = '0' + hex;
}
System.out.print(hex.toUpperCase());
builder.append(hex);
}
System.out.println();
return builder.toString();
}
public BigInteger random(BigInteger max) {
BigInteger r = new BigInteger(256, random);
while (r.compareTo(max) >= 0) {
r = new BigInteger(128, random);
}
return r;
}
private boolean allZero(byte[] buffer) {
for (int i = 0; i < buffer.length; i++) {
if (buffer[i] != 0)
return false;
}
return true;
}
/**
* 加密
*
* @param input 待加密消息M
* @param publicKey 公钥
* @return byte[] 加密后的字节数组
*/
public byte[] encrypt(String input, ECPoint publicKey) {
System.out.println("publicKey is: " + publicKey);
byte[] inputBuffer = input.getBytes();
printHexString(inputBuffer);
/* 1 产生随机数k,k属于[1, n-1] */
BigInteger k = random(n);
System.out.print("k: ");
printHexString(k.toByteArray());
/* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */
ECPoint C1 = G.multiply(k);
byte[] C1Buffer = C1.getEncoded(false);
System.out.print("C1: ");
printHexString(C1Buffer);
// 3 计算椭圆曲线点 S = [h]Pb * curve没有指定余因子,h为空
// BigInteger h = curve.getCofactor(); System.out.print("h: ");
// printHexString(h.toByteArray()); if (publicKey != null) { ECPoint
// result = publicKey.multiply(h); if (!result.isInfinity()) {
// System.out.println("pass"); } else {
// System.err.println("计算椭圆曲线点 S = [h]Pb失败"); return null; } }
/* 4 计算 [k]PB = (x2, y2) */
ECPoint kpb = publicKey.multiply(k).normalize();
/* 5 计算 t = KDF(x2||y2, klen) */
byte[] kpbBytes = kpb.getEncoded(false);
DerivationFunction kdf = new KDF1BytesGenerator(new ShortenedDigest(
new SHA256Digest(), 20));
byte[] t = new byte[inputBuffer.length];
kdf.init(new ISO18033KDFParameters(kpbBytes));
kdf.generateBytes(t, 0, t.length);