0

我正在尝试使用 SpongyCastle 在 Android 上验证 ECDSA 数字签名。我有一个X509Certificate包含我需要用来验证它的公钥,但我不太清楚如何获取PublicKey(向下转换ECPublicKey)以用于ECDSASigner该类。

我使用 C# 版本的 BouncyCastle 完成了这项工作,如下所示:

ECDsaSigner signer = new ECDsaSigner();
signer.Init(false, cert.GetPubliKey());

在 API 的 Java 版本中,该X509Certificate.getPublicKey()方法返回一个PublicKey类而不是AsymmetricKeyParameter. 但是,该ECDSASigner.init()方法需要一个CipherParameters对象。我不知道如何为 ECDSA 执行此操作。

对于 RSA 签名,我只是手动重建了一个新RSAKeyParameters对象:

RSAEngine engine = new RSAEngine();
engine.init(
    false,
    new RSAKeyParameters(
        false,
        ((RSAPublicKey) pubKey).getModulus(),
        ((RSAPublicKey) pubKey).getPublicExponent()
    )
);

这似乎并不理想,但我认为它应该工作。但我什至不知道如何为 ECDSA 做这个等价物。我认为有更好的方法可以做到这一点,但我无法确定要使用的正确 API。

4

2 回答 2

5

我想我终于想通了。看起来我需要使用Signature类来处理这个问题,而不是ECDSASigner直接使用类。我仍然想了解如何ECDSASigner在所有这些抽象内部使用该类(只是出于我自己的好奇心)。

无论如何,这就是我的代码验证 ECDSA 签名的样子(至少供我使用)。希望这将帮助一些未来试图解决类似问题的人:

Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
sig.initVerify(pubKey);
sig.update(plainBytes);
if (!sig.verify(signedBytes)) {
    throw new Exception("ECDSA signature verification failed.");
}
于 2015-07-20T16:00:36.330 回答
0

正如您自己指出的那样,您需要使用 Signature 类。JCA是在 Java 中进行加密的默认方式,它使用提供者模式:

  1. 首先,您必须注册要使用的提供程序,例如,
Security.addProvider(new BouncyCastleProvider());

Android 上的默认提供程序是精简版 BouncyCastle。SpongyCastle 是 BouncyCastle 的全功能副本(已重命名以避免名称冲突)。还有可用的 Sun/Oracle JCA。

  1. 接下来,您请求一个签名实例,例如:
签名 sig = Signature.getInstance("NONEwithECDSA", "BC");

在这里,JCA 查找名称为“BC”的提供者,以及它是否注册了支持“NONEwithECDSA”签名的 SignatureSpi 类。“Signature”类作为一个工厂类工作,它也包装了实际的实现类。

  1. 最后,您可以使用签名实例:
sig.initVerify(pubKey);

首先,它在 Signature 类中执行一些代码(通常只是验证),然后调用底层的 SignatureSpi 类。当您尝试直接使用提供程序时,可能缺少这个中间层,例如,类初始化可能需要额外的步骤。

要查看更多详细信息,您可以下载 bouncy/spongy castle 源代码并在调试器中执行示例 - 这不是 Android 特定的,因此您可以例如在 Eclipse 中创建桌面应用程序。

于 2015-12-11T09:15:27.950 回答