0

I try to use Elliptic Curve Digital Signature Algorithm (ECDSA) with Bouncy Castle and Java. I want to generate a public key and private key. The problem is that these keys have the exact same values. Let's look at the code:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
ECGenParameterSpec params = new ECGenParameterSpec("prime256v1");
keyPairGenerator.initialize(params, secureRandom); 
KeyPair keyPair = keyPairGenerator.generateKeyPair();

I use the java.security related classes:

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;

Everything is working fine, but the problem is that the public key matches the private key. I am confused because the public key should be a point on the elliptic curve (so far so good). The private key should be an integer, but it is the same point (on the curve) as the public key. Am I missing something? When I print the public key and private key values:

EC Public Key [f9:63:ec:0b:ca:a4:c6:f8:50:d0:2f:29:8b:23:10:13:d8:1c:2f:16]
        X: 818af4b0ed955e273c4d81c1480db282293b95881b7f04dba897da0cef3a91de
        Y: 3b00a30ced960780a8a830b928601dbfd32ac09e8e19e2297f8831f66e80fd15

EC Private Key [f9:63:ec:0b:ca:a4:c6:f8:50:d0:2f:29:8b:23:10:13:d8:1c:2f:16]
        X: 818af4b0ed955e273c4d81c1480db282293b95881b7f04dba897da0cef3a91de
        Y: 3b00a30ced960780a8a830b928601dbfd32ac09e8e19e2297f8831f66e80fd15
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
balazsh
  • 17
  • 3

1 Answers1

1

You just did system out on the object. These are indeed the public specs. If you check the actual bytes of the key, you'll see the difference:

@Test
void stackOverflowQuestion() throws Exception{
    Security.addProvider(new BouncyCastleFipsProvider());

    final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", BouncyCastleFipsProvider.PROVIDER_NAME);
    final SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
    final ECGenParameterSpec params = new ECGenParameterSpec("prime256v1");
    keyPairGenerator.initialize(params, secureRandom);
    final KeyPair keyPair = keyPairGenerator.generateKeyPair();

    System.out.println(keyToBase64String(keyPair.getPrivate()));
    System.out.println(keyToBase64String(keyPair.getPublic()));
}

public static String keyToBase64String(final Key key) {
    return bytesToBase64(key.getEncoded());
}

private static String bytesToBase64(final byte[] bytes) {
    return Base64.getEncoder().encodeToString(bytes);
}

output:

MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQggbwdSOULxslgm+ckKNW9d0gtPAPUrSjU29Rtk6szTeKgCgYIKoZIzj0DAQehRANCAASP3lAcUGCqmvYUt9hZEjPArtcdBlUYC3Sac9XSpZFRkFnWmIHxwx40ejFXxE9U2mq+VDMe21rjXBvdnqxHyCV4
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEj95QHFBgqpr2FLfYWRIzwK7XHQZVGAt0mnPV0qWRUZBZ1piB8cMeNHoxV8RPVNpqvlQzHtta41wb3Z6sR8gleA==

Also, don't use SHA1PRNG. You can trust the provide secure random of BC. Use instead: keyPairGenerator.initialize(params);

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
BarbetNL
  • 408
  • 2
  • 16
  • The SHA1 collision break affects some signatures especially certificates and some raw hashes (like git), but does not endanger PRNG. OTOH I concur the Bouncy people are competent and it's best to accept their defaults unless there is a clear reason to change. – dave_thompson_085 Jul 13 '22 at 23:54
  • @dave_thompson_085 you are correct, your answer triggered my interest and I read into it a bit. Still I read that it calls in the random generator of the operating system and that in some OS's it might not be the best option. So best indeed is it to leave it to the BC library to decide how to generate the secureRandom. It is optimized for all enviroments/conditions. – BarbetNL Jul 14 '22 at 09:47