使用 SpongyCastle 验证 ECDSA 签名
Verify ECDSA signature using SpongyCastle
我正在尝试使用 SpongyCastle 在 Android 上验证 ECDSA 数字签名。我有一个 X509Certificate
,其中包含我需要用来验证它的 public 密钥,但我不太清楚如何获得 PublicKey
(向下转换 ECPublicKey
) 用于 ECDSASigner
class.
我使用 BouncyCastle 的 C# 版本完成了此操作,如下所示:
ECDsaSigner signer = new ECDsaSigner();
signer.Init(false, cert.GetPubliKey());
在 API 的 Java 版本中,X509Certificate.getPublicKey()
方法 returns 是 PublicKey
class 而不是 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。
我想我终于明白了。看起来我需要使用 Signature
class 来处理这个问题,而不是直接使用 ECDSASigner
class。我仍然想了解 ECDSASigner
class 是如何在所有这些抽象内部使用的(只是出于我自己的好奇心)。
无论如何,这就是我的代码用来验证 ECDSA 签名的样子(至少供我使用)。希望这会帮助将来尝试解决类似问题的人:
Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
sig.initVerify(pubKey);
sig.update(plainBytes);
if (!sig.verify(signedBytes)) {
throw new Exception("ECDSA signature verification failed.");
}
正如您自己所说,您需要使用签名 class。 JCA 是在 Java 中进行加密的默认方式,它使用提供者模式:
- 首先,您必须注册要使用的提供商,例如
Security.addProvider(new BouncyCastleProvider());
Android 上的默认提供程序是一个缩减的 BouncyCastle。 SpongyCastle 是 BouncyCastle 的全功能副本(重命名以避免名称冲突)。还有 Sun/Oracle JCA 可用。
- 接下来,您请求一个签名实例,例如:
Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
在这里,JCA 查找名称为 "BC" 的提供程序,以及它是否已注册支持 "NONEwithECDSA" 签名的 SignatureSpi class。 "Signature" class 作为工厂 class 工作,它也包装了实际的实现 class.
- 终于可以使用签名实例了:
sig.initVerify(pubKey);
首先,它会在Signatureclass中执行一些代码(通常只是验证),然后调用底层的SignatureSpiclass。当您尝试直接使用提供程序时,可能缺少这个中间层,例如,class 初始化可能需要额外的步骤。
要查看更多详细信息,您可以下载 bouncy/spongy 城堡源代码并在调试器中执行示例 - 这不是 Android 特定的,因此您可以,例如,在蚀.
我正在尝试使用 SpongyCastle 在 Android 上验证 ECDSA 数字签名。我有一个 X509Certificate
,其中包含我需要用来验证它的 public 密钥,但我不太清楚如何获得 PublicKey
(向下转换 ECPublicKey
) 用于 ECDSASigner
class.
我使用 BouncyCastle 的 C# 版本完成了此操作,如下所示:
ECDsaSigner signer = new ECDsaSigner();
signer.Init(false, cert.GetPubliKey());
在 API 的 Java 版本中,X509Certificate.getPublicKey()
方法 returns 是 PublicKey
class 而不是 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。
我想我终于明白了。看起来我需要使用 Signature
class 来处理这个问题,而不是直接使用 ECDSASigner
class。我仍然想了解 ECDSASigner
class 是如何在所有这些抽象内部使用的(只是出于我自己的好奇心)。
无论如何,这就是我的代码用来验证 ECDSA 签名的样子(至少供我使用)。希望这会帮助将来尝试解决类似问题的人:
Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
sig.initVerify(pubKey);
sig.update(plainBytes);
if (!sig.verify(signedBytes)) {
throw new Exception("ECDSA signature verification failed.");
}
正如您自己所说,您需要使用签名 class。 JCA 是在 Java 中进行加密的默认方式,它使用提供者模式:
- 首先,您必须注册要使用的提供商,例如
Security.addProvider(new BouncyCastleProvider());
Android 上的默认提供程序是一个缩减的 BouncyCastle。 SpongyCastle 是 BouncyCastle 的全功能副本(重命名以避免名称冲突)。还有 Sun/Oracle JCA 可用。
- 接下来,您请求一个签名实例,例如:
Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
在这里,JCA 查找名称为 "BC" 的提供程序,以及它是否已注册支持 "NONEwithECDSA" 签名的 SignatureSpi class。 "Signature" class 作为工厂 class 工作,它也包装了实际的实现 class.
- 终于可以使用签名实例了:
sig.initVerify(pubKey);
首先,它会在Signatureclass中执行一些代码(通常只是验证),然后调用底层的SignatureSpiclass。当您尝试直接使用提供程序时,可能缺少这个中间层,例如,class 初始化可能需要额外的步骤。
要查看更多详细信息,您可以下载 bouncy/spongy 城堡源代码并在调试器中执行示例 - 这不是 Android 特定的,因此您可以,例如,在蚀.