Skip to content

Commit b86def0

Browse files
committed
Add ENCRYPTION_AES_256 support, Close #139
1 parent 879686f commit b86def0

File tree

10 files changed

+658
-261
lines changed

10 files changed

+658
-261
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System.IO;
2+
using System.util;
3+
using iTextSharp.text;
4+
using iTextSharp.text.pdf;
5+
using Microsoft.VisualStudio.TestTools.UnitTesting;
6+
7+
namespace iTextSharp.LGPLv2.Core.FunctionalTests.Issues;
8+
9+
/// <summary>
10+
/// https://github.com/VahidN/iTextSharp.LGPLv2.Core/issues/139
11+
/// </summary>
12+
[TestClass]
13+
public class Issue139
14+
{
15+
[TestMethod]
16+
public void Test_Issue139_Verify_PdfReader_Works()
17+
{
18+
var inputFile = TestUtils.GetPdfsPath(fileName: "issue139.pdf");
19+
20+
using (var reader = new PdfReader(inputFile))
21+
{
22+
Assert.AreEqual(expected: 2, reader.NumberOfPages);
23+
}
24+
}
25+
26+
[TestMethod]
27+
public void Test_Issue139_CreateSimple_AES_256_Pdf()
28+
{
29+
var pdfFilePath = TestUtils.GetOutputFileName();
30+
var encryptionType = PdfWriter.ENCRYPTION_AES_256;
31+
CreateEncryptedPdfFile(pdfFilePath, encryptionType);
32+
}
33+
34+
[TestMethod]
35+
public void Test_Issue139_CreateSimple_AES_128_Pdf()
36+
{
37+
var pdfFilePath = TestUtils.GetOutputFileName();
38+
var encryptionType = PdfWriter.ENCRYPTION_AES_128;
39+
CreateEncryptedPdfFile(pdfFilePath, encryptionType);
40+
}
41+
42+
[TestMethod]
43+
public void Test_Issue139_CreateSimple_AES_256_V3_Pdf()
44+
{
45+
var pdfFilePath = TestUtils.GetOutputFileName();
46+
var encryptionType = PdfWriter.ENCRYPTION_AES_256_V3;
47+
CreateEncryptedPdfFile(pdfFilePath, encryptionType);
48+
}
49+
50+
[TestMethod]
51+
public void Test_Issue139_CreateSimple_STANDARD_ENCRYPTION_128_Pdf()
52+
{
53+
var pdfFilePath = TestUtils.GetOutputFileName();
54+
var encryptionType = PdfWriter.STANDARD_ENCRYPTION_128;
55+
CreateEncryptedPdfFile(pdfFilePath, encryptionType);
56+
}
57+
58+
[TestMethod]
59+
public void Test_Issue139_CreateSimple_STANDARD_ENCRYPTION_40_Pdf()
60+
{
61+
var pdfFilePath = TestUtils.GetOutputFileName();
62+
var encryptionType = PdfWriter.STANDARD_ENCRYPTION_40;
63+
CreateEncryptedPdfFile(pdfFilePath, encryptionType);
64+
}
65+
66+
private static void CreateEncryptedPdfFile(string pdfFilePath, int encryptionType)
67+
{
68+
using (var fileStream = new FileStream(pdfFilePath, FileMode.Create))
69+
{
70+
using (var document = new Document(PageSize.A4))
71+
{
72+
var permissions = 0;
73+
permissions |= PdfWriter.AllowPrinting;
74+
permissions |= PdfWriter.AllowCopy;
75+
permissions |= PdfWriter.AllowScreenReaders;
76+
77+
var writer = PdfWriter.GetInstance(document, fileStream);
78+
79+
writer.SetEncryption(encryptionType, userPassword: "user", ownerPassword: "owner", permissions);
80+
81+
document.AddAuthor(TestUtils.Author);
82+
83+
// step 3
84+
document.Open();
85+
86+
// step 4
87+
document.Add(new Paragraph(str: "Hello World"));
88+
}
89+
}
90+
91+
using var reader = new PdfReader(pdfFilePath, "owner".GetIsoBytes());
92+
Assert.IsTrue(reader.IsEncrypted(), message: "PdfReader fails to report test file to be encrypted.");
93+
94+
Assert.IsTrue(reader.IsOpenedWithFullPermissions,
95+
message: "PdfReader fails to recognize password as owner password.");
96+
97+
Assert.AreEqual(expected: 1, reader.NumberOfPages,
98+
message: "PdfReader fails to report the correct number of pages");
99+
100+
var author = reader.Info[key: "Author"];
101+
Assert.AreEqual(TestUtils.Author, author);
102+
}
103+
}
Binary file not shown.

