签名¶
假定待签名数据头为:
"request_id": "2XiTgZ2oVrBgGqKQ1ruCKh",
"access_key": "2y7cg8kmoGDrDBXJLaizoD",
"nonce": 1464594744
签名过程用Java代码描述如下:
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.util.Base64;
public class SignatureUtil {
//签名
public static String sign(byte[] data, String privateKey) {
SM2 sm2 = new SM2(privateKey,null);
sm2.setMode(SM2Engine.Mode.C1C2C3);
sm2.usePlainEncoding();
//签名使用Base64编码后得到的值即为请求头中signature字段的值
return Base64.getEncoder().encodeToString(sm2.sign(data));
}
//验签
public static boolean verify(byte[] data, String publicKey, String sign) {
SM2 sm2 = new SM2(null, publicKey);
sm2.setMode(SM2Engine.Mode.C1C2C3);
sm2.usePlainEncoding();
return sm2.verify(data,Base64.getDecoder().decode(sign));
}
//测试用例
public static void main(String[] args) {
KeyPair keyPair = SecureUtil.generateKeyPair("SM2");
String publicKey = HexUtil.encodeHexStr(((BCECPublicKey)keyPair.getPublic()).getQ().getEncoded(false));
//RSA私钥文件路径
String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(keyPair.getPrivate()));
System.out.println(publicKey);
System.out.println(privateKey);
long requestId = IdUtil.getSnowflakeNextId();//2XiTgZ2oVrBgGqKQ1ruCKh
String accessKey = "2y7cg8kmoGDrDBXJLaizoD";
long nonce = System.currentTimeMillis()/1000;//1464594744
String data = requestId + accessKey + nonce;
//签名
String sign = sign(data.getBytes(StandardCharsets.UTF_8),privateKey);
System.out.println(sign);
//验签
boolean verify = verify(data.getBytes(StandardCharsets.UTF_8),publicKey,sign);
System.out.println(verify);
}
}
Note
签名所用的方法是SM2,签名数据字符串转换成bytes时要用UTF-8编码格式