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

Support one pass re-encryption? #824

Open
newpavlov opened this issue Nov 30, 2021 · 2 comments
Open

Support one pass re-encryption? #824

newpavlov opened this issue Nov 30, 2021 · 2 comments
Labels
aead Authenticated Encryption with Associated Data (AEAD) crate cipher Block and stream cipher crate

Comments

@newpavlov
Copy link
Member

I have encountered a problem in which I need to re-encrypt data. I wonder if we could add some kind of API which would allow "in-flight" re-encryption, i.e. we would decrypt blocks (or a block, if cipher does not support parallel decryption) with an old cipher, immedetely encrypt them with a new cipher, and only then store the result in an output buffer. It should not only help with performance, since data processing is done in one pass, but also improve security a bit, since it would minimize time plaintext spends in RAM.

In my case decryption and encryption is done by a single algorithm, but in general decryption and encryption may be performed by different algorithms (e.g. you decrypt data with AES-GCM and encrypt it with ChaCha20Poly1305).

Unfortunately, right now I don't have good ideas of how such API could look like. Do you have any good ideas and do you think it's worth to support such API in trait crates?

@newpavlov newpavlov added aead Authenticated Encryption with Associated Data (AEAD) crate cipher Block and stream cipher crate labels Nov 30, 2021
@tarcieri
Copy link
Member

Something based on iterators might be useful here, iterating over chunks of the ciphertext, decrypting them, then passing the chunk for re-encryption.

But the real issue is this would require disclosing unauthenticated plaintexts, and would have an odd error case after the input has been re-encrypted in the event MAC verification fails.

If inputs are really so long that a microoptimization like this is needed, another option is to use STREAM to segment them, which avoids disclosing unauthenticated plaintexts.

@newpavlov
Copy link
Member Author

newpavlov commented Nov 30, 2021

Ideally data would stay in registers without spilling to stack or output buffer. In the stream ciphers case we even could XOR two keystream blocks and apply result to the input ciphertext, thus fundamentally eliminating plaintext exposure.

Also using iterators could be quite difficult in the case of block size mismatch.

But the real issue is this would require disclosing unauthenticated plaintexts, and would have an odd error case after the input has been re-encrypted in the event MAC verification fails.

I think we should avoid one-pass AEAD decryption if possible (i.e. we should check tag first and only then start decryption), even if it damages performance a bit. This applies to the proposed re-encryption as well. Yes, we could zeroize output buffer in the case of tag mismatch and from Rust PoV it would look like we do not expose plaintext, but there are some nasty corner cases like potential panics and operating over shared memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aead Authenticated Encryption with Associated Data (AEAD) crate cipher Block and stream cipher crate
Projects
None yet
Development

No branches or pull requests

3 participants
@tarcieri @newpavlov and others