From 58c1f1adc2db7afbf72de1544bcaed9e9dc3d4bb Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Thu, 6 Jul 2023 23:16:50 +0100 Subject: [PATCH] update --- .../index.md | 78 +++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) rename docs/blog/2023/07/{01-new-encryption => 07-new-encryption}/index.md (52%) diff --git a/docs/blog/2023/07/01-new-encryption/index.md b/docs/blog/2023/07/07-new-encryption/index.md similarity index 52% rename from docs/blog/2023/07/01-new-encryption/index.md rename to docs/blog/2023/07/07-new-encryption/index.md index 1cd01d89868..179f929623f 100644 --- a/docs/blog/2023/07/01-new-encryption/index.md +++ b/docs/blog/2023/07/07-new-encryption/index.md @@ -9,23 +9,25 @@ tags: [insights] End to end encryption is a very important component of Atuin. One of our core philosophies when we created the sync service is that we want no reason to worry about user data. The shell is a very -sensitive system with API keys, AWS credentials, account passwords, etc. We didn't want to give the opportunity for that data to leak, -either through an attack, through a mistake on our parts, or through -state actor interference. +sensitive system with API keys, AWS credentials, account passwords, etc. +We didn't want to give the opportunity for that data to leak, either through an attack, +through a mistake on our parts, or through state actor interference. -This post will cover my research into the long-term security of Atuin history data. [Side channel attacks](https://en.wikipedia.org/wiki/Side-channel_attack) are not our top concern, although where possible I have tried to prevent them. -These attacks would likely be directly coordinated at a specific user, -as side channel attacks require monitoring an encryption algorithm in action (in otherwords, monitoring the device). Since your history data is already stored unencrypted locally, it's most likely cheaper for an attacker to [buy a wrench](https://xkcd.com/538/) and steal your laptop, than it is to analyse your CPU access patterns. +If there's one thing I have learnt as an engineer, it's that cryptography is hard. +If you are an expert in cryptographic implementations or cryptoanalysis, please get in touch. +This post will cover my research as - a non crypto expert - into the long-term security of Atuin history data. -> NOTE: There are still concerns about recently discovered attacks like Meltdown/Spectre -which have been shown to extract keys from JS directly in the browser. -> These can allow wide-spread attacks. They are considered extreme vulnerabilities -> and often you have bigger security concerns. I recommend always staying up to date on -> your OS security updates. +> Disclaimer, where reasonable, I have considered the security of +> [Side channel attacks](https://en.wikipedia.org/wiki/Side-channel_attack). +> Right now, our biggest concern is attacks on the atuin server, where the encrypted data is stored at rest. +> All atuin data is stored unencrypted on your local device in order to perform search. Improvements +> to cryptographic implementations can come in later revisions if any realistic side channel attacks are found. ## TL;DR -Our encryption system is changing from [NaCl secretbox](https://nacl.cr.yp.to/secretbox.html), and moving to [PASETO v4 local encryption](https://github.com/paseto-standard/paseto-spec/tree/master/docs/01-Protocol-Versions#version-4-sodium-modern) with [PASERK local key wrapping](https://github.com/paseto-standard/paserk/blob/master/types/local-wrap.md). +Our encryption system is changing from [NaCl secretbox](https://nacl.cr.yp.to/secretbox.html), +and moving to [PASETO v4 local encryption](https://github.com/paseto-standard/paseto-spec/tree/master/docs/01-Protocol-Versions#version-4-sodium-modern) +with [PASERK local key wrapping](https://github.com/paseto-standard/paserk/blob/master/types/local-wrap.md). ## Backstory @@ -33,11 +35,16 @@ All the way back in [April 2021, in our V0.5 release](https://github.com/ellie/a Ellie decided to use the [NaCl standard](https://nacl.cr.yp.to/) (aka salt/libsodium) for our encryption as a tried and trusted standard. Specifically, [secretbox](https://nacl.cr.yp.to/secretbox.html) was the algorithm of choice. +If you're not familiar, secretbox is an implementation of _authenticated symmetrical encryption_. This means +that only the owner of the encryption key can decrypt the data (this will be the user), and that any attempts +to tamper with the data can be detected. + Honestly, this is a great system and offers everything we needed. However, our interface to libsodium was an unmaintained crate called [sodiumoxide](https://github.com/sodiumoxide/sodiumoxide) and had issues being portable. Because of this, I started looking into what algorithms libsodium uses underneath and if we can use a native Rust implementation. -As an Authenticated Encryption (AEAD) scheme, secretbox is made up of 2 main components. A stream cipher and a message authentication code (MAC). +Secretbox is made up of 2 main components. A stream cipher and a message authentication code. These are XSalsa20 and Poly1305 respectively, both designed by NaCl's author [Daniel J. Bernstein](https://en.wikipedia.org/wiki/Daniel_J._Bernstein). -In a brave effort, I decided to [roll my own crypto](https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own) and implement this [XSalsa20 + Poly1305 system in Rust](https://github.com/ellie/atuin/pull/805). +In a brave effort, I decided to [roll my own crypto](https://security.stackexchange.com/questions/18197/why-shouldnt-we-roll-our-own) +and implement this [XSalsa20 + Poly1305 system in Rust](https://github.com/ellie/atuin/pull/805). > NOTE: I didn't actually implement the underlying algorithms. we are using: > * [poly1305](https://github.com/RustCrypto/universal-hashes/tree/master/poly1305) @@ -50,16 +57,17 @@ In a brave effort, I decided to [roll my own crypto](https://security.stackexcha After peeling back the veil that is our cryptographic implementation, I started thinking a lot more about just how secure the system is. -The more I started looking, the more I noticed potential improvements. Salsa20/Poly1305 both date back to 2005. In another 20 years, is this system going to still be secure? +The more I started looking, the more I noticed potential improvements. +Salsa20/Poly1305 both date back to 2005. In another 20 years, is this system going to still be secure? Let's take a look at some potential attacks ### We don't guarantee a unique Initialisation Vector per message We use a random 192 bit IV. There is a known attack on stream ciphers if the -Key + IV pair is ever re-used. For all practical purposes this is enough, assuming the OS random source is any good. A [birthday attack](https://en.wikipedia.org/wiki/Birthday_attack) calculation suggests that it needs in the order of 10^25 messages for a 1% chance of collision. +Key + IV pair is ever re-used. For all practical purposes this is enough, assuming the OS random source is any good. A [birthday attack](https://en.wikipedia.org/wiki/Birthday_attack) calculation suggests that it needs in the order of 10^23 messages for a one-in-a-trillion chance of collision. -This is not an issue as none of our users are ever going to generate 10^25 entries in their lifetimes, and we certainly aren't willing to store [yottabytes](https://en.wikipedia.org/wiki/Byte#Multiple-byte_units) of their data. +This is not an issue as all of our users combined are never going to generate 10^23 entries, and we certainly aren't willing to store [zettabytes](https://en.wikipedia.org/wiki/Byte#Multiple-byte_units) of their data. ### We use the same key for each message @@ -69,7 +77,9 @@ To put that number into perspective. Performing 1 billion key operations per CPU Atuin uses a 256 bit key which is even more secure, and therefore not at risk of a practical brute force attack. It follows that we are likely safe from a known plain-text attack. -However, there is still the issue of key leaking. We have no key-upgrade policy. If a key is leaked, maybe through a side-channel attack or through a social attack, then the only solution is to create a new account with a new key. +However, there is still the issue of key leaking. We have no key-upgrade policy. +If a key is leaked, maybe through a side-channel attack, a social attack, or malware, +then the only solution is to create a new account with a new key. This is partially an issue. @@ -81,7 +91,15 @@ We're also in the middle of redesigning our sync service. While we're already pl ### Key wrapping -A common approach to encrypting lots of different data is the use of wrapped keys. The idea here is that each payload has an ephemeral encryption key. This is then encrypted (wrapped) using the master key and stored with the data. Innitially, this seemed less secure to me. However, analysis seems to point out that the master key is less vulnerable to side channel attacks since it is less used. It also offers no decrease in security since brute forcing the master key from an ephemeral data key is just as hard as it is for any message. +A common approach to encrypting lots of different data is the use of wrapped keys. +The idea here is that each payload has an ephemeral encryption key. +This is then encrypted (wrapped) using the master key and stored with the data. + +Innitially, this seemed less secure to me. However, analysis seems to point out that +the master key is less vulnerable to side channel attacks since it is less used. +It also offers no decrease in security since brute forcing the master key from an +ephemeral data key is just as hard as it is for any message. In the end, it's like +a password manager for your encrypted data. This unlocks some potential future upgrades. @@ -90,12 +108,24 @@ This unlocks some potential future upgrades. ### Stronger ciphers -XSalsa20 was later superceded by XChaCha20 by the same author. It has a very similar construction, but the stream cipher has better mixing characteristics, which makes any non brute force attacks harder to craft. +XSalsa20 was later superceded by XChaCha20 by the same author. It has a very similar construction, +but the stream cipher has better mixing characteristics, which makes any non brute force attacks harder to craft. + +## Conclusion -## Outcome +I started to craft a new solution using these concepts. +But eventually I realised that I shouldn't be reinventing the wheel here. +During more and more of my research sessions did [PASETO](https://paseto.io/) come up. +While the intended use case is security tokens, +their local encryption scheme is designed such that encrypted data is safe to be shared publically. +Their V4 scheme also uses the XChaCha20 cipher like I was initially planning to use. -I started to craft a new solution using these concepts. But eventually I realised that I shouldn't be reinventing the wheel here. More and more in my research did [PASETO](https://paseto.io/) come up. While the intended use case is security tokens, their local encryption scheme is designed such that encrypted data is safe to be shared publically. Their V4 scheme also uses the XChaCha20 cipher like I was initially planning to use. +In the end I bit the bullet and decided to use the standard. +The nice thing with secretbox is that existing implementations in other languages are widely available. +Making it easy to implement sync in third parties. If we implemented our own scheme, +that would make it much easier for third parties to make mistakes if they wanted to use the sync data directly. -In the end I bit the bullet and decided to use the standard. The nice thing with secretbox is that existing implementations in other languages are widely available. Making it easy to implement sync in third parties. If we implemented our own scheme, that would make it much easier for third parties to make mistakes if they wanted to use the sync data directly. +Using PASETO, there are existing implementations that we didn't have to write. +This means that we don't build software doomed to die a lonely death. It also means +that we benefit directly from future versions of the specification. -Using PASETO, there are existing implementations that we didn't have to write. This means that we don't build software doomed to die a lonely death.