A Java implementation of AES-GCM-SIV (draft 05).
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci
src
.gitignore
CHANGELOG.md
LICENSE
README.md
pom.xml
spotbugs.xml

README.md

AES-GCM-SIV

CircleCI

A Java implementation of AES-GCM-SIV (draft-irtf-cfrg-gcmsiv-08), a nonce-misuse resistant Authenticated Encryption And Data (AEAD) algorithm.

Is it ready

No, AES-GCM-SIV is still in draft form and hasn't yet been standardized. This library implements the algorithm described in draft-irtf-cfrg-gcmsiv-08.

Is it fast

It's very fast. AES-GCM-SIV's performance is largely dependent on hardware support for AES and GCM. Java 8 added AES-NI support, but only for AES-CBC, and Java 9 will improve GCM performance via pclmulqdq intrinsics, but only for AES-GCM. All things being equal, AES-GCM is slightly faster for encryption and slightly slower for decryption.

Here's some benchmark results from a c4.xlarge EC2 instance using Java 1.8.0_131-b11, comparing AES/GCM/NoPadding to AES-GCM-SIV:

Benchmark                       Mode  Cnt   Score   Error  Units
Benchmarks.aes_GCM_Decrypt      avgt  200  24.336 ± 0.026  us/op
Benchmarks.aes_GCM_Encrypt      avgt  200  23.570 ± 0.008  us/op
Benchmarks.aes_GCM_SIV_Decrypt  avgt  200  23.154 ± 0.012  us/op
Benchmarks.aes_GCM_SIV_Encrypt  avgt  200  23.106 ± 0.015  us/op

Java 9's GCM intrinsics make it roughly 3x faster (9+181):

Benchmark                       Mode  Cnt   Score   Error  Units
Benchmarks.aes_GCM_Decrypt      avgt  200   8.936 ± 0.313  us/op
Benchmarks.aes_GCM_Encrypt      avgt  200   7.490 ± 0.237  us/op
Benchmarks.aes_GCM_SIV_Decrypt  avgt  200  23.439 ± 1.991  us/op
Benchmarks.aes_GCM_SIV_Encrypt  avgt  200  24.462 ± 0.196  us/op

Java 11's further optimizations make it roughly 4x faster (11+28):

Benchmark                       Mode  Cnt   Score   Error  Units
Benchmarks.aes_GCM_Decrypt      avgt    5   5.987 ± 0.272  us/op
Benchmarks.aes_GCM_Encrypt      avgt    5   5.876 ± 0.726  us/op
Benchmarks.aes_GCM_SIV_Decrypt  avgt    5  20.871 ± 3.363  us/op
Benchmarks.aes_GCM_SIV_Encrypt  avgt    5  19.970 ± 1.719  us/op

Why's it good

AES-GCM-SIV is a nonce-misuse resistant AEAD, which means it doesn't fail catastrophically if a nonce gets re-used. This is a concern for large systems which involve operations with a single key:

Since a central allocation system for nonces is not operationally viable, random selection of nonces is the only possibility. AES-GCM’s limit of 2^32 random nonces (per key) suggests that, even if the system rotated these secret keys daily, it could not issue more than about 50K tokens per second. However, in order to process DDoS attacks the system may need to sustain issuance of several hundred million per second.

Unlike AES-GCM or ChaChaPoly1305, AES-GCM-SIV can tolerate some duplicate nonces, but it still has limits:

When discussing this work, we found a widespread misunderstanding of the term “nonce-misuse resistant”. Many people appear to expect the security of a nonce-misuse resistant scheme to be completely unaffected by the number of times that a nonce is reused. Thus, while it is a convenient shorthand to distinguish schemes that tolerate repeated nonces (e.g., AES-GCM-SIV) from those that do not (e.g., AES-GCM and ChaCha20-Poly1305), nonce-misuse resistance is not necessarily a “binary” property. In particular, it is not binary for the case of AES-GCM-SIV, and as we have shown the security bounds of AES-GCM-SIV change as the number of repeated nonces varies.

As such, it is important to understand what security is actually guaranteed by nonce-misuse resistance. First and foremost, nonce-misuse resistant schemes reveal when the same plaintext is encrypted using the same nonce, and this is well understood. Due to this, some have concluded that if an application guarantees unique plaintexts, then the same nonce can be safely reused in every encryption. Although this is true in some sense, it is also true that the security bounds can be degraded, as we have shown in this paper. Thus, it is not recommended to purposefully use AES-GCM-SIV with the same nonce (unless the number of encryptions is small enough so that the quadratic bound is small). We stress that if the same nonce is used always, then AES-GCM-SIV is no worse than previous schemes; however, AES-GCM-SIV can achieve far better bounds and it is worth taking advantage of this.

We believe that AES-GCM-SIV is well suited to applications where independent servers need to work with the same key, and where nonce repetition is a real threat. In such cases, it is not possible to enjoy the better bounds available for encryption schemes that utilize state to ensure unique nonces in every encryption.

(from "AES-GCM-SIV: Specification and Analysis")

That said, you should still use randomly generated nonces:

We stress that nonce-misuse resistant schemes guarantee that if a nonce repeats then the only security loss is that identical plaintexts will produce identical ciphertexts. Since this can also be a concern (as the fact that the same plaintext has been encrypted twice is revealed), we do not recommend using a fixed nonce as a policy. In addition, as we show below, better-than-birthday bounds are achieved by AES-GCM-SIV when nonces repetition is low. Finally, as shown in [BHT18], there is a great security benefit in the multi- user/multi-key setting when each particular nonce is re-used by a small number of users only. We stress that nonce-misuse resistance was never intended to be used with intentional nonce-reuse; rather, such schemes provide the best possible security in the event of nonce reuse. Due to all of the above, it is RECOMMENDED that nonces be randomly generated.

Some example usage bounds for AES-GCM-SIV are given below (for these bounds, the adversary's advantage is always below 2^-32). For up to 256 repeats of a nonce (i.e., where one can assume that nonce misuse is no more than this bound), the following message limits should be respected (this assumes a short AAD):

  • 2^29 messages, where each plaintext is at most 1GiB
  • 2^35 messages, where each plaintext is at most 128MiB
  • 2^49 messages, where each plaintext is at most 1MiB
  • 2^61 messages, where each plaintext is at most 16KiB

(from draft-irtf-cfrg-gcmsiv-08)

Add to your project

<dependency>
  <groupId>com.codahale</groupId>
  <artifactId>aes-gcm-siv</artifactId>
  <version>0.4.3</version>
</dependency>

Note: module name for Java 9+ is com.codahale.aesgcmsiv.

Use the thing

import com.codahale.aesgcmsiv.AEAD;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

class Example {
  void roundTrip() {
    final AEAD aead = new AEAD(decodeHex("ee8e1ed9ff2540ae8f2ba9f50bc2f27c"));
    
    final byte[] plaintext = "Hello world".getBytes(StandardCharsets.UTF_8);
    final byte[] data = "example".getBytes(StandardCharsets.UTF_8);
   
    // automatically generates a nonce
    final byte[] ciphertext = aead.seal(plaintext, data);
    
    // automatically parses the nonce from the ciphertext
    final Optional<byte[]> result = aead.open(ciphertext, data);

    System.out.println(result.map(String::new));
  } 
}

AEAD also has versions of seal and open which support pre-generated nonces.

License

Copyright © 2017 Coda Hale

Distributed under the Apache License 2.0.