Comment crypter de nombreux fichiers avec AES-GCM, sans exécuter la fonction de dérivation de clé à chaque fois?
Question liée: AES cryptant plusieurs fichiers
Avec a password
, j'ai 100k fichiers à crypter. (Peut-être 100k fichiers aujourd'hui; ou peut-être 50k aujourd'hui, 10k demain et 40k fichiers la semaine prochaine).
Jusqu'à présent, j'ai fait ceci (pseudo-code):
for each file: plaintext = file.read() nonce = getrandom(bytes=16) key = KDF_PBKDF2(password, salt=nonce, count=1000000) # very slow for each file! ciphertext, tag = AES_GCM_cipher(key, nonce=nonce).encrypt(plaintext) write to disk: nonce | ciphertext | tag
et pour décrypter le fichier crypté
nonce, ciphertext, tag = file.read() key = KDF_PBKDF2(password, salt=nonce, count=1000000) # very slow for each file! plaintext = AES_GCM_cipher(key, nonce=nonce).decrypt(ciphertext)
Evidemment, ce n'est pas optimal, puisque j'exécute la fonction KDF pour chaque fichier, et c'est lent!
J'ai pensé à cette solution:
# do this ONLY ONCE for each encryption session: salt = getrandom(bytes=16) key = KDF_PBKDF2(password, salt=salt, count=1000000) # run only once for each file: plaintext = file.read() nonce = getrandom(bytes=16) ciphertext, tag = AES_GCM_cipher(key, nonce=nonce).encrypt(plaintext) write to disk: salt | nonce | ciphertext | tag
mais cela a l'inconvénient de devoir ajouter 16 octets supplémentaires (
salt
) au début de chaque fichier chiffré. Est-ce une pratique courante?Et surtout, il présente l'inconvénient suivant lors du décryptage:
for each encrypted file: salt, nonce, ciphertext, tag = file.read() # since salt may be different for each file # we have to run: key = KDF_PBKDF2(password, salt=salt, count=1000000) # very slow for each file! ...
Puisque
salt
c'est au début de chaque fichier crypté, cela signifie que nous devons exécuter la fonction KDF ... pour chaque fichier crypté que nous voulons décrypter! Ce sera très lent.Nous pourrions les mettre en cache
cache[salt] = key
, de sorte que si nous retrouvons la même chosesalt
, nous avons déjà lekey
, mais je ne suis pas sûr que ce soit une solution élégante.
Question: quel schéma utiliser pour crypter 100k fichiers (en une seule passe ou en plusieurs sessions) avec un mot de passe avec AES-GCM?
Réponses
Un sérieux au sujet de la cryptographie basée sur les mots de passe ne doit pas s'éloigner KDF_PBKDF2
, mais courir vers Argon2 (ou scrypt s'il est plus facilement disponible)! L'exploitation de Bitcoin a (en 2020) montré que les ASIC dédiés exécutant SHA-256 à un taux élevé (220 TH / s) et une efficacité (15 pJ / H) peuvent devenir disponibles dans le commerce pour quelques milliers de dollars américains. Cela rend intenable de s'appuyer sur PBKDF2-HMAC exécuté sur du matériel standard pour étirer les mots de passe choisis par l'utilisateur dans les applications de haute sécurité.
La méthode proposée a une caractéristique: elle salt
est commune à plusieurs fichiers si, et pour le large aléatoire salt
seulement si, ils ont été chiffrés ensemble. Il s'agit à la fois d'une fuite d'informations éventuellement indésirable et d'un moyen de résoudre l'inconvénient mentionné: le code d'étirement du mot de passe utilisé dans le décryptage peut maintenir un cache RAM de ( salt
, key
) paires.
J'envisagerais de remplacer AES-GCM par AES-GCM-SIV , pour la tranquillité d'esprit en cas de bégaiement du RNG, mais en gardant à l'esprit que deux passes sont nécessaires sur les données.
Autant je recommande de couper le dernier octet quand cela compte (par exemple lorsque les données se trouvent sur un code à barres ou passent par un moyen de communication lent ou / et épuisant la batterie), je ne recommanderai pas d'économiser salt
et de nonce
taille dans le cryptage de fichier comme nous sommes dans les années 80.