2011-12-07 48 views
1

我在C#的Rijndael/AES解密C#到PHP转换

string s = "hellowld"; 
byte[] bytes = new UnicodeEncoding().GetBytes(s); 
FileStream stream = new FileStream(inputFile, FileMode.Open); 
RijndaelManaged managed = new RijndaelManaged(); 
CryptoStream stream2 = new CryptoStream(stream, managed.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read); 
FileStream stream3 = new FileStream(outputFile, FileMode.Create); 
try 
{ 
    int num; 
    while ((num = stream2.ReadByte()) != -1) 
    { 
     stream3.WriteByte((byte) num); 
    } 
[....] 

此代码段解密某个文件,并输出解密版本下面的代码。在从IM RijndaelManaged的用所述密码作为密钥对CreateDecryptor的方法,并且还作为IV。

我发现了一些代码在这里计算器上的PHP但如果我尝试给钥匙,像在C#什么也没有发生字节的IV相同的数组。

$Pass = "hellowld"; 
$Clear = file_get_contents('./file.dat', FILE_USE_INCLUDE_PATH); 

$bytePass=array(); 
$i = 0; 
foreach (str_split($Pass) as $value) { 
    $bytePass[$i]=ord($value); 
    $i++; 
} 

echo decryptAES($Clear,$bytePass,$bytePass); 

function decryptAES($content,$iv, $key,$aes) { 

// Setzt den Algorithmus 
switch ($aes) { 
    case 128: 
     $rijndael = 'rijndael-128'; 
     break; 
    case 192: 
     $rijndael = 'rijndael-192'; 
     break; 
    default: 
     $rijndael = 'rijndael-256'; 
} 

// Setzt den Verschlüsselungsalgorithmus 
// und setzt den Output Feedback (OFB) Modus 
$cp = mcrypt_module_open($rijndael, '', 'ofb', ''); 

// Ermittelt die Anzahl der Bits, welche die Schlüssellänge des Keys festlegen 
$ks = mcrypt_enc_get_key_size($cp); 

// Erstellt den Schlüssel, der für die Verschlüsselung genutzt wird 
$key = substr(md5($key), 0, $ks); 

// Initialisiert die Verschlüsselung 
mcrypt_generic_init($cp, $key, $iv); 

// Entschlüsselt die Daten 
$decrypted = mdecrypt_generic($cp, $content); 

// Beendet die Verschlüsselung 
mcrypt_generic_deinit($cp); 

// Schließt das Modul 
mcrypt_module_close($cp); 

return trim($decrypted); 

} 

我真的需要一些帮助,如何在PHP中正确创建代码。没有必要使用PHP输出文件,字符串就足够了。

UPDATE: 默认的C#RijndaelManaged密码方法是AES-128-CBC。我改变了我的PHP代码到的mcrypt模块(default C# cipher method

更新2: 我还是设法创建一个Java解密这导致我的另一件事。 PHP必须使用PKCS7填充。

+0

如果它有助于继承人的文件。 http://php.net/manual/en/function.mcrypt-module-open.php – Matt

回答

1

你的C#代码并没有真正看起来安全的,所以如果你可以改变它,请参阅下面的一些技巧。 下面是修改后的样子可能是相当于给定的C#代码你给PHP代码。

function decryptAES128CBC($content,$iv, $key) { 

    // AES is Rijndael-128 
    $rijndael = 'rijndael-128'; 

    // key size is 128 bit = 16 bytes 
    $ks = 16; 

    // CBC mode, not OFB 
    $cp = mcrypt_module_open($rijndael, '', 'cbc', ''); 

    // pad key and IV by zeros (this is not a good idea) 
    $key = str_pad($key, $ks, "\0"); 
    $iv = str_pad($key, $iv, "\0"); 

    // initialize the decryptor with key and IV 
    mcrypt_generic_init($cp, $key, $iv); 

    // the actual work 
    $decrypted = mdecrypt_generic($cp, $content); 

    // clean up 
    mcrypt_generic_deinit($cp); 
    mcrypt_module_close($cp); 

    // remove padding, see below 
    return unpad($decrypted); 
} 

最后unpad是有以除去可能是由加密函数追加到放大消息大小为完整数量的块的填充。通过使用RijndaelManaged的默认填充是PKCS7-填充,其附加一字节数(16个1之间),其中的每一个等于添加的字节数。在真正的实现中,你会在解密之后检查填充是否有效(即所有这些字节都具有相同的值),但对于“快速和肮脏”,你可以简单地使用检查最后一个字节并删除那么多字节的东西。示例请参见comments to mcrypt_decrypt

如果你可以改变你的C#代码:

  • 注意,一般是不使用(每个键)的固定值作为初始化向量是一个好主意,并使用该密钥本身初始化矢量也不好,要么。使用随机初始化向量(与消息一起发送)或查看下一个点。另外,您通常不希望直接使用(相当短的)密码作为密钥,而是使用更长的密码短语,并将其与盐(包含在消息中)进行哈希以得到密钥。如果你这样做,你也可以从相同的两片的数据(但在某种程度上,他们将不同,使用密钥导出函数)获得初始化向量。 为避免暴力破解加密文件中的密码,请在此处使用慢哈希函数(PBKDF-2或bcrypt)。

+0

非常感谢你的详细解答。我无法更改C#代码,但是php代码的信息足以解决我的问题。它确实有帮助。 – Taylantz