SM2加解密 + MD5验签
1.SM2加密
概念:
SM2(国密椭圆曲线密码算法)是由中国国家密码管理局制定的椭圆曲线公钥密码算法标准。它包含了数字签名、加密、密钥协商等多个功能。以下是SM2加解密的基本介绍:
SM2加密(公钥加密):
-
生成密钥对: 首先,需要生成一对公私钥对。这对密钥是基于椭圆曲线的数学问题生成的,分别用于加密和解密。
-
加密数据: 加密方使用接收方的公钥对数据进行加密。具体步骤如下:
- 随机生成对称密钥(比如AES密钥),用于对称加密数据。
- 使用接收方的公钥对对称密钥进行非对称加密。
- 使用对称密钥对原始数据进行对称加密。
-
发送密文: 发送方将加密后的对称密钥和加密后的数据一起发送给接收方。
SM2解密(私钥解密):
-
获取密文: 接收方收到密文后,使用自己的私钥对对称密钥进行解密,得到原始的对称密钥。
-
解密数据: 使用解密得到的对称密钥对密文进行对称解密,得到原始的数据。
SM2的特点:
-
安全性: SM2基于椭圆曲线离散对数问题,具有较高的安全性,能够抵抗传统的公钥密码体制中的大多数攻击。
-
效率: 相比RSA,SM2在相同安全性水平下使用较短的密钥长度,加密解密效率更高。
-
国密标准: SM2是中国国家密码管理局发布的密码算法标准,广泛应用于中国的各种信息安全领域,包括数字证书、电子身份证等。
特点: 公钥加密,私钥解密。此时公司不会将公钥私钥进行传输,而是将其存储在本地配置文件中,只需传输加密数据即可。
//数据加密
//入参: 字节数组 公钥 + 数据
//返参: 字符串
public static String encrypt(byte[] publicKey, byte[] data) throws IOException {
if (publicKey == null || publicKey.length == 0) {
return null;
}
if (data == null || data.length == 0) {
return null;
}
byte[] source = new byte[data.length];
System.arraycopy(data, 0, source, 0, data.length);
Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance();
ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
ECPoint c1 = cipher.Init_enc(sm2, userKey);
cipher.Encrypt(source);
byte[] c3 = new byte[32];
cipher.Dofinal(c3);
return new StringBuffer(Util.byteToHex(c1.getEncoded())).append(Util.byteToHex(c3)).append(Util.byteToHex(source)).toString();
}
// 数据解密1
//入参:私钥 + 字符串加密数据 返参:字符串
public static String decrypt(String privateKey, String encryptedData) throws IOException {
return decrypt(privateKey, encryptedData, "UTF-8");
}
//数据解密2
//入参:私钥 + 字符串加密数据 + 编码设置 返参:字符串
public static String decrypt(String privateKey, String encryptedData, String character) throws IOException {
if (privateKey == null || privateKey.equals("")) {
return null;
}
if (encryptedData == null || encryptedData.equals("")) {
return null;
}
byte[] data = Util.hexToByte(encryptedData);
byte[] privateK = Util.hexToByte(privateKey);
// 加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
byte[] c1Bytes = Util.hexToByte(encryptedData.substring(0, 130));
int c2Len = data.length - 97;
byte[] c3 = Util.hexToByte(encryptedData.substring(130, 130 + 64));
byte[] c2 = Util.hexToByte(encryptedData.substring(194, 194 + 2 * c2Len));
SM2 sm2 = SM2.Instance();
BigInteger userD = new BigInteger(1, privateK);
// 通过C1实体字节来生成ECPoint
ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.Init_dec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);
// 返回解密结果
return new String(c2,character);
}
2.MD5验签
概念:
MD5 验签是一种基于 MD5(Message Digest Algorithm 5)哈希算法的数据验证方法,用于验证数据的完整性和真实性。通常,MD5 验签是在数字签名和摘要的场景下应用的一种技术。
MD5 验签的步骤:
- 数据签名: 发送方使用私钥对原始数据进行数字签名,生成数字签名值。
- 数据传输: 发送方将
原始数据和数字签名值一起传输给接收方。 - 数据验签: 接收方使用相同的哈希算法,对接收到的原始数据进行哈希运算,生成一个散列值。然后,接收方使用发送方数字签名值进行验证。
- 比对散列值: 接收方比对计算得到的散列值和数字签名值是否匹配。如果匹配,说明数据未被篡改,验证通过。
举例:
//1.转换为字节数组
byte[] md5 = json.toString().getBytes();
//2.字节数组转换为其十六进制表示的散列值
String Contentmd5 = DigestUtils.md5DigestAsHex(md5);
//3.将header中的散列值与计算的散列值比较
Contentmd5.equals(headers)