3
votes

I am trying to generate signature using ECDSA with secp256r1 curve (P256) and SHA256 algorithm for message hash. Also i am using Bouncy Castle libraries. Code below,

public class MyTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new MyTest().getSign();
    }

    void getSign() {
        // Get the instance of the Key Generator with "EC" algorithm

        try {
            KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
            ECGenParameterSpec kpgparams = new ECGenParameterSpec("secp256r1");
            g.initialize(kpgparams);

            KeyPair pair = g.generateKeyPair();
            // Instance of signature class with SHA256withECDSA algorithm
            Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
            ecdsaSign.initSign(pair.getPrivate());

            System.out.println("Private Keys is::" + pair.getPrivate());
            System.out.println("Public Keys is::" + pair.getPublic());

            String msg = "text ecdsa with sha256";//getSHA256(msg)
            ecdsaSign.update((msg + pair.getPrivate().toString())
                    .getBytes("UTF-8"));

            byte[] signature = ecdsaSign.sign();
            System.out.println("Signature is::"
                    + new BigInteger(1, signature).toString(16));

            // Validation
            ecdsaSign.initVerify(pair.getPublic());
            ecdsaSign.update(signature);
            if (ecdsaSign.verify(signature))
                System.out.println("valid");
            else
                System.out.println("invalid!!!!");

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

    }

}

Here key pairs are generated using KeyPair , but for my requirement I will be having a static privateKey and public key. Also, validation of signature is always returning false.

Need help, how can I have static private key and on validation part.

2

2 Answers

8
votes

Jackpot - nothing in your title is a problem!

First, you probably aren't actually using BouncyCastle. Sun/Oracle Java 7 and 8 now includes an EC provider (earlier versions did not) and the one-arg form of getInstance uses the first available provider, which is normally SunEC unless you or someone has altered the provider list.

TO VERIFY A SIGNATURE: pass the same data to the verifying Signature.update() as you passed to the signing Signature.update(). Exactly the same, byte for byte. Pass the signature value only to Signature.verify(). Putting PrivateKey.toString() in the data is silly; this value is specific to the running Java process, so you'll have to send it to the receiving process (if different, as it normally should be) where it is useless and a waste of space.

TO USE A STATIC KEY: do just that. Create a keypair and store it someplace, then read it in and use it. The easiest secure (password protected) store is a Java KeyStore (JKS) file, but that requires a certificate chain (perhaps a dummy one) which is a nuisance to code yourself; fortunately the keytool utility with -genkeypair generates a keypair with a dummy selfsigned certificate, and for -keyalg ec -keysize 256 it uses the (very popular) secp256r1 curve. Also specify -alias name of your choice, -keystore filename, any names you like for the dummy cert, and passwords. To use a keypair from a JKS file:

  • use java.security.KeyStore.getInstance("JKS") to create a store object and pass .load(InputStream,char[]) a FileInputStream on the file, and the password.

  • use .getKey(String alias,char[] password) and cast to get the PrivateKey. Use for signing.

  • use .getCertificateChain(String alias)[0].getPublicKey() to get the PublicKey from the first (only) cert. Use for verifying.

0
votes

I've decided update initial question's code with final working version for future readers.

    try {
        KeyPairGenerator kg = KeyPairGenerator.getInstance("EC");
        ECGenParameterSpec kpgparams = new ECGenParameterSpec("secp256r1");
        kg.initialize(kpgparams);

        KeyPair kp = kg.generateKeyPair();
        PublicKey pubKey = kp.getPublic();
        PrivateKey pvtKey = kp.getPrivate();

        // sign
        Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
        ecdsaSign.initSign(pvtKey);
        String message = "text ecdsa with sha256";//getSHA256(msg)
        ecdsaSign.update(message.getBytes(StandardCharsets.UTF_8), 0, message.length());
        byte[] signature = ecdsaSign.sign();

        // Validation
        ecdsaSign.initVerify(pubKey);
        ecdsaSign.update(message.getBytes(StandardCharsets.UTF_8), 0, message.length());
        boolean result = ecdsaSign.verify(signature);

        assertTrue(result); // junit5 assert
    } catch (Exception e) {
         e.printStackTrace();
    }