2012-04-09 102 views
0

我需要从PHP到C#客户端(Mono,在各种平台上)为AES加密的base64编码文件提供服务。我已经成功地获得了AES加密/解密的正常工作,但只要我尝试base64编码/解码就会遇到麻烦。下面的例子都禁用了AES,所以这不应该是一个因素。在PHP和C之间解码base64文件内容#

我简单的测试案例,一个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#解码和using-

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!!" 

然而,一旦我开始尝试对文件的内容做同样的事情,FormatException:找到无效字符由Convert.FromBase64CharArray引发:

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-

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

只是好奇。在你写fwrite后,php可以打开那个文件并且解码没有错误? – webbiedave 2012-04-09 16:46:09

+0

你需要弄清楚它不喜欢哪个字符。我猜这可能是一个编码问题。 – 2012-04-09 16:58:35

+0

@webbiedave我不认为我检查了这一点。当我再看一遍时,我会的。 – FlintZA 2012-05-10 09:26:10

回答

1

您的阅读Base64文本代码不正确。

  • Base64是文本,所以考虑使用文本阅读器,而不是
  • 的Base64可能包含新的行/空格。即将整个Base64编码值拆分为70-80个字符长的字符串是自定义的。

要验证是否在该文件中的数据是正确读出的整个文件作为字符串(StreamReader.ReadToEnd),并转换为字节阵列(Convert.FromBase64String)。

如果文件包含有效的Base64数据,且无法将其读取为单个字符串,则应执行自己的Base64解码或手动读取正确数量的非空白字符(4的倍数)并解码此类块。

+0

好的,我必须尝试整个字符串。我只是担心这些文件可能太大而无法在一个块中处理(此客户端代码有时会在移动设备上运行,因为内存可用性会成为问题)。 – FlintZA 2012-05-10 09:27:58

1

Base64编码将3个八位字节转换为4个编码字符。因此,您提供的解码数据的长度必须是4

首先倍数,确保DecodeBufferSize是4下一页这么多,因为StreamReader.Read并不能保证所有请求的字节将被读取,你应该继续阅读buffer,直到它被填满,或者流的末尾已经到达。