Oto moje wymagania:Dlaczego coś zaszyfrowane w PHP nie pasuje do tego samego ciągu zaszyfrowanego w Ruby?
Potrzebuję zaszyfrować ciąg znaków w PHP przy użyciu szyfrowania AES (w tym losowego iv), zakodować go w Base64, a następnie zakodować go w URL, aby mógł zostać przekazany jako parametr adresu URL.
Próbuję uzyskać taki sam wynik zarówno w PHP jak i Ruby, ale nie mogę sprawić, żeby działał.
Oto mój kod PHP:
function encryptData($data,$iv){
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv_size = mcrypt_enc_get_iv_size($cipher);
if (mcrypt_generic_init($cipher, 'g6zys8dlvvut6b1omxc5w15gnfad3jhb', $iv) != -1){
$cipherText = mcrypt_generic($cipher,$data);
mcrypt_generic_deinit($cipher);
return $cipherText;
}
else {
return false;
}
}
$data = 'Mary had a little lamb';
$iv = '96b88a5f0b9efb43';
$crypted_base64 = base64_encode(encryptData($data, $iv));
Oto mój kod Ruby:
module AESCrypt
def AESCrypt.encrypt(data, key, iv)
aes = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
aes.encrypt
aes.key = key
aes.iv = iv
aes.update(data) + aes.final
end
end
plaintext = "Mary had a little lamb"
iv = "96b88a5f0b9efb43"
@crypted = AESCrypt::encrypt(plaintext, "g6zys8dlvvut6b1omxc5w15gnfad3jhb", iv)
@crypted_base64 = Base64.encode64(@crypted)
@crypted_base64_url = CGI.escape(@crypted_base64)
irytujące jest to, że obie próbki kodu produkować podobny ale nie identyczne skrótów. Na przykład, powyższy kod generuje (base64 zakodowane, a nie URL zakodowane):
PHP: /aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=
Ruby /aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=
może ktoś wyjaśnić, co robię źle tutaj? Ponadto łatwiej mi (ponieważ jestem facetem z Ruby, a nie PHP) naprawić kod Ruby zamiast kodu PHP. Jeśli więc chciałbyś zapewnić rozwiązanie w języku Ruby, które dobrze łączyłoby się z PHP, byłbym bardzo wdzięczny.
Aha, a także, w produkcji iv naprawdę będzie losowa, ale dla tego przykładu ustawiam ją tak, aby była na stałe taka sama, aby można było porównywać dane wyjściowe.
EDIT:
Dzięki za odpowiedź Eugen RIECK, przyjechałem w roztworze. Ruby blokuje bloki, ale PHP tego nie robi i musisz to zrobić ręcznie. Zmień kod PHP do następującego, a otrzymasz zaszyfrowane ciągi że powyższy kod Ruby można łatwo rozszyfrować:
$iv = '96b88a5f0b9efb43';
$data = 'Mary had a little lamb';
function encryptData($data,$iv){
$key = 'g6zys8dlvvut6b1omxc5w15gnfad3jhb';
$padded_data = pkcs5_pad($data);
$cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_data, MCRYPT_MODE_CBC, $iv);
return $cryptogram;
}
function pkcs5_pad ($text, $blocksize){
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
Nie mogę pomóc w rozwiązaniu, ale myślę, że może to mieć coś wspólnego z blokowaniem klocków (ponieważ ciągi wyjściowe są takie same dla pierwszych n znaków). Możesz spróbować dodać dopełnienie do zwykłego tekstu ręcznie w oparciu o rozmiar bloku. – Mikk
Twój kod Ruby wywołuje AES-256. Twój kod PHP wywołuje AES-128. Jesteś pewien, że to prawda? Twoja IV jest wyraźnie dla 128 ... – Charles
@Charles Nie rozumiem tego też. Ale to jedyny sposób, w jaki działa.Przełączenie PHP w celu wywołania AES-256 powoduje, że Ruby daje "zły odszyfrować" błąd z OpenSSL. (Zobacz wątek wymieniony w moim komentarzu do odpowiedzi poniżej, omawia to dalej). Również [this] (http://www.chilkatsoft.com/p/php_aes.asp) dostarcza pełnego wyjaśnienia dziwności szyfrowania PHP. Myślę, że to rozwiąże twoje pytanie. – John