我在C#中有以下代码
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);
}
[....]
此代码段解密某个文件并输出解密版本。在RijndaelManaged的CreateDecryptor方法中,使用密码作为KEY,也作为IV。
我在这里找到了一些关于PHP的stackoverflow的代码,但是如果我尝试给出密钥,并且在C#中使用相同的Bytes数组,则没有任何反应。
$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中输出文件,只需一个字符串即可。
更新: 默认的C#RijndaelManaged密码方法是AES-128-CBC。我将我的PHP代码更改为mcrypt模块(default C# cipher method)
更新2: 我确实设法创建了一个Java Decryptor,它引导我做另一件事。 PHP必须使用PKCS7 Padding。
答案 0 :(得分:1)
您的C#代码看起来并不安全,因此如果您可以更改它,请参阅下面的一些提示。 以下是您修改的给定PHP代码,看起来它可能等同于给定的C#代码。
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-padding,它附加了一些字节(1到16之间),每个字节等于附加的字节数。在实际实现中,您将在解密后检查填充是否有效(即所有这些字节具有相同的值),但对于“快速和脏”,您可以简单地使用检查最后一个字节并删除那么多字节的东西。有关示例,请参阅comments to mcrypt_decrypt。
如果您可以更改C#代码:
请注意,使用固定值(每个键)作为初始化向量通常不是一个好主意,并且使用键本身作为初始化向量也不好。使用随机初始化向量(与消息一起发送),或查看下一个点。
此外,您通常不希望直接使用(相当短的)密码作为密钥,而是使用更长的密码短语,并使用盐(包含在消息中)对其进行散列以导出键。如果这样做,您还可以从相同的两个数据中导出初始化向量(但是使用密钥派生函数,它们将是不同的)。 要避免从加密文件中强制输入密码,请在此处使用慢速哈希函数(PBKDF-2或bcrypt)。