Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

# [RFC] Implement Authenticated Encryption using libsodium #113

Open
tychota opened this issue Feb 23, 2021 · 1 comment
Open

# [RFC] Implement Authenticated Encryption using libsodium #113

tychota opened this issue Feb 23, 2021 · 1 comment

Comments

@tychota
Copy link

tychota commented Feb 23, 2021

[RFC] Use libsodium instead of OpenSSL

Summary

This RFC conceptualise the implementation and migration of libsodium instead of OpenSSL to power transcrypt.
It will increase security and usability at a minor cost of installation ease and while supporting a lot of platforms.

Motivation

Expected outcome is to have better security and usability, while still supporting a wide range of platforms and being easy to install

Malleability issue

The main motivation is the malleability issues described in https://github.com/elasticdog/transcrypt#cipher-selection

Indeed aes-256-cbc is a cipher without authentication which means that transcrypt won't crash if the key is wrong or undefined.
Today in one of our project we spend a few hours debugging an issue with a new CI were the password wasn't set and transcrypt was doing. (This issue happened twice for me in two years so I think it is worth considering it.)

transcrypt -c aes-256-cbc -p 'undefined'

Ultimately this should not have happened and the step were transcrypt was executed should have failed with proper authentication.

Open SSL platform variability

As specified in the readme, the different platforms have very different version of OpenSSL.

I didn't find a marketshare of openssl version but I tend to agree that it is hard to move forward with new openSSL algorithms, as old platform may not support them.

Guide-level explanation

Phase 1

With the new transcrypt people will be able to execute the same worklow than today.

transcrypt
transcrypt -c aes-256-cbc -p 'the-new-password'

but they would get a hint in CLI to opt in and use the new backend "modern"

transcrypt -b modern
transcrypt -b modern -p 'the-new-password'

When using this modern backend this will add a step that check for a CLI wrapper to libsodium. Eg:

We can start by just implementing python backend, as it is widely stared, support old python version, and python itself as a really great platform support, is preinstalled in almost every UNIX system

Phase 2

Now three would be a depreciation warning. People can use the provided utility to migrate to new backend

transcrypt -m modern

New project are done with backend modern but can use

transcrypt -b legacy
transcrypt -b legacy -c aes-256-cbc -p 'the-new-password'

to use old backend

Phase 3

(Probably in a very long time)

We remove support for legacy backend.

Reference-level explanation

We will use libsodium secretbox constructions.

(Maybe we should use the file specific operation to work on a stream: libsodium secretstream)

How to chose between secretbox and secretstream.

image

Key derivation function

Libsodium already implement keygen function so manual steps are not needed.
We just need to use the high level equivalent for:

unsigned char key[crypto_secretbox_KEYBYTES];
crypto_secretbox_keygen(key);

eg in pynacl

import nacl.secret
import nacl.utils

# This must be kept secret, this is the combination to your safe
key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)

and store it.

Encryption and authentication

(Note the algorithm provides encryption and authentication in the same time, not encrypt then mac).

The algorithm is:

Encryption: XSalsa20 stream cipher
Authentication: Poly1305 MAC

It is:

  • very secure, more resistant than AES to bad implementation (eg timing attacks)
  • fast, even on non AES CPUs
  • futureproof (implemented by default in TLS 1.3)

We just need to use the high level equivalent for:

#define MESSAGE ((const unsigned char *) "test")
#define MESSAGE_LEN 4
#define CIPHERTEXT_LEN (crypto_secretbox_MACBYTES + MESSAGE_LEN)

unsigned char nonce[crypto_secretbox_NONCEBYTES];
unsigned char ciphertext[CIPHERTEXT_LEN];

randombytes_buf(nonce, sizeof nonce);
crypto_secretbox_easy(ciphertext, MESSAGE, MESSAGE_LEN, nonce, key);

eg in pynacl

import nacl.secret

key = "previously define key"

# This is your safe, you can use it to encrypt or decrypt messages
box = nacl.secret.SecretBox(key)

# This is our message to send, it must be a bytestring as SecretBox will
#   treat it as just a binary blob of data.
message = b"test"

# Encrypt our message, it will be exactly 40 bytes longer than the
#   original message as it stores authentication information and the
#   nonce alongside it.
encrypted = box.encrypt(message)

to cipher

and

# Decrypt our message, an exception will be raised if the encryption was
#   tampered with or there was otherwise an error.
plaintext = box.decrypt(encrypted)
print(plaintext.decode('utf-8'))

to decrypt.

Drawbacks

  • libsodium is not install by default in the system
  • libsodium is a lib thus it doesn't come with a a CLI. We need a high level wrapper for it.
  • there is less history to the ChaCha20 cipher than AES one's

Rationale and alternatives

Chacah20Poly1305 looks a compelling cipher to use. It increases the security by preventing malleability attacks. It is standard, and high security.
Two alternatives are:

  • stick to CBC and add an HMAC on top it: that looks better than existing and keep openssl but is less featureproof, and require doing our own crypto: should we pad the cipher ? the mac ? ect)
$ openssl enc -e -k password -p -aes-256-cbc -in plaintext -out ciphertext
salt=A2402067B9BFD4A1
key=EB3A88115C30F26C3987F1AB2577DF5B58C80EBEEA623506517FAD843C64E1FC
iv =B382453BCBF579CE14C0726D343F40E2
$ openssl dgst -hmac EB3A88115C30F26C3987F1AB2577DF5B58C80EBEEA623506517FAD843C64E1FC -sha256 ciphertext -out mac
HMAC-SHA256(ciphertext)= fa3fb9c9c743f35ba81793e2704c3fc9737cd2675011110cb1655ea7ceed2914
$ cat ciphertext mac

References

@tychota
Copy link
Author

tychota commented Feb 23, 2021

Hello there.

Thank for the library. It is widely used at https://www.bam.tech/bam-agence-experte-design-et-d%C3%A9veloppement-mobile
I opened this RFC as I was encountering malleability issues and lost a bunch of time today.

I'm proposing some design change for the lib, as I notice the subject isn't present in other issue.

I'm open for discussion and I will be updating the RFC as discussion arise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant