java 如何从 EC 公钥字节获取 PublicKey 对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26159149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get a PublicKey object from EC public key bytes?
提问by mritz_p
I am developing an application that needs to validate SHA256withECDSA
signatures with the help of secp256r1
(NIST P-256, P-256, prime256v1) public keys.
我正在开发一个需要SHA256withECDSA
借助secp256r1
(NIST P-256、P-256、prime256v1)公钥来验证签名的应用程序。
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:
公钥是由不同的应用程序在更早的某个时间点生成的,并以十六进制编码存储在我的数据库中。这里的十六进制字符串的格式等同于十六进制字符串时调用的OpenSSL将生成openssl ec -in x.pem -noout -text
一个文件x.pem
以前已被生成openssl ecparam -genkey -name secp256r1 -out x.pem
。消息和签名是从不同的应用程序接收的。考虑以下测试数据:
// Stored in Database
byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a");
// Received from Other Application
byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29");
byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654");
Now this shouldbe 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:
我的目标是使用 Java 和/或 Bouncycastle 加密 API 验证消息的签名。我isValidSignature
为此创建了一个方法:
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:
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?
但这会抛出一个java.security.spec.InvalidKeySpecException
(DER 长度超过 4 个字节:26)。我能做些什么来解析这个?
回答by mritz_p
The Bouncy Castle example code on elliptic curve key pair Generation and key factoriesgot me pretty close.
椭圆曲线密钥对生成和密钥工厂的Bouncy Castle 示例代码让我非常接近。
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:
有一次,我成功地创建一个ECDSA密钥工厂,为曲线规格secp256r1
/ NIST P-256
/ P-256
/prime256v1
曲线,我能够用ECPointUtil.decodePoint
获得曲线点。然后我可以生成一个公钥规范,使我能够生成这样的公钥:
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;
}