How can I generate a valid ECDSA EC key pair?

snewtMs picture snewtMs · Oct 20, 2016 · Viewed 7.3k times · Source

I am trying to generate ECDSA key pair using SpongyCastle in Android. This is the code:

static {
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

public static KeyPair generate() {
        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
        KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "SC");
        generator.initialize(ecSpec, new SecureRandom());
        KeyPair keyPair = g.generateKeyPair();
        Log.i(TAG, "EC Pub Key generated: " + utils.bytesToHex(keyPair.getPublic().getEncoded()));
        Log.i(TAG, "EC Private Key generated: " + utils.bytesToHex(keyPair.getPrivate().getEncoded()));            
       return generator.generateKeyPair();
}

Something is wrong since I always get something like that example of Public Key:

3059301306072A8648CE3D020106082A8648CE3D03010703420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

and Private Key:

308193020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420219AB4B3701630973A4B2917D53F69A4BE6DAD61F48016BFEF147B2999575CB2A00A06082A8648CE3D030107A14403420004483ABA9F322240010ECF00E818C041A60FE71A2BD64C64CD5A60519985F110AEDE6308027D2730303F5E2478F083C7F5BB683DCAC22BFEB62F3A48BD01009F40

The site ECDSA sample give me "Invalid ECDSA signature message", and them seems really very different from that smaller Private Key and always starting with "04" Public Key generated in the same site.

Also, my backend verification gives me the error "Invalid point encoding 0x30"

The backend Java method check is:

public ECPublicKey getPublicKeyFromHex(String publicKeyHex)
        throws NoSuchAlgorithmException, DecoderException, ApplicationGenericException {
    byte[] rawPublicKey = Hex.decodeHex(publicKeyHex.toCharArray());
    ECPublicKey ecPublicKey = null;
    KeyFactory kf = null;

    ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
    ECCurve curve = ecNamedCurveParameterSpec.getCurve();
    EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecNamedCurveParameterSpec.getSeed());
    java.security.spec.ECPoint ecPoint = ECPointUtil.decodePoint(ellipticCurve, rawPublicKey);
    java.security.spec.ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve,
            ecNamedCurveParameterSpec);
    java.security.spec.ECPublicKeySpec publicKeySpec = new java.security.spec.ECPublicKeySpec(ecPoint,
            ecParameterSpec);

    kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());

    try {
        ecPublicKey = (ECPublicKey) kf.generatePublic(publicKeySpec);
    } catch (Exception e) {
        throw new ApplicationGenericException(e.getMessage(), e.getCause());
    }

    return ecPublicKey;
}

Answer

dave_thompson_085 picture dave_thompson_085 · Oct 20, 2016

Java's default encoding for a PublicKey is "X.509" which is not just the EC point; it is an ASN.1 structure identifying the algorithm (EC) and parameters (here prime256v1) PLUS a BIT STRING wrapping the point; see rfc5280 section 4.2.1.7 and rfc3279 section 2.3.5.

Similarly the default encoding for PrivateKey is "PKCS#8" (unencrypted) which is a structure containing an AlgorithmIdentifier plus an OCTET STRING wrapping the data which in this case contains both the private key value and a copy of the public key, see rfc5208 section 5 and C.4 of document SEC 1 at http://www.secg.org with tag [0] omitted but tag [1] present.

To read (either or both of) them back in to Java, get a KeyFactory.getInstance("EC") and use generate{Public,Private} on an X509EncodedKeySpec or PKCS8EncodedKeySpec respectively. ECDSA and ECDH (and ECMQV etc) use the same key structures, unlike classic integer DSA and DH which use the same mathematical structure ($Z_p^*$) but slightly different representations.

PS: the javadoc for java.security.Key tells you most of this.