mirror of
https://github.com/FiloSottile/age.git
synced 2026-01-03 10:55:14 +00:00
age: mitigate multi-key attacks on ChaCha20Poly1305
It's possible to craft ChaCha20Poly1305 ciphertexts that decrypt under multiple keys. (I know, it's wild.) The impact is different for different recipients, but in general only applies to Chosen Ciphertext Attacks against online decryption oracles: * With the scrypt recipient, it lets the attacker make a recipient stanza that decrypts with multiple passwords, speeding up a bruteforce in terms of oracle queries (but not scrypt work, which can be precomputed) to logN by binary search. Limiting the ciphertext size limits the keys to two, which makes this acceptable: it's a loss of only one bit of security in a scenario (online decryption oracles) that is not recommended. * With the X25519 recipient, it lets the attacker search for accepted public keys without using multiple recipient stanzas in the message. That lets the attacker bypass the 20 recipients limit (which was not actually intended to defend against deanonymization attacks). This is not really in the threat model for age: we make no attempt to provide anonymity in an online CCA scenario. Anyway, limiting the keys to two by enforcing short ciphertexts mitigates the attack: it only lets the attacker test 40 keys per message instead of 20. * With the ssh-ed25519 recipient, the attack should be irrelevant, since the recipient stanza includes a 32-bit hash of the public key, making it decidedly not anonymous. Also to avoid breaking the abstraction in the agessh package, we don't mitigate the attack for this recipient, but we document the lack of anonymity. This was reported by Paul Grubbs in the context of the upcoming paper "Partitioning Oracle Attacks", USENIX Security 2021 (to appear), by Julia Len, Paul Grubbs, and Thomas Ristenpart.
This commit is contained in:
@@ -5,11 +5,14 @@
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
// Package agessh provides age.Identity and age.Recipient implementations of
|
||||
// types "ssh-rsa" and "ssh-ed25519", which allow reusing existing SSH key files
|
||||
// for encryption with age-encryption.org/v1.
|
||||
// types "ssh-rsa" and "ssh-ed25519", which allow reusing existing SSH keys for
|
||||
// encryption with age-encryption.org/v1.
|
||||
//
|
||||
// These should only be used for compatibility with existing keys, and native
|
||||
// X25519 keys should be preferred otherwise.
|
||||
// These recipient types should only be used for compatibility with existing
|
||||
// keys, and native X25519 keys should be preferred otherwise.
|
||||
//
|
||||
// Note that these recipient types are not anonymous: the encrypted message will
|
||||
// include a short 32-bit ID of the public key,
|
||||
package agessh
|
||||
|
||||
import (
|
||||
@@ -346,6 +349,12 @@ func (i *Ed25519Identity) Unwrap(block *age.Stanza) ([]byte, error) {
|
||||
}
|
||||
|
||||
// aeadEncrypt and aeadDecrypt are copied from package age.
|
||||
//
|
||||
// They don't limit the file key size because multi-key attacks are irrelevant
|
||||
// against the ssh-ed25519 recipient. Being an asymmetric recipient, it would
|
||||
// only allow a more efficient search for accepted public keys against a
|
||||
// decryption oracle, but the ssh-X recipients are not anonymous (they have a
|
||||
// short recipient hash).
|
||||
|
||||
func aeadEncrypt(key, plaintext []byte) ([]byte, error) {
|
||||
aead, err := chacha20poly1305.New(key)
|
||||
|
||||
Reference in New Issue
Block a user