Qui ci sono le mie esigenze:Perché una cosa criptata in PHP non corrisponde alla stessa stringa crittografata in Ruby?
ho bisogno di cifrare una stringa in PHP utilizzando la crittografia AES (tra cui un iv casuale), Base64 codificare, quindi codifica URL in modo che esso può essere passato come parametro URL.
Sto cercando di ottenere lo stesso risultato in entrambi PHP e Ruby, ma non riesco a farlo funzionare.
Ecco il mio codice 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));
Qui è il mio codice 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)
La cosa irritante è che entrambi i campioni di codice producono simile ma non gli hash identici. Ad esempio, il codice di cui sopra genera (Base64 codificati, non URL codificato):
PHP: /aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=
Rubino: /aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=
Qualcuno può spiegare che cosa sto facendo male qui? Inoltre, è più facile per me (dal momento che sono un ragazzo Ruby, non PHP di solito) per risolvere il codice Ruby piuttosto che il codice PHP. Quindi, se volessi fornire una soluzione in Ruby che si accoppiasse bene con PHP, sarei molto riconoscente.
Oh, e anche, nella produzione iv davvero sarà casuale, ma in questo esempio ho impostato per essere definitivamente stesso modo che uscita potrebbe essere confrontato.
EDIT:
Grazie alla risposta di Eugen Rieck, sono arrivato a una soluzione. Ruby blocca i blocchi, ma PHP non lo fa, e devi farlo manualmente. Modificare il codice PHP per quanto segue, e si ottiene stringhe criptate che quanto sopra Rubino codice può decifrare facilmente:
$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);
}
non aiuta in soluzione, ma penso che questo potrebbe avere qualcosa a che fare con il blocco imbottitura (dal momento che le stringhe di output sono gli stessi per i primi n caratteri). Potresti provare a aggiungere padding al testo normale manualmente in base alla dimensione del blocco. – Mikk
Il tuo codice Ruby sta invocando AES-256. Il tuo codice PHP sta invocando AES-128. Sei sicuro che sia corretto? Il tuo IV è chiaramente per 128 ... – Charles
@Charles Non capisco neanche questo. Eppure, questo è l'unico modo in cui funzionano le cose.Passando da PHP a invocare AES-256, Ruby genera un errore di "decrittografia errata" da OpenSSL. (Vedi la discussione elencata nel mio commento alla risposta qui sotto, ne discute ulteriormente) Anche [questo] (http://www.chilkatsoft.com/p/php_aes.asp) fornisce una spiegazione completa delle stranezze di crittografia di PHP. Penso che chiarisca la tua domanda. – John