BoringSSL is a Google fork of OpenSSL. It includes various interesting patches, including an implementation of the ChaCha20 cipher. In addition, BoringSSL allows you to group cipher suites of equal preference:
In this article I show you how you can tweak your nginx configuration to take advantage of this feature.
AES with AES-NI outperforms ChaCha20
AES with AES-NI makes encryption fast. Blazingly fast. For example, here is a benchmark I just took from the server running this website (a modest Intel Xeon E3-1220 V2 @ 3.10GHz):
Did 20341000 AES-128-GCM (16 bytes) seal operations in 3000099us (6780109.6 ops/sec): 108.5 MB/s Did 2356000 AES-128-GCM (1350 bytes) seal operations in 3000761us (785134.2 ops/sec): 1059.9 MB/s Did 438000 AES-128-GCM (8192 bytes) seal operations in 3002910us (145858.5 ops/sec): 1194.9 MB/s Did 17839000 AES-256-GCM (16 bytes) seal operations in 3000160us (5946016.2 ops/sec): 95.1 MB/s Did 2092000 AES-256-GCM (1350 bytes) seal operations in 3000884us (697127.9 ops/sec): 941.1 MB/s Did 388000 AES-256-GCM (8192 bytes) seal operations in 3004207us (129152.2 ops/sec): 1058.0 MB/s Did 7779000 ChaCha20-Poly1305 (16 bytes) seal operations in 3000332us (2592713.1 ops/sec): 41.5 MB/s Did 1139000 ChaCha20-Poly1305 (1350 bytes) seal operations in 3001412us (379488.1 ops/sec): 512.3 MB/s Did 220000 ChaCha20-Poly1305 (8192 bytes) seal operations in 3006395us (73177.3 ops/sec): 599.5 MB/s
As you can see from the results above, nothing beats AES with hardware acceleration – not even ChaCha20, which is impressively fast too given that it’s a software only cipher implementation.
ChaCha20 outperforms AES without AES-NI
Not every platform supports AES hardware acceleration though. Think of all the different types of clients connecting to this website. Many of them are ARM-powered mobile devices, Android or iOS for example, neither of which have hardware support for AES. So even if my server can handle the AES routines crazy fast, those devices would have to work a lot harder as they’re browsing this website. In this case, wouldn’t it make sense to switch to ChaCha20 instead, which not only reduces latency (= faster page loads) but also safes battery power?
Google ran a few tests:
Best of two worlds: AES and ChaCha20 in an equal preference group with BoringSSL
How do you enable group cipher suites of equal preference? You can find the info in the ssl_cipher_process_rulestr() function in ssl/ssl_ciph.c. To group ciphers, you seperate them using the OR symbol (|) and then enclose the group with square brackets, like this:
So for all nginx aficionados, here is the server-preferred cipher list I currently use (nginx must be build against boringssl):
ssl_ciphers [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]:[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECD HE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384;
As a result, if you are visiting this site with Chrome on an iPhone or Android device, you’ll be using the ChaCha20 cipher.
On the other hand, if you’re visiting with Chrome on a Windows 7 machine with AES-NI support, you’ll be using the AES-GCM cipher instead.