2010-11-18 68 views
3

我對加密知之甚少,但是我能夠在AES中使用PHP ...。下面是我使用的一對夫婦功能:PHP AES加密...不知道我在做什麼

function aes_decrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
     $key[$a%16]=chr(ord($key[$a%16])^ord($ky[$a])); 
    $mode = MCRYPT_MODE_ECB; 
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv(@mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
    return rtrim($dec,((ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord(substr($dec,strlen($dec)-1,1))):null)); 
} 

function aes_encrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
     $key[$a%16]=chr(ord($key[$a%16])^ord($ky[$a])); 
    $mode=MCRYPT_MODE_ECB; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val)/16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv(mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
} 

這些稍微從comment on the PHP documentation page for mcrypt修改。 (我從dev_urandom改爲蘭特,因爲我是在Windows中,其中dev_urandom不可用。)

反正我在這個函數中使用的關鍵是這樣定義的:

define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9")); 

我打電話給我像這樣的功能:現在

echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));

,所得十六進制字符串的前16個字節(32位)都很好。接下來的16個字節與預期不符。

請參閱我將這些數據發佈到外部Web服務,然後解密它。我(不幸的)不能給我一個測試案例我沒有發放我的加密密鑰和數據。對此我非常抱歉,但我希望熟悉mcrypt的人可以看看這個,並告訴我我做錯了什麼。

再次,對於缺乏堅實的測試案例感到抱歉,但我非常感謝您可以給予的任何幫助!

編輯:看來我的提供者,我張貼到使用空四。按照Rook的建議,我已經切換到CBC模式,並刪除了與密鑰相關的不必要的代碼。這裏是我的新功能:

function aes_decrypt($val,$key) 
{ 
    $mode = MCRYPT_MODE_CBC; 
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, null); 
    return rtrim($dec,((ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord(substr($dec,strlen($dec)-1,1))):null)); 
} 

function aes_encrypt($val,$key) 
{ 
    $mode = MCRYPT_MODE_CBC; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val)/16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, null); 
} 

回答

5

這個加密服務很可能使用了像CBC這樣的不同的分組密碼模式。如果在CBC模式下使用null iv,則ECB和CBC的第一個塊(本例中爲16個字節)將產生相同的密文。出於任何原因,任何人都不應該使用ECB模式。

下面是一個例子ECB模式的加密消息:

alt text

+0

您的意見對我很有幫助,我很欣賞上次的修改,儘管如果沒有它,您絕對是正確的。在對ECB和CBC的工作做了一些研究之後,我轉向了CBC。但是,我無法獲得能夠與我的在線服務一起工作的輸出,而我無法控制該服務。我已經設置了一個空IV(是的,令人恐懼),並且第一個塊排列成所需要的,但第二個塊仍然不匹配。我正在嘗試其他模式,但任何建議你可以給我最有幫助。我很欣賞你的時間和迴應。 – Brad 2010-11-19 14:32:32

+0

@Brad Your String2KeyFunction,(for循環XoR'ing空值)並不常見。如果他們使用不同的string2key,那麼它可能會導致問題。雖然如果你使用的密鑰小於16字節,那麼它只是一個明文密鑰,這是一個糟糕的設計,但也是一個普通的密鑰。對第一篇文章感到抱歉,那是不需要的。 – rook 2010-11-19 16:00:26

+0

@Rook,事實證明,無論如何,位並不重要,因爲我傳遞了正確長度的二進制密鑰。我認爲只存在處理奇數段密鑰。我已經刪除它,只是使用預定義的鍵。我相信關鍵部分是正確的,因爲第一個塊匹配。只有第二個塊沒有。我將在上面編輯我的帖子以反映我目前的功能。 – Brad 2010-11-19 17:34:04

1

我和其中編碼iPhone應用程序,並且其中利用上述方法來加密和解密數據我的大學。但是當我加密要從他的iPhone讀取的數據時,我們發現了一個問題。 iPhone使用PKCS7填充。上面的代碼是添加額外的填充,這將導致iPhone解密方法失敗。我們修改了代碼以解決當前問題:

public static function aes128Encrypt($key,$val) 
{ 
    $mode = MCRYPT_MODE_CBC; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $blocksize= mcrypt_get_block_size($enc,$mode); 
    $stringLength = strlen($val); 
    $paddingLength =$blocksize-($stringLength%$blocksize); 
    $val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength)); 
    return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")); 
}