src/iTextSharp.LGPLv2.Core/iTextSharp.LGPLv2.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<Description>iTextSharp.LGPLv2.Core is an unofficial port of the last LGPL version of the iTextSharp (V4.1.6) to .NET Core.</Description>
4-
<VersionPrefix>3.6.0</VersionPrefix>
4+
<VersionPrefix>3.7.0</VersionPrefix>
55
<Authors>Vahid Nasiri</Authors>
66
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0;netstandard2.0;net462;</TargetFrameworks>
77
<GenerateDocumentationFile>true</GenerateDocumentationFile>

src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/OutputStreamEncryption.cs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class OutputStreamEncryption : Stream
88
protected AesCipher Cipher;
99
protected Stream Outc;
1010
private const int Aes128 = 4;
11+
private const int AES_256 = 5;
1112
private const int AES_256_V3 = 6;
1213
private readonly bool _aes;
1314
private readonly byte[] _buf = new byte[1];
@@ -16,14 +17,15 @@ public class OutputStreamEncryption : Stream
1617
public OutputStreamEncryption(Stream outc, byte[] key, int off, int len, int revision)
1718
{
1819
Outc = outc;
19-
_aes = revision == Aes128 || revision == AES_256_V3;
20+
_aes = revision is Aes128 or AES_256_V3 or AES_256;
21+
2022
if (_aes)
2123
{
2224
var iv = IvGenerator.GetIv();
2325
var nkey = new byte[len];
24-
Array.Copy(key, off, nkey, 0, len);
25-
Cipher = new AesCipher(true, nkey, iv);
26-
Write(iv, 0, iv.Length);
26+
Array.Copy(key, off, nkey, destinationIndex: 0, len);
27+
Cipher = new AesCipher(forEncryption: true, nkey, iv);
28+
Write(iv, offset: 0, iv.Length);
2729
}
2830
else
2931
{
@@ -32,8 +34,8 @@ public OutputStreamEncryption(Stream outc, byte[] key, int off, int len, int rev
3234
}
3335
}
3436

35-
public OutputStreamEncryption(Stream outc, byte[] key, int revision) :
36-
this(outc, key, 0, key?.Length ?? throw new ArgumentNullException(nameof(key)), revision)
37+
public OutputStreamEncryption(Stream outc, byte[] key, int revision) : this(outc, key, off: 0,
38+
key?.Length ?? throw new ArgumentNullException(nameof(key)), revision)
3739
{
3840
}
3941

@@ -65,48 +67,45 @@ public void Finish()
6567
if (!_finished)
6668
{
6769
_finished = true;
70+
6871
if (_aes)
6972
{
7073
var b = Cipher.DoFinal();
71-
Outc.Write(b, 0, b.Length);
74+
Outc.Write(b, offset: 0, b.Length);
7275
}
7376
}
7477
}
7578

76-
public override void Flush()
77-
{
78-
Outc.Flush();
79-
}
79+
public override void Flush() => Outc.Flush();
8080

8181
public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
8282

8383
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
8484

85-
public override void SetLength(long value)
86-
{
87-
throw new NotSupportedException();
88-
}
85+
public override void SetLength(long value) => throw new NotSupportedException();
8986

