Istnieje kilka subtelnych rzeczy, które sprawiają, że to zawiedzie. Najważniejszy - nie określasz IV w kodzie, więc losowa wartość zostanie wygenerowana dla ciebie. Zauważylibyście, że w ten sposób nie można nawet odszyfrować swojego zaszyfrowanego tekstu w tym samym języku programowania.
Musisz więc podać jednoznacznie IV dla obu implementacji. Ale zanim pokażę Ci kod, kilka rad:
Key generacja:
Blowfish działa na 64 bitowych bloków, jego rozmiar klucza różna, ale OpenSSL (który obecnie uprawnienia zarówno szyfr Ruby i node.js' implementacja) domyślnie używa 128 bitów, czyli 16 bajtów.
Twój klucz narusza dwie zasady - pierwszą: po prostu jest za długa. Jest to szesnastkowa reprezentacja skrótu SHA-1, która wynosi 20 bajtów * 2 = 40 bajtów zamiast 16. W większości przypadków jest to w porządku, ponieważ implementacja obcina odpowiednio wartości, ale to jest coś, co powinno być , a nie zależne. na.
Drugi błąd, znacznie surowszy, polega na tym, że zamiast surowych bajtów używa się reprezentacji w postaci heksadecymalnej: duży problem bezpieczeństwa! Znaki szesnastkowe nie są wcale losowe, więc w efekcie redukujesz entropię danych wejściowych do połowy długości (ponieważ bazowe bajty były losowe).
bezpieczny sposób do generowania kluczy losowych używa OpenSSL :: Losowa
key = OpenSSL::Random.random_bytes(cipher_key_len)
Trzeci błąd jest, aby zachować swój klucz zakodowany w źródłach. To zły pomysł. Należy przynajmniej przechowywać go w innym miejscu w systemie plików, gdzie dostęp jest ściśle ograniczony. Zobacz także my answer na kolejne pytanie.Klucz powinien być przechowywany poza pasmem i ładowany dynamicznie w aplikacji.
Cipher:
Blowfish starzeje. Nadal jest uważany za nieprzerwany w tym sensie, że brutalne wymuszanie go jest jedynym sposobem na jego złamanie. Ale przestrzeń wyszukiwania o rozmiarze 2^64 nie jest poza zasięgiem zaradnych atakujących. Powinieneś więc przejść do AES.
Dopełnienie:
klocki OpenSSL wykorzystujące PKCS5Padding (znany również jako PKCS7Padding) domyślnie. Ruby czerpie z tego zyski, a mój zakład, node.js, również to wykorzystuje - więc powinieneś być na to bezpieczny.
Teraz do rozwiązania roboczego. Musimy wygenerować IV, Blowfish wymaga 64-bitowego - 8 bajtów. Będziesz potrzebował rbytes, aby uzyskać bezpieczne liczby losowe w węźle. IV może być zakodowana na stałe w twoich źródłach (to informacja publiczna, bez wpływu na bezpieczeństwo) - ale musi być taka sama po obu stronach. Powinieneś wstępnie wygenerować wartość i użyć jej zarówno dla node.js, jak i Ruby.
/*node.js*/
var rbytes = require('rbytes');
var iv = rbytes.randomBytes(8);
/*see advice above - this should be out-of-band*/
var key = rbytes.randomBytes(16);
var encrypted = "";
var cipher = crypto.createCipheriv('bf-cbc', key, iv);
encrypted += cipher.update('text');
encrypted += cipher.final('hex');
Teraz części Ruby:
require 'openssl'
c = OpenSSL::Cipher::Cipher.new("bf-cbc")
c.encrypt
# should be out-of-band again
c.key = OpenSSL::Random.random_bytes(16)
# may be public but has to be the same for Ruby and node
iv = OpenSSL::Random.random_bytes(8)
c.iv = iv
e = c.update("text")
e << c.final
puts e.unpack('H*')[0]
I w Ruby pozornie 1.8.7 wyjść \ 347 \ 232 \ 213 \ 006 \ 250; \ 207 \ 302 podczas gdy 1.9.2 wyprowadza \ xE7 \ x9A \ x8B \ x06 \ xA8; \ x87 \ xC2 –