Java BC包解析DER的SM2签名值转换成16进制字符串
以下是Java代码示例,用于解析DER编码的SM2签名值,并将其转换为十六进制字符串:
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
public class SM2Utils {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static byte[] sign(byte[] message, byte[] privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
// 使用SM3摘要算法计算消息的哈希值
byte[] digest = new byte[32];
SM3Digest sm3 = new SM3Digest();
sm3.update(message, 0, message.length);
sm3.doFinal(digest, 0);
// 解析私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
ECPrivateKeyParameters privateKeyParams = (ECPrivateKeyParameters) PrivateKeyFactory.createKey(pkcs8KeySpec);
// 创建SM2签名器
SM2Signer signer = new SM2Signer();
ECDomainParameters ecParams = privateKeyParams.getParameters();
ECParameterSpec ecSpec = new ECParameterSpec(ecParams.getCurve(), ecParams.getG(), ecParams.getN(), ecParams.getH(), ecParams.getSeed());
signer.init(true, privateKeyParams);
// 计算签名
signer.update(digest, 0, digest.length);
byte[] signature = signer.generateSignature();
// 将签名值编码为DER格式
ASN1Integer r = new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, 0, 32)));
ASN1Integer s = new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, 32, 64)));
ASN1Sequence seq = new DERSequence(new ASN1Integer[] { r, s });
byte[] derSignature = seq.getEncoded();
return derSignature;
}
public static boolean verify(byte[] message, byte[] publicKey, byte[] signature) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
// 使用SM3摘要算法计算消息的哈希值
byte[] digest = new byte[32];
SM3Digest sm3 = new SM3Digest();
sm3.update(message, 0, message.length);
sm3.doFinal(digest, 0);
// 解析公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
ECPublicKeyParameters publicKeyParams = (ECPublicKeyParameters) PublicKeyFactory.createKey(x509KeySpec);
// 创建SM2签名器
SM2Signer verifier = new SM2Signer();
ECDomainParameters ecParams = publicKeyParams.getParameters();
ECParameterSpec ecSpec = new ECParameterSpec(ecParams.getCurve(), ecParams.getG(), ecParams.getN(), ecParams.getH(), ecParams.getSeed());
verifier.init(false, publicKeyParams);
// 解码DER格式的签名值
ASN1Sequence seq = ASN1Sequence.getInstance(signature);
BigInteger r = ((ASN1Integer) seq.getObjectAt(0)).getValue();
BigInteger s = ((ASN1Integer) seq.getObjectAt(1)).getValue();
byte[] rs = new byte[64];
System.arraycopy(r.toByteArray(), r.toByteArray().length > 32 ? 1 : 0, rs, 0, 32);
System.arraycopy(s.toByteArray(), s.toByteArray().length > 32 ? 1 : 0, rs, 32, 32);
// 验证签名
verifier.update(digest, 0, digest.length);
return verifier.verifySignature(rs);
}
public static void main(String[] args) throws Exception {
// 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("sm2p256v1");
keyPairGenerator.initialize(ecGenSpec, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
byte[] privateKey = keyPair.getPrivate().getEncoded();
byte[] publicKey = keyPair.getPublic().getEncoded();
// 签名
byte[] message = "Hello, SM2!".getBytes();
byte[] signature = sign(message, privateKey);
// 输出签名值的十六进制字符串
String signatureHex = Hex.toHexString(signature);
System.out.println(signatureHex);
// 验证签名
boolean verified = verify(message, publicKey, signature);
System.out.println("Signature verified: " + verified);
}
}
``
原文地址: https://www.cveoy.top/t/topic/cJyF 著作权归作者所有。请勿转载和采集!