Turn an byte encoded Key back into it's original ECPublicKey in Bouncy Castle
-
19-09-2019 - |
Question
In Java I have a ECDH public Key that I am sending as a byte array.
Once I have received the byte array how can I turn it back into a public key?
I am using Bouncy Castle but a Java solution would be just as useful.
Thanks
Solution
How are the raw bytes formatted for the ECDH key? Where are you getting the raw bytes?
Generally, one uses the appropriate *Spec class to turn raw key material into a Key but the ECPublicKeySpec and DHPublicKeySpec classes don't accept a raw byte array.
OTHER TIPS
When you got the encoded key, assuming you used the default "[your keyPair].getPublic().getEncoded()" method, this will work.
X509EncodedKeySpec ks = new X509EncodedKeySpec(pubKeyByteString.toByteArray());
KeyFactory kf;
try {
kf = java.security.KeyFactory.getInstance("ECDH");
} catch (NoSuchAlgorithmException e) {
log.error("Cryptography error: could not initialize ECDH keyfactory!", e);
return;
}
ECPublicKey remotePublicKey;
try {
remotePublicKey = (ECPublicKey)kf.generatePublic(ks);
} catch (InvalidKeySpecException e) {
log.warn("Received invalid key specification from client",e);
return;
} catch (ClassCastException e) {
log.warn("Received valid X.509 key from client but it was not EC Public Key material",e);
return;
}
I found the above solution by @LaceCard didn't work for me. In general this isn't obvious but then again nothing in cryptography is ;)
String key = "MihU9ztW9sEvkBL6BxyaOMgkSbodNS8yoHaHcio+WE...blahblah"
byte[] keyBytes = Base64.decode(key);
//If using Android and Spongycastle provider should be "SC"
KeyFactory kf = KeyFactory.getInstance("ECDH", "BC");
//CURVE_NAME e.g prime192v1
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE_NAME);
ECPoint point = ecSpec.getCurve().decodePoint(keyBytes);
ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, ecSpec);
ECPublicKey myECPublicKey = (ECPublicKey) kf.generatePublic(pubSpec);
Note: you'll need to handle the potential exceptions appropriately