簡體   English   中英

為什么在PHP中加密的東西與在Ruby中加密的相同字符串不匹配?

[英]Why does something encrypted in PHP not match the same string encrypted in Ruby?

這是我的要求:

我需要使用AES加密(包括隨機iv)在PHP中加密字符串,對其進行Base64編碼,然后對其進行URL編碼,以便將其作為URL參數傳遞。

我試圖在PHP和Ruby中獲得相同的結果,但我不能使它工作。

這是我的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));

這是我的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)

令人憤怒的是,兩個代碼示例都產生相似但不相同的哈希值。 例如,上面的代碼生成(base64編碼,而不是URL編碼):

PHP: /aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=

Ruby: /aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=

誰能解釋我在這里做錯了什么? 此外,我更容易(因為我是一個Ruby人,通常不是PHP)修復Ruby代碼而不是PHP代碼。 因此,如果您想在Ruby中提供與PHP配對良好的解決方案,我將非常感激。

哦,而且,在生產中,iv確實是隨機的,但是對於這個例子,我將它設置為永久相同,以便可以比較輸出。

編輯:

感謝Eugen Rieck的回答,我找到了解決方案。 Ruby填充塊,但PHP沒有,你必須手動完成。 將PHP代碼更改為以下內容,您將獲得上述Ruby代碼可以輕松解密的加密字符串:

$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);
}

事實證明,這很容易:填充是罪魁禍首。

AES是塊密碼,因此它適用於固定大小的塊。 這意味着,最后一個塊將全部填充,並且,您知道,標准的好處是,有很多可供選擇。 PHP使用零填充,您將不得不查看AESCrypt以找出Ruby使用的內容。

各種JS AES庫和PHP存在同樣的問題。 我們總是在做自己的填充,因為這已經讓我陷入了血紅色的憤怒很多次。

當然,這解釋了為什么第一部分(攜帶信息)是相同的,而第二部分(攜帶填充)是不同的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM