我正在开发一个应用程序,需要在secp256r1(NIST P-256,P-256,prime256v1)公钥的帮助下验证SHA256withECDSAsignatures.
公钥在某个较早的时间点由不同的应用程序生成,并以十六进制编码存储在我的数据库中.这里十六进制字符串的格式相当于OpenSSL在以前由openssl ecparam -genkey -name secp256r1 -out生成的文件x.pem上调用openssl ec -in x.pem -noout -text时生成的十六进制字符串x.pem.
消息和签名是从不同的应用程序接收的.
请考虑以下测试数据:
现在这应该是一个有效的签名.
我的目标是使用Java和/或Bouncycastle加密API验证消息上的签名.我创建了一个方法isValidSignaturefor:
@H_404_6@private static boolean isValidSignature(byte[] pubKey,byte[] message,byte[] signature) throws NoSuchAlgorithmException,NoSuchProviderException,InvalidKeyException,SignatureException,InvalidKeySpecException { Signature ecdsaVerify = Signature.getInstance("SHA256withECDSA",new BouncyCastleProvider()); ecdsaVerify.initVerify(getPublicKeyFromHex(pubKey)); ecdsaVerify.update(message); return ecdsaVerify.verify(signature); }我试图提取公钥:
KeyFactory.generatePublic:
@H_404_6@private static PublicKey getPublicKeyFromHex(byte[] pubKey) throws NoSuchAlgorithmException,InvalidKeySpecException { KeyFactory fact = KeyFactory.getInstance("ECDSA",new BouncyCastleProvider()); return fact.generatePublic(new X509EncodedKeySpec(pubKey)); }但这会抛出java.security.spec.InvalidKeySpecException(DER长度超过4个字节:26).
我该怎么做才能解析这个?
解决方法
Bouncy Castle example code on elliptic curve key pair Generation and key factories让我非常接近.
一旦我设法创建了一个ECDSA密钥工厂和secp256r1 / NIST P-256 / P-256 / prime256v1曲线的曲线规范,我就能够使用ECPointUtil.decodePoint来获得一个曲线点.然后,我可以生成一个公钥规范,使我能够生成如下公钥:
@H_404_6@private PublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException,InvalidKeySpecException { ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1"); KeyFactory kf = KeyFactory.getInstance("ECDSA",new BouncyCastleProvider()); ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1",spec.getCurve(),spec.getG(),spec.getN()); ECPoint point = ECPointUtil.decodePoint(params.getCurve(),pubKey); EcpublicKeySpec pubKeySpec = new EcpublicKeySpec(point,params); EcpublicKey pk = (EcpublicKey) kf.generatePublic(pubKeySpec); return pk; }