Dưới đây là các yêu cầu của tôi:Tại sao một cái gì đó được mã hóa trong PHP không khớp với cùng một chuỗi được mã hóa trong Ruby?
Tôi cần mã hóa chuỗi bằng PHP sử dụng mã hóa AES (bao gồm iv ngẫu nhiên), Base64 mã hóa nó, sau đó mã hóa URL để nó có thể được truyền dưới dạng thông số URL.
Tôi đang cố gắng để có được kết quả tương tự trong cả PHP và Ruby, nhưng tôi không thể làm cho nó hoạt động.
Đây là mã PHP của tôi:
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));
Đây là mã Ruby của tôi:
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)
Điều phẩn nộ là cả hai mẫu mã sản xuất tương tự nhưng không băm giống hệt nhau. Ví dụ, đoạn mã trên tạo (mã hóa base64, không URL mã hóa):
PHP: /aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=
Ruby: /aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=
bất cứ ai có thể giải thích những gì tôi đang làm sai ở đây? Ngoài ra, nó dễ dàng hơn cho tôi (vì tôi là một người Ruby, không phải PHP thường) để sửa mã Ruby thay vì mã PHP. Vì vậy, nếu bạn muốn cung cấp một giải pháp trong Ruby mà sẽ kết hợp tốt với PHP, tôi sẽ đánh giá cao nhất. Oh, và ngoài ra, trong sản xuất iv thực sự sẽ là ngẫu nhiên, nhưng đối với ví dụ này tôi đặt nó là vĩnh viễn giống nhau để có thể so sánh đầu ra.
EDIT:
Nhờ câu trả lời Eugen Rieck, tôi đến một giải pháp. Ruby sẽ chặn các khối, nhưng PHP thì không, và bạn phải thực hiện nó theo cách thủ công. Thay đổi mã PHP để sau, và bạn sẽ có được chuỗi mã hóa mà trên của Ruby mã có thể giải mã một cách dễ dàng:
$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);
}
Không thể giúp giải pháp nhưng tôi nghĩ rằng điều này có thể có liên quan đến khối đệm (vì chuỗi đầu ra giống nhau cho các ký tự đầu tiên). Bạn có thể muốn thử thêm phần đệm vào văn bản thuần túy theo cách thủ công dựa trên kích thước khối. – Mikk
Mã Ruby của bạn đang gọi AES-256. Mã PHP của bạn đang gọi AES-128. Bạn có chắc chắn điều này là chính xác? IV của bạn rõ ràng là 128 ... – Charles
@Charles Tôi cũng không hiểu điều này. Tuy nhiên, đây là cách duy nhất mọi thứ hoạt động.Chuyển đổi PHP để gọi AES-256 làm cho Ruby đưa ra một lỗi "giải mã xấu" từ OpenSSL. (Xem chủ đề được liệt kê trong bình luận của tôi cho câu trả lời dưới đây, nó thảo luận thêm về điều này) Ngoài ra [this] (http://www.chilkatsoft.com/p/php_aes.asp) cung cấp giải thích đầy đủ về các kỳ quặc mã hóa của PHP. Tôi nghĩ rằng nó làm sáng tỏ câu hỏi của bạn. – John