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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:23:59  来源:igfitidea点击:

How can I get a PublicKey object from EC public key bytes?

javacryptographybouncycastle

提问by mritz_p

I am developing an application that needs to validate SHA256withECDSAsignatures 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 -texton a file x.pemthat 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 isValidSignaturefor 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/prime256v1curve I was able to use ECPointUtil.decodePointto 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;
}