【发布时间】:2011-12-28 07:18:06
【问题描述】:
我正在尝试在 C# 和 PHP 之间同步我的加密和解密方法,但似乎出了点问题。
在 Windows Phone 7 SDK 中,您可以使用 AESManaged 来加密您的数据
我使用以下方法:
public static string EncryptA(string dataToEncrypt, string password, string salt)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
//Generate a Key based on a Password, Salt and HMACSHA1 pseudo-random number generator
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
//Create AES algorithm with 256 bit key and 128-bit block size
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // rfc2898.GetBytes(aes.BlockSize / 8);
// to check my results against those of PHP
var blaat1 = Convert.ToBase64String(aes.Key);
var blaat2 = Convert.ToBase64String(aes.IV);
//Create Memory and Crypto Streams
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
//Encrypt Data
byte[] data = Encoding.Unicode.GetBytes(dataToEncrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
//Return Base 64 String
string result = Convert.ToBase64String(memoryStream.ToArray());
return result;
}
finally
{
if (cryptoStream != null)
cryptoStream.Close();
if (memoryStream != null)
memoryStream.Close();
if (aes != null)
aes.Clear();
}
}
我解决了生成密钥的问题。 Key 和 IV 与 PHP 端的类似。但是加密的最后一步出错了。
这是我的 PHP 代码
<?php
function pbkdf2($p, $s, $c, $dk_len, $algo = 'sha1') {
// experimentally determine h_len for the algorithm in question
static $lengths;
if (!isset($lengths[$algo])) { $lengths[$algo] = strlen(hash($algo, null, true)); }
$h_len = $lengths[$algo];
if ($dk_len > (pow(2, 32) - 1) * $h_len) {
return false; // derived key is too long
} else {
$l = ceil($dk_len / $h_len); // number of derived key blocks to compute
$t = null;
for ($i = 1; $i <= $l; $i++) {
$f = $u = hash_hmac($algo, $s . pack('N', $i), $p, true); // first iterate
for ($j = 1; $j < $c; $j++) {
$f ^= ($u = hash_hmac($algo, $u, $p, true)); // xor each iterate
}
$t .= $f; // concatenate blocks of the derived key
}
return substr($t, 0, $dk_len); // return the derived key of correct length
}
}
$password = 'test';
$salt = 'saltsalt';
$text = "texttoencrypt";
#$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
#echo $iv_size . '<br/>';
#$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
#print_r (mcrypt_list_algorithms());
$iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
$key = pbkdf2($password, $salt, 1000, 32);
echo 'key: ' . base64_encode($key) . '<br/>';
echo 'iv: ' . base64_encode($iv) . '<br/>';
echo '<br/><br/>';
function addpadding($string, $blocksize = 32){
$len = strlen($string);
$pad = $blocksize - ($len % $blocksize);
$string .= str_repeat(chr($pad), $pad);
return $string;
}
echo 'text: ' . $text . '<br/>';
echo 'text: ' . addpadding($text) . '<br/>';
// -- works till here
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv);
echo '1.' . $crypttext . '<br/>';
$crypttext = base64_encode($crypttext);
echo '2.' . $crypttext . '<br/>';
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, addpadding($text), MCRYPT_MODE_CBC, $iv);
echo '1.' . $crypttext . '<br/>';
$crypttext = base64_encode($crypttext);
echo '2.' . $crypttext . '<br/>';
?>
需要指出的是,Key 和 IV 在 .NET 和 PHP 上看起来很相似,但在执行 mcrypt_encrypt() 时的最终调用中似乎出现了问题。最终结果,加密字符串,与 .NET 不同。
谁能告诉我我做错了什么。据我所知,一切都应该是正确的。
谢谢!
编辑:
.NET 中 AESManaged 对象的其他信息
密钥大小 = 256 模式 = CBC 填充 = PKCS7
【问题讨论】:
-
似乎出错了是什么意思?您收到错误消息吗?你得到不同的结果吗? (这是正常的,如果 IV 是随机的。)你不能再次解密吗?还有什么?
-
嗨 Paulo,最终结果,加密字符串,在 PHP 和 .NET 之间有所不同,但我几乎可以肯定我输入了正确的密钥和 IV(以及要加密的文本)。希望能多解释一点。
标签: php windows-phone-7 encryption aes