ECDSA Keys and Signatures
EJBCA supports ECDSA signature keys in addition to RSA. You can create a CA using ECDSA keys both using the Admin GUI and the CLI (bin/ejbca.sh ca init).
This section provides information on ECDSA Keys and Signatures in the following sections:
Generated Keys and Certificates
When generating a CA in EJBCA, up to three keys and certificates are generated:
- A CA signing keypair and certificate
- An encryption keypair, used for encrypting key recovery information
- An OCSP signer keypair and certificate
When using ECDSA keys, the CA signing keypair and the OCSP signer keypair will be the ECDSA keytype you select when creating the CA. The CA signing and OCSP signing certificate will be signed using your selected signature algorithm. The encryption keypair will always be RSA, using 1024 or 2048 bit key length. It uses the key length set in the Admin GUI or 2048 bit by default using the CLI.
Using ECDSA with an HSM
Note that the keyEncryptKey cannot be ECDSA, but should be an RSA key. Your HSM must support both ECDSA and RSA keys. You can use PKCS11HSMKeyTool from the clientToolBox to generate keys and certificate requests from an HSM. For more information, see the section about HSM property parameters.
Using named Brainpool curves in Java PKCS#11
Until recently, OracleJDK/OpenJDK did not have named curve definitions for the Brainpool curves. This functionality is available in later revisions of Java, such as late Java 8 and Java 11 releases. For older releases, Enterprise users can get a compiled patch together with an installation script for Debian-based operating systems from PrimeKey.
Brainpool should work on all HSMs that have named curve support for Brainpool. It has been tested on Thales TCT Luna SA and Utimaco CryptoServer. Thales ProtectServer supports Brainpool but not using named curves, see below for brainpool support on ProtectServer using custom domain parameters.
You can create and use CAs with brainpool curves in the HSM. Example clientToolBox commands to generate a key:
./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /usr/lunasa/lib/libCryptoki2_64.so brainpoolP160r1 keyAliasBp160 1 ./ejbcaClientToolBox.sh PKCS11HSMKeyTool test /usr/lunasa/lib/libCryptoki2_64.so 1 ./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /etc/utimaco/libcs2_pkcs11.so brainpoolP160r1 keyAliasBp160 1 ./ejbcaClientToolBox.sh PKCS11HSMKeyTool test /etc/utimaco/libcs2_pkcs11.so 1
Using SHA224WithECDSA in Java PKCS#11
OracleJDK/OpenJDK did not have support for SHA224WithECDSA in the PKCS#11 provider until recently. This functionality is available in later revisions of Java, such as late Java 8 and Java 11 releases. For older releases, Enterprise users can get a compiled patch together with an installation script for Debian-based operating systems from PrimeKey.
It should work on all HSMs that have support for SHA224WithECDSA.
Using Brainpool ECC with Thales ProtectServer Gold HSM
The following instructions were contributed by DGBK, Netherlands and apply for using Brainpool curves with the Thales ProtectServer Gold HSM. Note that ProtectServer needs explicit parameters for the Brainpool curves. Also, when using explicit parameters (and using the Sun PKCS#11 provider), you cannot use the EJBCA tools to generate keys, but have to use the HSM vendors tools.
Before generating domain parameters and keys, first apply the patch for explicit parameters, as described above.
Note that the following commands apply for ProtectServer Gold software version 3.33, firmware version 2.07.
- Create domain parameters file brainpoolP160r1.txt from ptk_c_administration_manual_rev-c.pdf, Appendix G, Sample EC Domain Parameter Files. Note that you must add "cofactor=01" last in the parameters file, the cofactor is always one (in the spec document) for brainpool curves (cofactor=1 does not work, it has to be 01).
Configure the HSM to accept custom domain parameters (E flag):
Import the domain parameters to the HSM:
/ctkmu idp -s 1 -t ec -n brainpoolP160r1 brainpoolP160r1.txtXML
Generate keys and a (dummy) certificate. The dummy certificate is needed for the java PKCS#11 provider, the DN does not matter.
./ctcert c -k -l bpkey -tec -s1 -CbrainpoolP160r1 -d30yXML
Test the keys with:
./ejbcaClientToolBox.sh PKCS11HSMKeyTool test /opt/PTK/lib/libcryptoki.so 1XML
Start EJBCA and create a new CA with CAToken Properties:
sharedLibrary=/opt/PTK/lib/libcryptoki.so defaultKey=bpkey slotLabelType=SLOT_NUMBER slotLabelValue=1XML
ECC named curves vs explicit parameters
Normally, you want to generate requests and certificates using named curves encoded in certificates and requests, this is what IETF recommends. In some cases you need to generate the request and certificate with explicit parameters instead, this is for instance mandated by ICAO for usage in CSCA's and DS's for ePassports.
- When generating requests with clientToolBox PKCS11HSMKeyTool certreq you can specify a flag to use explicit parameters instead of named curves. Named curves is the default.
- When creating CAs with ejbca.sh ca init you can specify a flag to use explicit parameters instead of named curves. Named curves is the default.
- When EJBCA issues certificate with public keys from certificate requests (csr's) the key in the certificate will be the same as in the csr. If the csr uses explicit parameters, so will the issued certificate.
If you generate a CA with explicit ECC parameters in the CA certificate you will not be able to run commands like 'ejbca.sh ca listcas' because Java only supports named curves when serializing certificates. You can resolve this by adding the BC provider as the first provider:
$ sudo vi /etc/java-7-openjdk/security/java.security security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider (renumber the ones below)
After editing this (make sure you edit the right file) you need to restart JBoss.
Uncompressed and compressed format
EC Public Keys, with named curves, can be encoded in two different ways in the SubjectPublicKeyInfo structure that carries the public key in X.509 certificates and PKCS#10 or CRMF CSRs. These are compressed or uncompressed form. While they are equivalent when using the public key, the byte encoding differ. As stated in RFC3279 section 2.3.5 the uncompressed format is the commonly used. EJBCA can issue certificates with both formats from EJBCA 8.0. CAs will be created using the uncompressed format, while issued certificates can use either. The following three different formats are supported in EJBCA 8.0 and later.
- If the CSR contains a SubjectPublicKeyInfo using named curve in uncompressed format, issued certificate will use named curve with uncompressed format.
- If the CSR contains a SubjectPublicKeyInfo using named curve in compressed format, issued certificate will use named curve with compressed format.
- If the CSR contains a SubjectPublicKeyInfo using explicit parameters in uncompressed format, issued certificate will use explicit parameters with uncompressed format.
EJBCA supports the curves that BouncyCastle supports, including named curves from Nist, SEC and X9.62. New curves may be supported without this list being updated, give it a try. For more information about ECDSA curves, refer to the Bouncycastle wiki.
Note that EJBCA does not support/allow EC keys less than 224 bits long. Shorter curves are noted below for reference only.
|X9.62 Curves||SEC Curves||Nist Curves||Teletrust Curves|
X9.62 provides 3 alternatives for the parameters that can be found in an EC public key. One of these is named implicitlyCA and indicates that the parameters are defined else where, implicit in the name of the certification authority (CA) that issued the key. In this situation the actual parameters appear in the ASN.1 encoding of the key as a DER encoded NULL. As the definition says, when the key is used, the parameters will have to come from elsewhere. In EJBCA the parameters are configured in conf/cesecore.properties.
When creating a new CA using the implicitlyCA facility, you first configure your curve parameters in conf/cesecore.properties and issue commands:
- ant clean
- ant deployear
After restarting the application server you can now create a new CA using the name implicitlyCA instead of a curve name as keyspec in the Admin GUI or CLI. The CA certificate will now be created with the NULL encoding of the public key.
When issuing client certificates where the client public key uses implicitlyCA, you must allow key length 0 in the certificate profile, because EJBCA can not read the key length, since the parameters are defined elsewhere.
See Bouncycastle wiki for more information about the implicitlyCA facility.
The curve parameters in conf/cesecore.parameters are configured in Bouncycastle using the following code:
ECCurve curve = new ECCurve.Fp( new BigInteger(ecdsa.implicitlyca.q), // q new BigInteger(ecdsa.implicitlyca.a, 16), // a new BigInteger(ecdsa.implicitlyca.b, 16)); // b org.bouncycastle.jce.spec.ECParameterSpec implicitSpec = new org.bouncycastle.jce.spec.ECParameterSpec( curve, curve.decodePoint(Hex.decode(ecdsa.implicitlyca.g)), // G new BigInteger(ecdsa.implicitlyca.n)); // n ConfigurableProvider config = (ConfigurableProvider)Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); config.setParameter(ConfigurableProvider.EC_IMPLICITLY_CA, implicitSpec);
Creating client certificates
You can also issue normal requests for client certificates using ECDSA keys.
All certificates signed by an ECDSA CA will naturally use ECDSA signatures, regardless if the client keys are RSA or ECDSA.
When batch generating client keys using the CLI command 'bin/ejbca.sh batch' you configure the type of client keys that will be generated in the file conf/batchtool.properties. The possible parameters are explained there. If using the implicitlyCA facility the same parameters as configured for the ca in conf/cesecore.properties are used.
When using the implicitlyCA mode only one set of curve parameters can be set for the whole EJBCA instance. This means that if you have several CAs using ECDSA with implicitlyCA, they will all use the same curve parameters. You can mix implicitlyCA with named curves according to your liking.