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
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);