0

I'm trying to verify an ECDSA digital signature on Android using SpongyCastle. I have a X509Certificate that contains the public key that I need to use to verify it but I can't quite figure out how to get the PublicKey (down cast ECPublicKey) for use with the ECDSASigner class.

I've done this using the C# version of BouncyCastle which looks like this:

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

In the Java version of the APIs, the X509Certificate.getPublicKey() method returns a PublicKey class instead of AsymmetricKeyParameter. However, the ECDSASigner.init() method needs a CipherParameters object. I can't figure out how to do this for ECDSA.

For RSA signatures I just manually reconstructed a new RSAKeyParameters object:

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

This doesn't seem ideal but I think it should work. But I can't even figure out how to do this equivalent for ECDSA. I would think there's a better way to do this but I can't figure out the right APIs to use.

Jason X
  • 51
  • 5

2 Answers2

5

I think I finally figured this out. It looks like I need to use the Signature class to handle this instead of using the ECDSASigner class directly. I'd still like to understand how the ECDSASigner class is used internally inside all of this abstraction (just for my own curiosity).

Anyways, this is what my code looks like to verify the ECDSA signature (for my use at least). Hopefully this will help some future person trying to solve a similar issue:

Signature sig = Signature.getInstance("NONEwithECDSA", "BC");
sig.initVerify(pubKey);
sig.update(plainBytes);
if (!sig.verify(signedBytes)) {
    throw new Exception("ECDSA signature verification failed.");
}
Jason X
  • 51
  • 5
0

As you noted yourself, you need to use Signature class. JCA is the default way to do crypto in Java and it uses provider pattern:

  1. First, you must register what provider to use, e.g.,
Security.addProvider(new BouncyCastleProvider());

The default provider on Android is a cut-down BouncyCastle. SpongyCastle is a fully-featured copy of BouncyCastle (renamed to avoid name conflicts). There are also Sun/Oracle JCA's available.

  1. Next, you request a signature instance, e.g.:
Signature sig = Signature.getInstance("NONEwithECDSA", "BC");

Here, JCA looks for the provider with name "BC" and whether it has registered a SignatureSpi class that supports "NONEwithECDSA" signature. The "Signature" class works as a factory class that also wraps the actual implementation class.

  1. Finally, you can use the signature instance:
sig.initVerify(pubKey);

First, it executes some code (usually, just verification) in Signature class and then calls the underlying SignatureSpi class. This intermediate layer is probably what was missing when you tried to use the provider directly, e.g., the class initialization might need extra steps.

To look at more details, you can download the bouncy/spongy castle source and execute the example in debugger - this is not Android-specific so you can, e.g., create a desktop app in Eclipse.

StoneyKeys
  • 138
  • 8