Skip to content

Conversation

jagerman
Copy link
Member

This defines a new determinstic, streamable attachment encryption/decryption for Session clients to use in the future, built on libsodium's crypto_secretstream API (which is XChaCha20-poly1305-based).

Unlike current Session attachment encryption, the encryption added here uses deterministic (though private, cryptographically secure) nonce and key generated from the user, file contents itself, and type of file, so that the same user uploading an identical attachment results in an identical encrypted copy, thus allowing deduplication in case of things like file server response timeouts or repeated uploads of the same profile picture.

Unlike current attachments, these functions also allow streaming of attachment data (via the added Decryptor) so that, in future clients, an attachment can be decrypted and saved as it arrives, rather than needing to store the whole thing in memory to decrypt it.

This also reimplements the padding added to attachments. Currently clients use this monstrosity:

let desiredSize: Int = max(541, min(Int(Network.maxFileSize), Int(floor(pow(1.05, ceil(log(Double(plaintext.count)) / log(1.05)))))))

which is not only difficult to read, but also involves several floating point functions where imprecision (and thus potential metadata leakage about which client created it) can creep in. The new protocol works vaguely similar: we pad up to fixed sizes that with the size of the attachment.

Moreover there is no way to recover the amount of padding from the attachment itself: rather a Session client has to communicate the URL, key, and size to someone they are trying to send to out of band, who then downloads, decrypts the whole thing, then chops off the padding based on what they were told the size was. With the new scheme, padding is now deterministic and embedded in the pre-encrypted data, and is transparently stripped out when decrypting.

The plan is for Session clients to start understanding (but not using) this new encryption format, and then once sufficient time has passed for clients to have upgraded, start using this instead of the current AES-GCM encryption.

This defines a new determinstic, streamable attachment
encryption/decryption for Session clients to use in the future, built on
libsodium's crypto_secretstream API (which is XChaCha20-poly1305-based).

Unlike current Session attachment encryption, the encryption added here
uses deterministic (though private, cryptographically secure) nonce and
key generated from the user, file contents itself, and type of file, so
that the same user uploading an identical attachment results in an
identical encrypted copy, thus allowing deduplication in case of things
like file server response timeouts or repeated uploads of the same
profile picture.

Unlike current attachments, these functions also allow streaming of
attachment data (via the added Decryptor) so that, in future clients, an
attachment can be decrypted and saved as it arrives, rather than needing
to store the whole thing in memory to decrypt it.

This also reimplements the padding added to attachments.  Currently
clients use this monstrosity:

    let desiredSize: Int = max(541, min(Int(Network.maxFileSize), Int(floor(pow(1.05, ceil(log(Double(plaintext.count)) / log(1.05)))))))

which is not only difficult to read, but also involves several floating
point functions where imprecision (and thus potential metadata leakage
about which client created it) can creep in.  The new protocol works
vaguely similar: we pad up to fixed sizes that with the size of the
attachment.

Moreover there is no way to recover the amount of padding from the
attachment itself: rather a Session client has to communicate the URL,
key, *and size* to someone they are trying to send to out of band, who
then downloads, decrypts the whole thing, then chops off the padding
based on what they were told the size was.  With the new scheme, padding
is now deterministic and embedded in the pre-encrypted data, and is
transparently stripped out when decrypting.

The plan is for Session clients to start understanding (but not using)
this new encryption format, and then once sufficient time has passed for
clients to have upgraded, start using this instead of the current
AES-GCM encryption.
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

Successfully merging this pull request may close these issues.

1 participant