我需要将来自PHP的AES加密的base64编码文件提供给C#客户端(Mono,在各种平台上)。我已经成功地使AES加密/解密工作正常,但是一旦我尝试base64编码/解码,我就遇到了麻烦。以下两个示例都禁用了AES,因此不应该是一个因素。
我最简单的测试用例,一个Hello World字符串,工作正常:
PHP服务输出 -
// Save encoded data to file
$data = base64_encode("Hello encryption world!!");
$file = fopen($targetPath, 'w');
fwrite($file, $data);
fclose($file);
// Later on, serve the file
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".basename($product->PackageFilename($packageId)));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($targetPath));
ob_clean();
flush();
$handle = fopen($targetPath, "r");
fpassthru($handle);
fclose($handle);
C#解码和使用 -
StreamReader reader = new StreamReader(stream);
char[] buffer = DecodeBuffer;
string decoded = "";
int read = 0;
while (0 < (read = reader.Read(buffer, 0, DecodeBufferSize)))
{
byte[] decodedBytes = Convert.FromBase64CharArray(buffer, 0, read);
decoded += System.Text.Encoding.UTF8.GetString(decodedBytes);
}
Log(decoded); // Correctly logs "Hello encryption world!!"
但是,一旦我开始尝试对文件内容做同样的事情,Convert.FromBase64CharArray抛出 FormatException:找到无效字符:
PHP服务输出 -
// Save encoded data to file
$data = base64_encode(file_get_contents($targetPath));
$file = fopen($targetPath, 'w');
fwrite($file, $data);
fclose($file);
// Later on, serve the file
// Same as above
C#解码和使用 -
using (Stream file = File.Open(zipPath, FileMode.Create))
{
using (StreamReader reader = new StreamReader(stream))
{
char[] buffer = DecodeBuffer;
byte[] decodedBytes;
int read = 0;
while (0 < (read = reader.Read(buffer, 0, DecodeBufferSize)))
{
// Throws FormatException: Invalid character found
decodedBytes = Convert.FromBase64CharArray(buffer, 0, read);
file.Write(decodedBytes, 0, decodedBytes.Length);
}
}
}
是否应该对较大的数据进行某种额外的处理以使base64有效?用大二进制数据做这个也许是不恰当的 - 如果是这样的话你怎么能防止字符传输不安全的潜在问题呢?
答案 0 :(得分:1)
您的阅读Base64文本代码不正确。
验证文件中的数据是否正确将整个文件读为字符串(StreamReader.ReadToEnd)并转换为字节数组(Convert.FromBase64String)。
如果文件包含有效的Base64数据,并且您无法将其作为单个字符串读取,则应实现自己的Base64解码或手动读取正确数量的非空白字符(4的倍数)并解码此类块。
答案 1 :(得分:1)
Base64编码将3个八位字节转换为4个编码字符。因此,您为解码提供的数据长度必须是4的倍数。
首先,确保DecodeBufferSize
是4的倍数。接下来,由于StreamReader.Read
不能保证读取所有请求的字节,因此应继续读入buffer
直到要么它已被填充,要么已到达流的末尾。