Używam języka Ruby o nazwie Open SSL bindings do szyfrowania AES-256. Mogę zaszyfrować niepusty ciąg. Jednak podczas próby zaszyfrowania pustego ciągu Ruby podnosi wyjątek, narzucając, że dane nie mogą być puste. Jak mogę zaszyfrować pusty ciąg za pomocą powiązań OpenSSL Ruby?Szyfruj pusty ciąg znaków
kod do odtworzenia problemu
require "openssl"
KEY = OpenSSL::Cipher::Cipher.new("aes-256-cbc").random_key
def encrypt(plaintext)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.encrypt
iv = cipher.random_iv
cipher.iv = iv
cipher.key = KEY
ciphertext = cipher.update(plaintext) # <- ArgumentError here
ciphertext << cipher.final
[iv, ciphertext]
end
def decrypt(iv, ciphertext)
cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
cipher.decrypt
cipher.iv = iv
cipher.key = KEY
plaintext = cipher.update(ciphertext)
plaintext << cipher.final
plaintext
end
p decrypt(*encrypt("foo")) # "foo"
p decrypt(*encrypt(""))
# /tmp/foo.rb:11:in `update': data must not be empty (ArgumentError)
# from /tmp/foo.rb:11:in `encrypt'
# from /tmp/foo.rb:27:in `<main>'
Wersje
- ruby-2.2.2p95
- OpenSSL :: wersja jest "1.1.0"
- Microsoft SQL Server 2014 (12.0.2000.8)
Dlaczego chcę szyfrować puste ciągi?
Piszę program ETL do migracji danych z jednej bazy danych do bazy danych SqlServer. Niektóre kolumny ze źródłowej bazy danych muszą być zaszyfrowane przed zapisaniem ich w docelowej bazie danych. Kolumny źródłowe mogą zawierać dowolne dane, w tym puste ciągi. Kolumny docelowe są zwykle niedozwolone. Kolumny docelowe zostaną odszyfrowane przez kod .net.
Cel nr 1: Brak informacji o zaszyfrowanym polu, w tym o tym, czy istnieje, czy nie, powinien być możliwy do odzyskania bez prawidłowego odszyfrowania go. Zaszyfrowany pusty ciąg powinien być nieodróżnialny od innych zaszyfrowanych danych.
Cel # 2: kod .net, który odszyfruje te wartości, nie musi specjalnie traktować pustych ciągów.
Jeśli mogę uzyskać openssl do szyfrowania pustych ciągów, osiągnę oba te cele.
Obejście - Nie szyfrować pustych strun
ja po prostu nie mógł szyfrować pustych strun, przekazując je przez.
def encrypt(plaintext)
return plaintext if plaintext.empty?
...
end
def decrypt(iv, ciphertext)
return ciphertext if ciphertext.empty?
...
end
ten ma wady, gdyż informacje odsłaniających, a także wymaga kodu współpracującego być zapisane na boku NET.
Obejście - Dodaj pewnej stałej do tekstu jawnego
mogę dodać jakiś stały ciąg tekstu jawnego przed szyfrowaniem i usunąć go po odszyfrowaniu:
PLAINTEXT_SUFFIX = " "
def encrypt(plaintext)
plaintext += PLAINTEXT_SUFFIX
...
end
def decrypt(iv, ciphertext)
...
plaintext.chomp(PLAINTEXT_SUFFIX)
end
Ukrywa czy dane istnieje, czy nie, ale nadal wymaga współpracującego kodu .net.
OpenSSL obsługuje dopełnienie PKCS # 7, więc to powinno działać. Jest to prawdopodobnie lepiej dopasowane do raportu o błędzie. Przy okazji, czy próbowałeś po prostu pominąć 'cipher.update', jeśli tekst jawny jest pusty? "szyfrowanie.final" może być w tym przypadku wystarczające. –
@ArtjomB. Próbowałem pominąć wywołanie aktualizacji # Cipher. To nie zadziałało, gdy próbowałem go wcześniej z powodu błędu ID10T, niż nie zauważyłem w tym czasie. Okazuje się, że to rozwiązanie. Czy mógłbyś dodać to jako odpowiedź? –
Możesz dodać sam. Nie mam pojęcia o rubinach i nie chcę się uczyć w tym szczególnym czasie. :) –