Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for DER encoded keys #9

Open
ricmoo opened this issue Jan 19, 2015 · 5 comments
Open

Add support for DER encoded keys #9

ricmoo opened this issue Jan 19, 2015 · 5 comments

Comments

@ricmoo
Copy link
Owner

ricmoo commented Jan 19, 2015

A lot of people use Java on their server side, which stores keys DER encoded.

It should be fairly simple to add ASN.1 identifiers and bit strings to the DER decoder. I do need to research what various identifiers Java will use to specify the payload though.

@user454322
Copy link

In the meantime, how can I use keys generated by Bouncy Castle in GMEllipticCurveCrypto?

@ricmoo
Copy link
Owner Author

ricmoo commented Jan 21, 2015

Here is a quick example. I'm not really a Java guy, so I'm dumping it out as a hex encoded string to make it easier to see what you get, but it should be fairly simple to adapt to your needs... (i.e. base64 or binary)

import java.math.BigInteger;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;

public class KeyEncoder {

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

    private static String numberToString(BigInteger value, int size) {
        byte bytes[] = value.toByteArray();

        // Initialize the output with 0's
        char output[] = new char[size * 2];
        for (int i = 0; i < size * 2; i++) {
            output[i] = '0';
        }

        // Place the number in the output right-aligned
        int back = output.length - 1;
        for (int i = bytes.length - 1; i >= 0; i--) {
            if (back < 1) { break; }
            int v = bytes[i] & 0xFF;
            output[back--] = hexArray[v & 0x0F];
            output[back--] = hexArray[v >>> 4];
        }

        return new String(output);
    }

    public static String encodePublicKey(ECPublicKey publicKey) {
        int bits = publicKey.getParams().getCurve().getField().getFieldSize();

        ECPoint point = publicKey.getW();
        String x = numberToString(point.getAffineX(), bits / 8);
        String y = numberToString(point.getAffineY(), bits / 8);

        return "04" + x + y;
    }

    public static String encodePrivateKey(ECPrivateKey privateKey) {
        int bits = privateKey.getParams().getCurve().getField().getFieldSize();
        return numberToString(privateKey.getS(), bits / 8);
    }

    public static KeyPair generate(String name) throws Exception {
        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(name);
        KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
        g.initialize(ecSpec, new SecureRandom());
        return g.generateKeyPair();
    }


    public static void main(String[] argv) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        KeyPair pair;
        try {
            pair = generate("secp128r1");
            System.out.println("secp128k1 pub: " + encodePublicKey((ECPublicKey)(pair.getPublic())));
            System.out.println("secp128k1 priv: " + encodePrivateKey((ECPrivateKey)(pair.getPrivate())));

            pair = generate("secp192r1");
            System.out.println("secp192k1 pub: " + encodePublicKey((ECPublicKey)(pair.getPublic())));
            System.out.println("secp192k1 priv: " + encodePrivateKey((ECPrivateKey)(pair.getPrivate())));

            pair = generate("secp256r1");
            System.out.println("secp256k1 pub: " + encodePublicKey((ECPublicKey)(pair.getPublic())));
            System.out.println("secp256k1 priv: " + encodePrivateKey((ECPrivateKey)(pair.getPrivate())));

            pair = generate("secp384r1");
            System.out.println("secp384k1 pub: " + encodePublicKey((ECPublicKey)(pair.getPublic())));
            System.out.println("secp384k1 priv: " + encodePrivateKey((ECPrivateKey)(pair.getPrivate())));

        } catch (Exception e) {
            System.out.println(e);

        }
    }
}

@user454322
Copy link

Thanks!

It is working now.

This is what I'm doing:

  • Java
System.out.println("private:" + BaseEncoding.base64().encode(
                        Crypto.encodePrivateKey(keyPair.getPrivate())
                        ));

System.out.println("public:" + BaseEncoding.base64().encode(
                        Crypto.encodePublicKey(keyPair.getPublic())
                        ));

which produces something like:

private:gPMSvSgCTuwdDKETYHwhIUYeGsa+aMTF5A7zndqgVR4=
public:BKw6bRNWHpjZ/jq8vSUAwEEOHCWeKClN6GUlBT1qIOlL7Ya2C8vngYhqj1f906JZHN5jlIpD9TPN5hwQThlIKpA=

  • Then in Objective-C
GMEllipticCurveCrypto *keyPair = [GMEllipticCurveCrypto cryptoForKeyBase64:@"BKw6bRNWHpjZ/jq8vSUAwEEOHCWeKClN6GUlBT1qIOlL7Ya2C8vngYhqj1f906JZHN5jlIpD9TPN5hwQThlIKpA="];
keyPair.privateKeyBase64 = @"gPMSvSgCTuwdDKETYHwhIUYeGsa+aMTF5A7zndqgVR4=";

@fullfiction
Copy link

fullfiction commented Jan 6, 2017

Hello there,

pls give me some example how can I generate keypair, send public to server in DER format and verify it with BC

@passuf
Copy link

passuf commented Nov 23, 2017

Hi everyone,

Is there any update on this? I am currently trying to export the public key in DER format.

Thanks for any input!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants