如何从 EC 公钥字节中获取 PublicKey 对象?
我正在开发一个应用程序,该应用程序需要在 secp256r1
(NIST P-256、P-256、prime256v1)公钥的帮助下验证 SHA256withECDSA
签名.p>
公钥由不同的应用程序在较早的某个时间点生成,并以十六进制编码存储在我的数据库中.这里的十六进制字符串的格式等同于 OpenSSL 在对文件 x.pem
调用 openssl ec -in x.pem -noout -text
时生成的十六进制字符串之前由 openssl ecparam -genkey -name secp256r1 -out x.pem
生成.消息和签名是从不同的应用程序接收的.考虑以下测试数据:
//存储在数据库中byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e//从其他应用程序接收字节[]消息= DatatypeConverter.parseHexBinary( 54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29");字节[]签名= DatatypeConverter.parseHexBinary( 304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654");
现在这个应该是一个有效的签名.
我的目标是使用 Java 和/或 Bouncycastle 加密 API 验证消息上的签名.我为此创建了一个方法 isValidSignature
:
private static boolean isValidSignature(byte[] pubKey, byte[] message,byte[] 签名)抛出 NoSuchAlgorithmException、NoSuchProviderException、InvalidKeyException、SignatureException、InvalidKeySpecException {签名 ecdsaVerify = Signature.getInstance("SHA256withECDSA", new BouncyCastleProvider());ecdsaVerify.initVerify(getPublicKeyFromHex(pubKey));ecdsaVerify.update(消息);返回 ecdsaVerify.verify(签名);}
我已尝试提取公钥:
KeyFactory.generatePublic:
private static PublicKey getPublicKeyFromHex(byte[] pubKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {KeyFactory 事实 = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());return fact.generatePublic(new X509EncodedKeySpec(pubKey));}
但这会引发 java.security.spec.InvalidKeySpecException
(DER 长度超过 4 个字节:26).我该怎么做才能解析这个?
Bouncy Castle 椭圆曲线密钥对生成和密钥工厂示例代码让我非常接近.
一旦我设法为 secp256r1
/NIST P-256
/P-256
/创建了 ECDSA 密钥工厂和曲线规范prime256v1
曲线 我能够使用 ECPointUtil.decodePoint
来获得曲线点.然后我可以生成一个公钥规范,使我能够生成这样的公钥:
private PublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException {ECNamedCurveParameterSpec 规范 = ECNamedCurveTable.getParameterSpec("prime256v1");KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());ECPoint 点 = ECPointUtil.decodePoint(params.getCurve(), pubKey);ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec);返回PK;}
I am developing an application that needs to validate SHA256withECDSA
signatures with the help of secp256r1
(NIST P-256, P-256, prime256v1) public keys.
The public keys are generated by a different application at some earlier point in time and stored in my database in hex encoding. The format of the hex string here is equivalent to the hex string OpenSSL would generate when calling openssl ec -in x.pem -noout -text
on a file x.pem
that has previously been generated by openssl ecparam -genkey -name secp256r1 -out x.pem
.
The message and signature are received from a different application.
Consider the following test data:
// Stored in Database
byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a");
// Received from Other Application
byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29");
byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654");
Now this should be a valid signature.
My objective is to validate the signature over the message using the Java and/or Bouncycastle crypto API. I have created a method isValidSignature
for that:
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);
}
I have tried to extract the public key:
KeyFactory.generatePublic:
private static PublicKey getPublicKeyFromHex(byte[] pubKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
KeyFactory fact = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
return fact.generatePublic(new X509EncodedKeySpec(pubKey));
}
But this throws a java.security.spec.InvalidKeySpecException
(DER length more than 4 bytes: 26).
What can I do to parse this?
The Bouncy Castle example code on elliptic curve key pair Generation and key factories got me pretty close.
Once I managed to create a ECDSA key factory and a curve specification for the secp256r1
/NIST P-256
/P-256
/prime256v1
curve I was able to use ECPointUtil.decodePoint
to obtain a curve point. I could then generate a public key specification that enabled me to generate a public key like this:
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;
}
相关文章