2012-04-09 52 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,直到它被填滿,或者流的末尾已經到達。