Jak zaszyfrować wiele plików za pomocą AES-GCM, bez uruchamiania funkcji wyprowadzania klucza za każdym razem?
Powiązane pytanie: szyfrowanie AES wielu plików
W przypadku password
mam 100 000 plików do zaszyfrowania. (Może dziś 100 tys. Plików, dziś może 50 tys., Jutro 10 tys. I w następnym tygodniu 40 tys.).
Do tej pory zrobiłem to (pseudokod):
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
i odszyfrować zaszyfrowany plik
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)
Oczywiście nie jest to optymalne, ponieważ uruchamiam funkcję KDF dla każdego pliku, a to jest powolne!
Myślałem o tym rozwiązaniu:
# 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
ale ma to tę wadę, że
salt
na początku każdego zaszyfrowanego pliku trzeba wstawić 16 dodatkowych bajtów ( ). Czy to powszechna praktyka?A przede wszystkim ma tę wadę podczas odszyfrowywania:
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! ...
Ponieważ
salt
znajduje się na początku każdego zaszyfrowanego pliku, oznacza to, że musimy uruchomić funkcję KDF ... dla każdego zaszyfrowanego pliku, który chcemy odszyfrować! Będzie to bardzo powolne.Moglibyśmy umieścić je w pamięci podręcznej
cache[salt] = key
, tak, że jeślisalt
ponownie znajdziemy to samo , to już mamykey
, ale nie jestem pewien, czy jest to eleganckie rozwiązanie.
Pytanie: którego schematu użyć do zaszyfrowania 100k plików (w jednym przebiegu lub w wielu sesjach) za pomocą hasła z AES-GCM?
Odpowiedzi
Jeden poważny w kwestii kryptografii opartej na hasłach nie może odejść KDF_PBKDF2
, ale biec do Argon2 (lub przeszyfrować, jeśli jest łatwiej dostępny)! Wydobywanie bitcoinów pokazało (w 2020 r.), Że dedykowane układy ASIC działające w trybie SHA-256 z wysoką szybkością (220 TH / s) i wydajnością (15 pJ / h) mogą stać się dostępne na rynku za kilka tysięcy dolarów. To sprawia, że nie można polegać na PBKDF2-HMAC działającym na standardowym sprzęcie do rozciągania haseł wybranych przez użytkownika w aplikacjach o wysokim poziomie bezpieczeństwa.
Proponowana metoda ma jedną cechę: salt
jest wspólna dla kilku plików, a dla szerokiego losowego salt
tylko wtedy, gdy zostały one zaszyfrowane razem. Jest to zarówno prawdopodobnie niechciany wyciek informacji, jak i sposób rozwiązania wspomnianej wady: kod rozciągający hasło używany do deszyfrowania może utrzymywać pamięć podręczną RAM składającą się z ( salt
, key
) par.
Rozważałbym zastąpienie AES-GCM AES-GCM-SIV , dla spokoju ducha w przypadku zacinania się RNG, ale należy pamiętać, że potrzebne są dwa przejścia przez dane.
Chociaż zalecam przycinanie ostatniego bajtu, gdy się liczy (np. Gdy dane znajdują się na kodzie kreskowym lub przechodzą przez powolny lub wyczerpujący baterię nośnik komunikacyjny), nie polecam oszczędzania salt
i nonce
rozmiaru w szyfrowaniu plików, tak jak my są w latach 80.