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

I am developing an application that should verify SHA256withECDSA signatures SHA256withECDSA public keys (NIST P-256, P-256, prime256v1).

Public keys are generated by another application at some earlier point in time and are stored in my database in hexadecimal encoding. The format of the hexadecimal string here is equivalent to the hexadecimal string that OpenSSL generates when invoking openssl ec -in x.pem -noout -text in the x.pem file that was previously generated using openssl ecparam -genkey -name secp256r1 -out x.pem . Message and signature are accepted from another application. Consider the following test data:

 // Stored in Database byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a"); // Received from Other Application byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29"); byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654"); 049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a"); // Stored in Database byte[] pubKey = DatatypeConverter.parseHexBinary("049a55ad1e210cd113457ccd3465b930c9e7ade5e760ef64b63142dad43a308ed08e2d85632e8ff0322d3c7fda14409eafdc4c5b8ee0882fe885c92e3789c36a7a"); // Received from Other Application byte[] message = DatatypeConverter.parseHexBinary("54686973206973206a75737420736f6d6520706f696e746c6573732064756d6d7920737472696e672e205468616e6b7320616e7977617920666f722074616b696e67207468652074696d6520746f206465636f6465206974203b2d29"); byte[] signature = DatatypeConverter.parseHexBinary("304402205fef461a4714a18a5ca6dce6d5ab8604f09f3899313a28ab430eb9860f8be9d602203c8d36446be85383af3f2e8630f40c4172543322b5e8973e03fff2309755e654"); 

Now it must be a valid signature.

My goal is to verify the signature on the message using the Java API and / or Bouncycastle crypto. For this, I created the isValidSignature method:

 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 tried to extract the public key:

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 raises a java.security.spec.InvalidKeySpecException (DER length is more than 4 bytes: 26). What can I do to make it out?

+6
java cryptography bouncycastle
source share
1 answer

The Bouncy Castle code example on the Generation elliptic curve key pairs and key factories got me pretty close.

Once I managed to create an ECDSA factory key and a curve specification for the secp256r1 / NIST P-256 / P-256 / prime256v1 , I was able to use ECPointUtil.decodePoint to get the curve point. Then I could generate a public key specification that would allow me to generate a public key as follows:

 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; } 
+12
source share

All Articles