我想咨询下java实现国密p7软验签,使用sm3withsm2,只需要验签,需要从签名值里解析出证书验签,可用的内容只有原文和签名值
原文:123456
签名值:MIIDJgYKKoEcz1UGAQQCAqCCAxYwggMSAgEBMQwwCgYIKoEcz1UBgxEwDAYKKoEcz1UGAQQCAaCCAkowggJGMIIB7KADAgECAgV6kZ2zajAKBggqgRzPVQGDdTAvMQswCQYDVQQGEwJjbjEMMAoGA1UECgwDYm9jMRIwEAYDVQQDDAlnbXN1YmNhMDEwHhcNMjIwMzMwMDMxNjIxWhcNMjQxMjI0MDMxNjIxWjB4MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQk9DIFNNMiBPQ0EzMTERMA8GA1UECwwIUEJQU1RFU1QxGTAXBgNVBAsMEE9yZ2FuaXphdGlvbmFsLTIxIzAhBgNVBAMMGjA0N0Bib2N0ZXN0c20yQFAyMDIyMDMyOUAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEaPWq1BLLJnsQbKfYVWIX3odW8QU8SlOdPIFgmj5eotqGuF39HLtKL2BnDte6zK0KStGHGDG+dysHCUEofkebd6OBqzCBqDAfBgNVHSMEGDAWgBTwazjBPiVRhWlDe9+pNmz3Fw5YfDAJBgNVHRMEAjAAMEsGA1UdHwREMEIwQKA+oDykOjA4MQ0wCwYDVQQDDARjcmwxMQwwCgYDVQQLDANjcmwxDDAKBgNVBAoMA2JvYzELMAkGA1UEBhMCY24wDgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBS7dSbEbSg7Q+Jrjuy0mhxyCSujMjAKBggqgRzPVQGDdQNIADBFAiEArbvuZl8jb84DIVFwo4QnE9V8LtSid1lzQ0uZUA13SO0CICHqOC/6lld6I6++uhfwHFXZCVsYhaoJSayfErDitg+ZMYGiMIGfAgEBMDgwLzELMAkGA1UEBhMCY24xDDAKBgNVBAoMA2JvYzESMBAGA1UEAwwJZ21zdWJjYTAxAgV6kZ2zajAKBggqgRzPVQGDETALBgkqgRzPVQGCLQEERzBFAiEAgWjzgPEcWhSoRtzXQjfDdMNgDcGhBR3695N+mzl5hfsCIG8UtHZpaI4o5TQVyEJxsPkwLcDPdC7oftupvZqX4/6v
我本地根据这个博客 https://blog.csdn.net/pridas/article/details/86118774 测试是ok的,但是你的这个代码应该是BASE64了,然后你的userId我也不知道是哪个。
测试代码
import org.bouncycastle.util.encoders.Hex;
import java.security.KeyPair;
import java.security.PublicKey;
public class SM2P7Verify {
public static void main(String[] args) throws Exception {
String s = "123456";
byte[] userId = "1234567812345678".getBytes();
KeyPair keyPair = GmUtil.generateKeyPair();
PublicKey aPublic = keyPair.getPublic();
byte[] bytes = GmUtil.signSm3WithSm2(s.getBytes(), userId, keyPair.getPrivate());
System.out.println(Hex.toHexString(bytes));
boolean b = GmUtil.verifySm3WithSm2( s.getBytes(), userId, bytes, aPublic);
System.out.println(b);
}
}
测试结果
188dce4b8db74c8b2f940c759fc9ff747b11dc40d0d33be661e276b4567561d066fdf8697b4c4ee702ab44282751603779f370f0759ff388f6fb1003aafa6e2a
true
一般银行会提供验签的调用方法的,或者你可以看看这个,关于java 国密p7验签_基于BC实现的(JAVA版)SM2国密算法签名验签DEMO的资料,看是否对你有帮助:https://blog.csdn.net/weixin_36027743/article/details/115076193
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
java实现国密p7软验签,使用sm3withsm2的步骤如下:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream fis = new FileInputStream(certPath);
X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
byte[] signature = Base64.decodeBase64(signValue); // 签名值,需要解码
byte[] data = "123456".getBytes(); // 待验签原文
Provider provider = Security.getProvider("BC"); // 注意需要引用BC库
Signature signature = Signature.getInstance("SM3withSM2", provider);
signature.initVerify(cert.getPublicKey());
signature.update(data);
boolean verified = signature.verify(signature);
System.out.println("验签结果:" + verified);
完整的验签代码示例:
import java.io.FileInputStream;
import java.security.Provider;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.apache.commons.codec.binary.Base64;
public class SM3withSM2Test {
public static void main(String[] args) throws Exception {
// 1. 加载证书
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream fis = new FileInputStream(certPath);
X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
// 2. 获取签名值和待验签原文
byte[] signature = Base64.decodeBase64(signValue);
byte[] data = "123456".getBytes();
// 3. 建立算法实例
Provider provider = Security.getProvider("BC");
Signature signature = Signature.getInstance("SM3withSM2", provider);
// 4. 初始化验签器
signature.initVerify(cert.getPublicKey());
// 5. 传入待验签原文
signature.update(data);
// 6. 执行验签操作并输出结果
boolean verified = signature.verify(signature);
System.out.println("验签结果:" + verified);
}
}
如果我的回答解决了您的问题,请采纳!