Implement the ChaCha20 and ChaCha20-Poly1305 ciphers as specified in RFC 7539. ChaCha20 is a relatively new stream cipher that can replace the older, insecure RC4 stream cipher.
- Provide ChaCha20 and ChaCha20-Poly1305
Cipherimplementations. These algorithms will be implemented in the SunJCE provider.
- Provide a
KeyGeneratorimplementation that creates keys suitable for ChaCha20 and ChaCha20-Poly1305 algorithms.
- Provide an
AlgorithmParametersimplementation for use with the ChaCha20-Poly1305 algorithm.
TLS cipher suite support will not be part of this JEP. TLS support for these ciphers will be part of a follow-on enhancement.
The only other widely adopted stream cipher, RC4, has long been deemed insecure. The industry consensus is that ChaCha20-Poly1305 is secure at this point in time, and it has seen fairly wide adoption across TLS implementations as well as in other cryptographic protocols. The JDK needs to be on par with other cryptographic toolkits and TLS implementations.
Additionally, TLS 1.3 only allows the use of AEAD-based cipher suites. Implementing the ChaCha20-Poly1305 algorithm is the first step in implementing different cipher suites that run in AEAD mode in case there were ever weaknesses to be found in AES or GCM.
The ChaCha20 and ChaCha20-Poly1305 algorithms will implement the
javax.crypto.CipherSpi API within the SunJCE provider. Ciphers will be instantiated in the same way as other ciphers, using the
Cipher.getInstance() method. For both ciphers, two acceptable transforms are allowed. The single-name transform is the preferred approach,
"ChaCha20" for ChaCha20 as a simple stream cipher with no authentication, and
"ChaCha20-Poly1305" for ChaCha20 as an AEAD cipher using Poly1305 as the authenticator.
"ChaCha20-Poly1305/None/NoPadding" are also acceptable transform strings, though no other mode or padding values besides
"NoPadding" will be accepted. Use of other mode or padding values will cause an exception to be thrown.
Initialization of the ChaCha20 cipher will accept a new
ChaCha20ParameterSpec(byte nonce, int counter); // Constructor public byte getNonce(); // Obtains a copy of the nonce value public int getCounter(); // Obtains the initial counter value
The nonce value must be 96 bits in length (12 bytes). Any other length will cause an exception to be thrown. The integer counter value may be any integer value, even negative, in order to allow the full range of unsigned 32-bit values.
Initialization of this algorithm without a
ChaCha20ParameterSpec will cause the cipher to generate its own 12-byte nonce internally and set the counter value to 1. The counter bytes may be obtained by invoking the
Initialization for ChaCha20-Poly1305 may be accomplished by providing an instance of the current
javax.crypto.spec.IvParameterSpec class which contains the 12-byte nonce. The decision to use
ChaCha20ParameterSpec allows ChaCha20-Poly1305 to be backported to earlier releases without making any API changes. Because
IvParameterSpec does not set length requirements on the bytes it holds, the cipher object itself will enforce the 12-byte length requirement during initialization.
As with ChaCha20, ChaCha20-Poly1305 may be initialized without an
IvParameterSpec, in which case the nonce will be randomly generated and may be obtained with
Key objects provided through any of the
init methods must have an algorithm type of "ChaCha20". A new
KeyGenerator implementation will be created to support this. As with existing
KeyGenerator implementations for other algorithms such as AES, RC2, ARCFOUR and the HmacSHA2 family, this
KeyGenerator may not be initialized with an
AlgorithmParameterSpec. If forms of the
init method are invoked that allow an adjustable key length, that parameter must be set to 256 or an
InvalidParameterException will be thrown.
Use of the ChaCha20 algorithm follows the existing
Cipher API used for other stream ciphers. A simple single-part encryption could be written as follows:
// Get a Cipher instance and set up the parameters // Assume SecretKey "key", 12-byte nonce "nonceBytes" and plaintext "pText" // are coming from outside this code snippet Cipher mambo = Cipher.getInstance("ChaCha20"); ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec(nonceBytes, 7); // Use a starting counter value of "7" // Encrypt our input mambo.init(Cipher.ENCRYPT_MODE, key, mamboSpec); byte encryptedResult = mambo.doFinal(pText);
For ChaCha20 running in AEAD mode with the Poly1305 authenticator, only the nonce is required since RFC 7539 defines the initial counter value for data to begin at 1. In order to allow this Cipher implementation to be backportable and facilitate its use within our JSSE provider,
javax.crypto.spec.IvParameterSpec will be used to provide the nonce.
When running in AEAD mode, output sizes may be different than inputs due to either the addition of the authentication tag (for encryption) or the consumption and verification of the tag (for decryption). Where allocation of an output buffer before encryption/decryption is desired the
getOutputSize() method should be used. A sample single-part encryption follows:
// Get a Cipher instance and set up the parameters // Assume SecretKey "key", 12-byte nonce "nonceBytes" and plaintext "pText" // are coming from outside this code snippet Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305"); AlgorithmParameterSpec mamboSpec = new IvParameterSpec(nonceBytes); // Encrypt our input mambo.init(Cipher.ENCRYPT_MODE, key, mamboSpec); byte encryptedResult = new byte[mambo.getOutputSize(pText.length)]; mambo.doFinal(pText, 0, pText.length, encryptedResult);
An important requirement for both ChaCha20 and ChaCha20-Poly1305 ciphers is that following a
doFinal() call, a new
init() call must be made which provides a different nonce from the one currently configured. This is similar to the requirement on encryption for AES-GCM, but in the cases of these two ciphers the init requirement must happen after both encryption and decryption operations. Subsequent calls to
Cipher.doFinal() after a previous
doFinal() and no
init() call in-between will result in an
IllegalStateException being thrown.
Testing will cover the following areas:
- Verify that the ChaCha20 and ChaCha20-Poly1305 ciphers pass all known-answer tests
- Verify the ChaCha20 key generator accepts the proper initialization forms and generates keys of the appropriate size
- Verify that the ciphers handle restrictions on initialization (no nonce reuse, etc.)
- Verify that the ciphers execute the proper re-initialization requirements between complete encryption/decryption operations
- Verify that our implementation interoperates with at least one other implementation
- Verfy the ChaCha20-Poly1305 AlgorithmParameters implementation accepts nonce data in the proper format.
The only significant dependency is the constant-time math APIs. These will be provided as part of JEP 324.