【C#】itextsharp 對受保護的PDF 處理:合併、修改

因為客戶要求配合將itextsharp 降版,因此碰到舊版itextsharp 對受保護PDF 的處理方法與新版的稍有不同。順便紀錄itextsharp 要如何處理加密或受保護的PDF

系統環境:

Windows 11、Visual Studio 2022、iTextSharp-LGPL 4.1.6、iTextSharp 5.5.13.3

加密種類

PDF的加密分兩種
User Password:PDF密碼。開啟PDF 時需要輸入密碼。
Owner Password:受保護的PDF。可以直接開啟PDF,但是無法編輯內容。開啟檔案時,PDF reader 顯示檔名的後面會顯示 (已保護)。

處理User Password

這邊的處理不是指破解密碼,是指程式要對輸入密碼正確及錯誤的狀況處理

string password = "12345678";
byte[] bytes = File.ReadAllBytes("有密碼的PDF 檔案路徑");
PdfReader reader;
try
{
    reader = new PdfReader(bytes, Encoding.UTF8.GetBytes(password));
 
	// 密碼正確可以往下操作
 
	
	reader = new PdfReader(bytes);
	// 如果沒帶密碼開啟有密碼的PDF,會直接跳到BadPasswordException
}
catch (BadPasswordException)
{

	// 密碼錯誤也會跑到BadPasswordException

	Console.WriteLine("密碼錯誤");
}

研究了一陣子,發現要檢查PDF 有沒有密碼只能用try-catch 方式,覺得也蠻奇怪的……

處理Owner Password

當要合併、修改 受保護的PDF,兩個版本要用不同的做法。

PdfReader reader = new PdfReader(bytes);

// iTextSharp 5.5.13.3
PdfReader.unethicalreading = true;


// iTextSharp-LGPL 4.1.6

if (reader.IsEncrypted())
{
	try
    {
    	// 直接修改PdfReader.encrypted 成false
    	var field = reader.GetType().GetField("encrypted", BindingFlags.NonPublic | BindingFlags.Instance);
        field?.SetValue(reader, false);
    }
    catch { }
}

using (MemoryStream stream = new MemoryStream())
{
	try
	{
		// PdfStamper 是修改PDF 用的物件
  		PdfStamper stamper = new PdfStamper(reader, stream);
	}
	catch
	{
		// 如果沒有經過上面的步驟解開保護,就會拋出例外狀況
	}
}

相關連結:

IText解保受保护的PDF - 簡書 (jianshu.com)