There is no need to use a 571 bit curve. Curves with 512 bits key size or higher provide 256 bits of security. That's plenty - until quantum computing gets of age and in that case neither will suffice. With a large quantum computer the security of Elliptic Curve cryptography using the Discrete Logarithm problem (ECDL) with a large enough quantum computer will be next to zero.
Currently most standards use either prime curves (curves over F(p)) or Edwards curves such as Curve25519 (Ed25519 and X25519). What you are using when you specify 571 is probably the curve over F(2^m) called sect571r1 standardized as K-571. That's a binary / Koblitz curve; binary curves are currently not often used and may not be available in every provider. Up to Java 18 there has been no support for binary curves.
Java 18 does support both prime and Edwards curves such as Ed25519, as you can see when looking at the Security -> Providers -> SunEC provider guide, section "Supported Elliptic Curve Names". Currently it supports secp256r1, secp384r1 and secp521r1 for signature generation and key agreement, Ed25519 and Ed448 for signature generation and X25519 and X448 for key agreement. These have been in there since Java 11, the last LTS version of Java.
Choosing specific curves this way isn't very clear and may have future consequences. What if a different curve is used because another provider is added that implements a curve of the same size?
Instead, use the following code if you want to stick to an named strong curve over a prime field:
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
generator.initialize(new ECGenParameterSpec("secp521r1"));
KeyPair keyPair = generator.generateKeyPair();
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
Pretty please with sugar on top, use the actual name of the curve and not just the bit size, i.e. ECGenParameterSpec
. You really don't want to generate curve domain parameters yourself, nor do you want to use any curve that fits the bit size. In general, with cryptography, I would not use any default values unless a standard defines them explicitly.
You could also try and add a provider (BouncyCastle for Java and later versions of Android, SpongyCastle for earlier versions of Android) to get support for more curves. Make sure you specify the provider to be used for the generator in that case. I would seriously suggest using a named curve as argued above.
Beware that the SunEC provided implementations of KeyPairGenerator
and Signature
will probably insist that they can handle software defined EC keys, while they are incompatible with these curve names. That means that you need to explicitly use the BouncyCastle or SpongyCastle provider, rather than simply add the provider to the known list:
Provider bc = new BouncyCastleProvider();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", bc);
kpg.initialize(new ECGenParameterSpec("K-571")); // "sect571r1" also works
KeyPair kp = kpg.generateKeyPair();
Signature sig = Signature.getInstance("SHA512WithECDSA", bc);
sig.initSign(kp.getPrivate());
sig.sign();