Search code examples
encryptionaesbouncycastleelliptic-curveecdsa

ECDSA private and public keys - how to get SecretKey?


I have used generateKeyPair() method to generate 2 different KeyPair using ECDSA algorithm.

public KeyPair generateKeyPair(){           

    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp192r1");
    KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
    g.initialize(spec, new SecureRandom());

    return g.generateKeyPair(); 
}

Then I used PrivateKey and PublicKey from separate KeyPair to get combined SecretKey:

private SecretKey generateSecretKey(PrivateKey privateKey, PublicKey publicKey) {

    KeyAgreement ka = KeyAgreement.getInstance("ECDH");
    ka.init(privateKey);
    ka.doPhase(publicKey),
            true);

    return ka.generateSecret("AES");
}

But I get at ka.generateSecret("AES"):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi.engineGenerateSecret(Unknown Source)
    at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)

If I use ECDSA, I get:

Exception in thread "main" java.security.NoSuchAlgorithmException: Algorithm ECDSA not available
   at javax.crypto.KeyAgreement.getInstance(KeyAgreement.java:184)

Using DH throws:

Exception in thread "main" java.security.InvalidKeyException: DHKeyAgreement requires DHPrivateKey
    at org.bouncycastle.jcajce.provider.asymmetric.dh.KeyAgreementSpi.engineInit(Unknown Source)
    at javax.crypto.KeyAgreement.implInit(KeyAgreement.java:346)
    at javax.crypto.KeyAgreement.chooseProvider(KeyAgreement.java:378)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:470)

How to get combined SecretKey from PrivateKey and PublicKey which are generated using ECDSA algorithm?


Solution

  • It works correctly and returns curve size shared secret after removing "AES" argument from return ka.generateSecret();:

    private SecretKey generateSecretKey(PrivateKey privateKey, PublicKey publicKey) {
    
        KeyAgreement ka = KeyAgreement.getInstance("ECDH");
        ka.init(privateKey);
        ka.doPhase(publicKey, true);
    
        return ka.generateSecret();
    }