【问题标题】:How can I get a PublicKey object from EC public key bytes?如何从 EC 公钥字节中获取 PublicKey 对象?
【发布时间】:2014-10-02 10:42:55
【问题描述】:

我正在开发一个应用程序,该应用程序需要借助 secp256r1(NIST P-256、P-256、prime256v1)公钥验证 SHA256withECDSAsignatures。

公钥由不同的应用程序在较早的某个时间点生成,并以十六进制编码存储在我的数据库中。这里的十六进制字符串的格式等价于 OpenSSL 在之前由openssl ecparam -genkey -name secp256r1 -out x.pem 生成的文件x.pem 上调用openssl ec -in x.pem -noout -text 时将生成的十六进制字符串。 消息和签名是从不同的应用程序接收的。 考虑以下测试数据:

// Stored in Database
byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a");

// Received from Other Application
byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29");
byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654");

现在这个应该是一个有效的签名。

我的目标是使用 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);
}

我已尝试提取公钥:

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));
}

但这会引发java.security.spec.InvalidKeySpecException(DER 长度超过 4 个字节:26)。 我该怎么做才能解析这个?

【问题讨论】:

  • 只是为了在复制代码时允许正确性; -noout OpenSSL 选项拼写错误。

标签: java cryptography bouncycastle


【解决方案1】:

Bouncy Castle example code on elliptic curve key pair Generation and key factories 让我非常接近。

一旦我设法为secp256r1/NIST P-256/P-256/prime256v1 曲线创建了ECDSA 密钥工厂和曲线规范,我就能够使用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;
}

【讨论】:

  • 谢谢,我正在尝试仅使用便携式充气城堡来做同样的事情,有什么想法吗?我失败了,因为 android.mono 中没有 ECPointUtil
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 2020-06-17
  • 2021-07-29
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多