一:SM2简介
SM2是中国密码学算法标准中的一种非对称加密算法
(包括公钥和私钥)。SM2主要用于数字签名
、密钥交换
和加密解密
等密码学。
- 生成秘钥:用于生成一对公钥和私钥。公钥:用于加密数据和验证数字签名。私钥:用于解密数据和生成数字签名。
- 数字签名:用于生成和验证数字签名,可以独立使用。数字签名可以确保数据的完整性和身份认证,防止数据被篡改或冒充。发送方可以使用自己的私钥生成数字签名,并将签名附加在数据上发送给接收方。接收方使用发送方的公钥来验证数字签名的有效性,从而确保数据的完整性和身份认证。
- 密钥交换:双方可以使用各自的私钥和对方的公钥来生成一个共享密钥,用于后续的对称加密通信。
- 加密解密:发送方使用接收方的公钥进行加密,接收方使用自己的私钥进行解密。
CFCA
二:Java
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>com.cfca</groupId>
<artifactId>SADK</artifactId>
<version>3.2.1.3</version>
</dependency>
public class SM2Util {
private static final String PVK_FILE = ".pvk";
private static final String PUB_FILE = ".puk";
/**
* 加密数据
* @param publicKey
* @param data
*/
public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {
byte[] result = null;
SM2Toolkit sm2Toolkit = new SM2Toolkit();
SM2PublicKey sm2PublicKey = (SM2PublicKey)publicKey;
result = sm2Toolkit.SM2EncryptData(sm2PublicKey, data);
return result;
}
public static byte[] decryptString(PrivateKey privateKey, String base64Text) throws Exception {
SM2Toolkit sm2Toolkit = new SM2Toolkit();
SM2PrivateKey sm2PrivateKey = (SM2PrivateKey)privateKey;
return sm2Toolkit.SM2DecryptData(sm2PrivateKey, BASE64Toolkit.decode(base64Text));
}
public static void sm4EncryptFile(String key, String inFile, String outFile) throws Exception{
SM4Toolkit toolkit = new SM4Toolkit();
toolkit.SM4Init(key.getBytes(), key.getBytes());
toolkit.SM4EncryptFile(inFile, outFile);
}
public static boolean sM4DecryptFile(String key, String inFile, String outFile) throws Exception {
SM4Toolkit toolkit = new SM4Toolkit();
toolkit.SM4Init(key.getBytes(), key.getBytes());
return toolkit.SM4DecryptFile(inFile, outFile);
}
/**
* 签名
* @param privateKey
*/
public static String singnString(PrivateKey privateKey, byte[] srcBytes) throws Exception {
SM2Toolkit sm2Toolkit = new SM2Toolkit();
SM2PrivateKey sm2PrivateKey = (SM2PrivateKey)privateKey;
String result = BASE64Toolkit.encode(sm2Toolkit.SM2Sign(sm2PrivateKey, srcBytes));
return result;
}
public static String sm2SignFile(String filePath, String privateKeyPath) throws Exception {
SM2Toolkit sm2Toolkit = new SM2Toolkit();
byte[] privateBytes = readKey(privateKeyPath);
SM2PrivateKey sm2PrivateKey = (SM2PrivateKey)sm2Toolkit.SM2BuildPrivateKey(BASE64Toolkit.encode(privateBytes));
byte[] hash = SM3Toolkit.SM3HashFile(sm2PrivateKey.getSM2PublicKey(), filePath);
String result = BASE64Toolkit.encode(BCSoftSM2.sign(hash, sm2PrivateKey.dBigInteger(), true));
return result;
}
/**
* 文件验签
* @param outfilePath
* @param keyPath
* @param singStr
* @return
*/
public static boolean verify(String outfilePath, String keyPath, String singStr) {
boolean result = false;
try {
SM2Toolkit toolkit = new SM2Toolkit();
SM2PublicKey sm2PublicKey = (SM2PublicKey)toolkit.SM2BuildPublicKey(BASE64Toolkit.encode(readKey(keyPath)));
byte[] hash = SM3Toolkit.SM3HashFile(sm2PublicKey, outfilePath);
result = toolkit.SM2VerifyHash(sm2PublicKey, hash, BASE64Toolkit.decode(singStr));
} catch (Exception e) {
throw new RuntimeException("文件验签失败");
}
return result;
}
/**
* 读取私钥
* @param keyPath
* @return
*/
public static SM2PrivateKey buildPrivateKey(String keyPath) throws Exception {
if (!keyPath.endsWith(PVK_FILE)) {
keyPath += PVK_FILE;
}
byte[] privateKeyByte = readKey(keyPath);
SM2Toolkit sm2Toolkit = new SM2Toolkit();
SM2PrivateKey sm2PrivateKey = (SM2PrivateKey)sm2Toolkit.SM2BuildPrivateKey(BASE64Toolkit.encode(privateKeyByte));
return sm2PrivateKey;
}
/**
* 读取公钥
* @param keyPath
* @return
*/
public static SM2PublicKey buildPublicKey(String keyPath) throws Exception {
if (!keyPath.endsWith(PUB_FILE)) {
keyPath += PUB_FILE;
}
byte[] privateKeyByte = readKey(keyPath);
SM2Toolkit sm2Toolkit = new SM2Toolkit();
SM2PublicKey sm2PublicKey = (SM2PublicKey)sm2Toolkit.SM2BuildPublicKey(BASE64Toolkit.encode(privateKeyByte));
return sm2PublicKey;
}
/**
* 读取秘钥
* @param filePath
*/
public static byte[] readKey(String filePath) throws Exception {
try(FileInputStream is = new FileInputStream(filePath)) {
byte[] out = new byte[is.available()];
byte[] buffer = new byte[1024];
int len;
for (int offset = 0; (len = is.read(buffer, 0, buffer.length)) != -1; offset += len) {
System.arraycopy(buffer, 0, out, offset, len);
}
return out;
}
}
public static void main(String[] args) throws Exception {
SM2Toolkit toolkit = new SM2Toolkit();
KeyPair keyPair = toolkit.SM2GenerateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 1. 对源文件进行签名(最终会作为签名文件和数据zip一起放到新的.zip中去)
String zipPath = "/Temp/data.zip";
String tempZipPath = "/Temp/Activiti/data.zip";
String signguare = sm2SignFile(zipPath, "xxx.pvk");
// 2. 对秘钥加密(最终将将加密的秘钥作为压缩包文件中的一部分)
String verifyChars = "1234567890abcdefghijkmnopqrstuvwxyz";
String encryptKey = RandomStringUtils.random(16, verifyChars).toUpperCase();
byte[] encrypt = encrypt(buildPublicKey("/Temp/xxx.puk"), random16.getBytes());
byte[] encryptKeyBytes = BASE64Toolkit.encode(encrypt).getBytes();
// 3. 加密源文件
sm4EncryptFile(encryptKey, zipPath, tempZipPath);
// 4. 新的zip = (sign文件、秘钥文件、加密源文件)
}
}