9087
public override void Write(byte[] buffer, int offset, int count)
9188
{
9289
if (_aes)
9390
{
9491
var b2 = Cipher.Update(buffer, offset, count);
92+
9593
if (b2 == null || b2.Length == 0)
9694
{
9795
return;
9896
}
9997

100-
Outc.Write(b2, 0, b2.Length);
98+
Outc.Write(b2, offset: 0, b2.Length);
10199
}
102100
else
103101
{
104-
var b2 = new byte[Math.Min(count, 4192)];
102+
var b2 = new byte[Math.Min(count, val2: 4192)];
103+
105104
while (count > 0)
106105
{
107106
var sz = Math.Min(count, b2.Length);
108-
Arcfour.EncryptArcfour(buffer, offset, sz, b2, 0);
109-
Outc.Write(b2, 0, sz);
107+
Arcfour.EncryptArcfour(buffer, offset, sz, b2, offOut: 0);
108+
Outc.Write(b2, offset: 0, sz);
110109
count -= sz;
111110
offset += sz;
112111
}
@@ -116,6 +115,6 @@ public override void Write(byte[] buffer, int offset, int count)
116115
public override void WriteByte(byte value)
117116
{
118117
_buf[0] = value;
119-
Write(_buf, 0, 1);
118+
Write(_buf, offset: 0, count: 1);
120119
}
121120
}

src/iTextSharp.LGPLv2.Core/iTextSharp/text/pdf/PdfContentByte.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ public class PdfContentByte
104104
0, 0, 0, 1, 1, 0, 1, 1
105105
};
106106

107+
private static readonly byte[] _r = DocWriter.GetIsoBytes(text: "\\r");
108+
private static readonly byte[] _n = DocWriter.GetIsoBytes(text: "\\n");
109+
private static readonly byte[] _t = DocWriter.GetIsoBytes(text: "\\t");
110+
private static readonly byte[] _b = DocWriter.GetIsoBytes(text: "\\b");
111+
private static readonly byte[] _f = DocWriter.GetIsoBytes(text: "\\f");
112+
107113
private bool _inText;
108114

109115
private int _mcDepth;
@@ -2835,7 +2841,7 @@ public void VariableRectangle(Rectangle rect)
28352841
/// </summary>
28362842
/// <param name="b">the byte array to escape</param>
28372843
/// <returns>an escaped byte array</returns>
2838-
internal static byte[] EscapeString(byte[] b)
2844+
public static byte[] EscapeString(byte[] b)
28392845
{
28402846
var content = new ByteBuffer();
28412847
EscapeString(b, content);
@@ -2848,8 +2854,18 @@ internal static byte[] EscapeString(byte[] b)
28482854
/// </summary>
28492855
/// <param name="b">the byte array to escape</param>
28502856
/// <param name="content"></param>
2851-
internal static void EscapeString(byte[] b, ByteBuffer content)
2857+
public static void EscapeString(byte[] b, ByteBuffer content)
28522858
{
2859+
if (b == null)
2860+
{
2861+
throw new ArgumentNullException(nameof(b));
2862+
}
2863+
2864+
if (content == null)
2865+
{
2866+
throw new ArgumentNullException(nameof(content));
2867+
}
2868+
28532869
content.Append_i(b: '(');
28542870

28552871
for (var k = 0; k < b.Length; ++k)
@@ -2859,23 +2875,23 @@ internal static void EscapeString(byte[] b, ByteBuffer content)
28592875
switch ((int)c)
28602876
{
28612877
case '\r':
2862-
content.Append(str: "\\r");
2878+
content.Append(_r);
28632879

28642880
break;
28652881
case '\n':
2866-
content.Append(str: "\\n");
2882+
content.Append(_n);
28672883

28682884
break;
28692885
case '\t':
2870-
content.Append(str: "\\t");
2886+
content.Append(_t);
28712887

28722888
break;
28732889
case '\b':
2874-
content.Append(str: "\\b");
2890+
content.Append(_b);
28752891

28762892
break;
28772893
case '\f':
2878-
content.Append(str: "\\f");
2894+
content.Append(_f);
28792895

28802896
break;
28812897
case '(':

0 commit comments

Comments
 (0)