我有一个PHP程序,它将PDF文件加密为.xxx文件。这个输出由一个C#程序读取,该程序将.xxx文件解密回PDF文件。
我的问题是,当我打开由C#解密的文件时,PDF阅读器告诉我该文件已损坏。。当我在PHP中加密纯文本并在C#上解密时,我得到了我加密的文件。。因此问题只出现在PDF文件中,或者换句话说,它出现在BINARY文件中
有什么建议吗?!
注:
- 在PHP中,我使用mcrypt扩展Rijndael算法CBC PKCS7填充(填充是手动完成的)
- 在C#中,我使用RijndaelManaged类来加密和解密数据
编辑:
以下是我在PHP中使用的加密方法:
function encrypt($key, $iv, $text) {
ini_set ( 'memory_limit', '-1' );
$mcrypt_cipher = MCRYPT_RIJNDAEL_256;
$mcrypt_mode = MCRYPT_MODE_CBC;
$text=addpadding($text,mcrypt_get_block_size($mcrypt_cipher,'cbc'));
$encrypted = rtrim ( mcrypt_encrypt ( $mcrypt_cipher, $key, $text, $mcrypt_mode, $iv ), " " );
$encrypted = base64_encode ( $encrypted );
return $encrypted;
}
下面是C#中的解密方法:
public static string DecryptString(string message, string KeyString, string IVString)
{
byte[] Key = Encoding.UTF8.GetBytes(KeyString);
byte[] IV = Encoding.UTF8.GetBytes(IVString);
string decrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.BlockSize = 256;
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
rj.Padding = PaddingMode.PKCS7;
try
{
MemoryStream ms = new MemoryStream();
//Encoding enc = new UTF8Encoding();
byte[] messageBytes = Convert.FromBase64String(message);
using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Write))
{
//byte[] messageBytes = enc.GetBytes(message);
cs.Write(messageBytes, 0, messageBytes.Length);
cs.Close();
}
byte[] encoded = ms.ToArray();
decrypted = Encoding.UTF8.GetString(encoded);
ms.Close();
}
catch (Exception e)
{
MessageBox.Show("An error occurred:"+ e.Message);
}
finally
{
rj.Clear();
}
return decrypted;
}
下面是我如何在C#中调用解密,以及我如何编写输出:
string Key = cryptography.MD5("X-Ware" + cryptography.MD5("123"));
string IV = cryptography.MD5("XWare");
string decrypted = cryptography.DecryptString(contents, Key, IV);
string outputFilename = cryptography.MD5(OFD.FileName) + ".tmp";
StreamWriter sw = new StreamWriter("C:\Windows\Temp\" + outputFilename, false, Encoding.UTF8);
BinaryWriter bw = new BinaryWriter(sw.BaseStream, Encoding.UTF8);
//sw.Write(decrypted);
bw.Write(decrypted);
sw.Close();
bw.Close();
我认为问题在于您在PHP和C#端都将二进制PDF数据视为文本。
decrypted = Encoding.UTF8.GetString(encoded);
如果CCD_ 1表示二进制数据。您可能应该跳过这一步,将DecryptString()
定义为返回byte[]
。然后也将其重命名。
如果你真的想把它作为字符串,你可能会更幸运地使用ASCII或ANSI编码:
decrypted = Encoding.ASCII.GetString(encoded);
但是这个错误可能已经发生在PHP方面了,我不知道。
另外,我刚刚注意到:
StreamWriter sw = new StreamWriter("C:\Windows\Temp\" + outputFilename,
false, Encoding.UTF8);
BinaryWriter bw = new BinaryWriter(sw.BaseStream, Encoding.UTF8);
这是一种非常复杂的创建BinaryWriter的方法。将不使用编码。和
bw.Write(decrypted);
这将写一个长度前缀的字符串,这肯定会使您的PDF无效。
当您将Decrypt的返回保持为string
时,请使用
File.WriteAllText("C:\Windows\Temp\" + outputFilename, decrypted);
当您将其作为byte[]
(推荐)返回时,请使用
File.WriteAllBytes("C:\Windows\Temp\" + outputFilename, decrypted);