我想在C#中加密一些(cookie)數據,然後用PHP解密它。我選擇了使用Rijndael加密。我幾乎可以工作,除了部分文本被解密!我開始從這個例子的工作:Decrypt PHP encrypted string in C#C#加密到PHP解密
這裏的文本(JSON),我加密(敏感信息已刪除):
{"DisplayName":"xxx", "Username": "yyy", "EmailAddress":"zzz"}
所以我登錄到它創建/ C#的應用程序從存儲編碼的cookie Key和IV,然後重定向到應該解密/讀取cookie的PHP應用程序。當我解密的cookie,它出來是這樣的:
{"DisplayName":"xxx","F�A ;��HP=D�������4��z����ť���k�#E���R�j�5�\�t. t�D��"
UPDATE:我已經得到一點點進一步,這是現在的結果
string(96) "{"DisplayName":"xxx","Username":"yyy","EmailAddress"�)ق��-�J��k/VV-v� �9�B`7^"
正如你所看到的,它開始解密它,但然後得到搞砸了...
當解密字符串它出來正確(與填充,我有一個函數要刪除Ë填充),但如果我一個字符改變測試字符串,我得到一次垃圾:
B�nHL�Ek �¿?�UΣlO����OЏ�M��NO/�f.M���Lƾ�CC�Y>F��~�qd�+
這裏的C#代碼,我用它來生成隨機密鑰和IV:
UPDATE:我只是用靜態密鑰/ IV現在,在這裏,他們是:
Key: lkirwf897+22#bbtrm8814z5qq=498j5
IV: 741952hheeyy66#[email protected]
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
symmetricKey.Padding = PaddingMode.Zeros;
symmetricKey.Mode = CipherMode.CBC;
string key = Convert.ToBase64String(symmetricKey.Key);
string IV = Convert.ToBase64String(symmetricKey.IV);
然後,我將密鑰和IV保存到數據庫中,以便以後進行編碼/解碼。
這是完全加密類:
public static class Encryption
{
public static string Encrypt(string prm_text_to_encrypt, string prm_key, string prm_iv)
{
var sToEncrypt = prm_text_to_encrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Encoding.ASCII.GetBytes(prm_key);
var IV = Encoding.ASCII.GetBytes(prm_iv);
//var key = Convert.FromBase64String(prm_key);
//var IV = Convert.FromBase64String(prm_iv);
var encryptor = rj.CreateEncryptor(key, IV);
var msEncrypt = new MemoryStream();
var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
var toEncrypt = Encoding.ASCII.GetBytes(sToEncrypt);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
var encrypted = msEncrypt.ToArray();
return (Convert.ToBase64String(encrypted));
}
public static string Decrypt(string prm_text_to_decrypt, string prm_key, string prm_iv)
{
var sEncryptedString = prm_text_to_decrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Encoding.ASCII.GetBytes(prm_key);
var IV = Encoding.ASCII.GetBytes(prm_iv);
//var key = Convert.FromBase64String(prm_key);
//var IV = Convert.FromBase64String(prm_iv);
var decryptor = rj.CreateDecryptor(key, IV);
var sEncrypted = Convert.FromBase64String(sEncryptedString);
var fromEncrypt = new byte[sEncrypted.Length];
var msDecrypt = new MemoryStream(sEncrypted);
var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return (Encoding.ASCII.GetString(fromEncrypt));
}
public static void GenerateKeyIV(out string key, out string IV)
{
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
rj.GenerateKey();
rj.GenerateIV();
key = Convert.ToBase64String(rj.Key);
IV = Convert.ToBase64String(rj.IV);
}
}
下面是我使用對數據進行解密的PHP代碼:
function decryptRJ256($key,$iv,$string_to_decrypt)
{
$string_to_decrypt = base64_decode($string_to_decrypt);
$rtn = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string_to_decrypt, MCRYPT_MODE_CBC, $iv);
//$rtn = rtrim($rtn, "\0\4");
$rtn = unpad($rtn);
return($rtn);
}
function unpad($value)
{
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
//apply pkcs7 padding removal
$packing = ord($value[strlen($value) - 1]);
if($packing && $packing < $blockSize){
for($P = strlen($value) - 1; $P >= strlen($value) - $packing; $P--){
if(ord($value{$P}) != $packing){
$packing = 0;
}//end if
}//end for
}//end if
return substr($value, 0, strlen($value) - $packing);
}
$ky = 'lkirwf897+22#bbtrm8814z5qq=498j5'; // 32 * 8 = 256 bit key
$iv = '741952hheeyy66#[email protected]'; // 32 * 8 = 256 bit iv
$enc = $_COOKIE["MyCookie"];
$dtext = decryptRJ256($ky, $iv, $enc);
var_dump($dtext);
我對這個部分有點不確定,因爲所有的我見過的示例代碼只是將base64編碼的字符串直接傳遞給解密器,但在我的示例中,我必須在通過base64_decode之前對其進行解碼,否則會出現密鑰和IV長度不正確的錯誤。
UPDATE:我使用PHP所需格式的ASCII密鑰。如果我從RijndaelManaged類生成密鑰,他們不會在PHP端工作,但我可以使用已知在PHP端工作的密鑰並在RijndaelManaged C#端使用它們。
如果我遺漏了任何相關信息,請讓我知道。 TIA!
我似乎記得,你可以得到這個,如果你提供解密IV是錯誤 – pm100 2012-08-08 22:06:03
是否不工作IV? – 2012-08-08 22:07:45
如果我不包含IV,它不起作用。 – solidau 2012-08-08 22:18:17