Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PgpCore.Tests/PgpCore.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp6.0</TargetFrameworks>
<TargetFrameworks>net472;net8.0</TargetFrameworks>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
37 changes: 37 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignAsync.File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,5 +275,42 @@ public async Task ClearSignAsync_SignMessageWithHeaders_ShouldSignMessage(KeyTyp
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public async Task ClearSignAsync_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
await testFactory.ArrangeAsync(keyType);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";
File.WriteAllText(testFactory.ContentFileInfo.FullName, utf8Content, Encoding.UTF8);

EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKeyFileInfo, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKeyFileInfo);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);

// Act
await pgpSign.ClearSignAsync(testFactory.ContentFileInfo, testFactory.EncryptedContentFileInfo);
bool verified = await pgpVerify.VerifyClearAsync(testFactory.EncryptedContentFileInfo);
string signedContent = File.ReadAllText(testFactory.EncryptedContentFileInfo.FullName, Encoding.UTF8);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
39 changes: 39 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignAsync.Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,5 +289,44 @@ public async Task ClearSignAsync_SignMessageWithHeaders_ShouldSignMessage(KeyTyp
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public async Task ClearSignAsync_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
await testFactory.ArrangeAsync(keyType);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";
File.WriteAllText(testFactory.ContentFileInfo.FullName, utf8Content, Encoding.UTF8);

EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKeyStream, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKeyStream);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);

// Act
using (Stream outputFileStream = testFactory.EncryptedContentFileInfo.Create())
await pgpSign.ClearSignAsync(testFactory.ContentStream, outputFileStream);

bool verified = await pgpVerify.VerifyClearAsync(testFactory.EncryptedContentStream);
string signedContent = File.ReadAllText(testFactory.EncryptedContentFileInfo.FullName, Encoding.UTF8);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
34 changes: 34 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignAsync.String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,39 @@ public async Task ClearSignAsync_SignMessageWithHeaders_ShouldSignMessage(KeyTyp
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public async Task ClearSignAsync_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
await testFactory.ArrangeAsync(keyType, FileType.Known);
EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKey, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKey);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";

// Act
string signedContent = await pgpSign.ClearSignAsync(utf8Content);
bool verified = await pgpVerify.VerifyClearAsync(signedContent);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
37 changes: 37 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignSync.File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,5 +275,42 @@ public void ClearSign_SignMessageWithHeaders_ShouldSignMessage(KeyType keyType)
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public void ClearSign_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
testFactory.Arrange(keyType);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";
File.WriteAllText(testFactory.ContentFileInfo.FullName, utf8Content, Encoding.UTF8);

EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKeyFileInfo, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKeyFileInfo);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);

// Act
pgpSign.ClearSign(testFactory.ContentFileInfo, testFactory.EncryptedContentFileInfo);
bool verified = pgpVerify.VerifyClear(testFactory.EncryptedContentFileInfo);
string signedContent = File.ReadAllText(testFactory.EncryptedContentFileInfo.FullName, Encoding.UTF8);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
39 changes: 39 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignSync.Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,5 +289,44 @@ public void ClearSign_SignMessageWithHeaders_ShouldSignMessage(KeyType keyType)
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public void ClearSign_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
testFactory.Arrange(keyType);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";
File.WriteAllText(testFactory.ContentFileInfo.FullName, utf8Content, Encoding.UTF8);

EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKeyStream, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKeyStream);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);

// Act
using (Stream outputFileStream = testFactory.EncryptedContentFileInfo.Create())
pgpSign.ClearSign(testFactory.ContentStream, outputFileStream);

bool verified = pgpVerify.VerifyClear(testFactory.EncryptedContentStream);
string signedContent = File.ReadAllText(testFactory.EncryptedContentFileInfo.FullName, Encoding.UTF8);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
34 changes: 34 additions & 0 deletions PgpCore.Tests/UnitTests/Sign/SignSync.String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,39 @@ public void ClearSign_SignMessageWithHeaders_ShouldSignMessage(KeyType keyType)
// Teardown
testFactory.Teardown();
}

[Theory]
[InlineData(KeyType.Generated)]
[InlineData(KeyType.Known)]
[InlineData(KeyType.KnownGpg)]
public void ClearSign_SignMessageWithUtf8Characters_ShouldPreserveUtf8(KeyType keyType)
{
// Arrange
TestFactory testFactory = new TestFactory();
testFactory.Arrange(keyType, FileType.Known);
EncryptionKeys signingKeys = new EncryptionKeys(testFactory.PrivateKey, testFactory.Password);
EncryptionKeys verificationKeys = new EncryptionKeys(testFactory.PublicKey);
PGP pgpSign = new PGP(signingKeys);
PGP pgpVerify = new PGP(verificationKeys);
string utf8Content = "Test with UTF-8: š ž č ć đ ñ ü ö ä € ₹ 中文 日本語 한글";

// Act
string signedContent = pgpSign.ClearSign(utf8Content);
bool verified = pgpVerify.VerifyClear(signedContent);

// Assert
using (new AssertionScope())
{
verified.Should().BeTrue();
signedContent.Should().Contain(utf8Content);
// Verify that specific UTF-8 characters are preserved
signedContent.Should().Contain("š");
signedContent.Should().Contain("€");
signedContent.Should().Contain("中文");
}

// Teardown
testFactory.Teardown();
}
}
}
8 changes: 4 additions & 4 deletions PgpCore/PGP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ private async Task OutputClearSignedAsync(Stream inputStream, Stream outputStrea
while (streamReader.Peek() >= 0)
{
string line = await streamReader.ReadLineAsync();
byte[] lineByteArray = Encoding.ASCII.GetBytes(line);
byte[] lineByteArray = Encoding.UTF8.GetBytes(line);
// Does the line end with whitespace?
// Trailing white space needs to be removed from the end of the document for a valid signature RFC 4880 Section 7.1
string cleanLine = line.TrimEnd();
byte[] cleanLineByteArray = Encoding.ASCII.GetBytes(cleanLine);
byte[] cleanLineByteArray = Encoding.UTF8.GetBytes(cleanLine);

pgpSignatureGenerator.Update(cleanLineByteArray, 0, cleanLineByteArray.Length);
await armoredOutputStream.WriteAsync(lineByteArray, 0, lineByteArray.Length);
Expand Down Expand Up @@ -273,11 +273,11 @@ private void OutputClearSigned(Stream inputStream, Stream outputStream, IDiction
{
string line = streamReader.ReadLine();
if (line == null) continue;
byte[] lineByteArray = Encoding.ASCII.GetBytes(line);
byte[] lineByteArray = Encoding.UTF8.GetBytes(line);
// Does the line end with whitespace?
// Trailing white space needs to be removed from the end of the document for a valid signature RFC 4880 Section 7.1
string cleanLine = line.TrimEnd();
byte[] cleanLineByteArray = Encoding.ASCII.GetBytes(cleanLine);
byte[] cleanLineByteArray = Encoding.UTF8.GetBytes(cleanLine);

pgpSignatureGenerator.Update(cleanLineByteArray, 0, cleanLineByteArray.Length);
armoredOutputStream.Write(lineByteArray, 0, lineByteArray.Length);
Expand Down
6 changes: 3 additions & 3 deletions PgpCore/PgpCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
<PackageProjectUrl>https://github.com/mattosaurus/PgpCore</PackageProjectUrl>
<RepositoryUrl>https://github.com/mattosaurus/PgpCore</RepositoryUrl>
<PackageTags>PGP .NET Core</PackageTags>
<Version>6.5.3.0</Version>
<Version>6.5.4.0</Version>
<AssemblyVersion>6.0.0.0</AssemblyVersion>
<FileVersion>6.5.3</FileVersion>
<PackageReleaseNotes>v6.5.3 - Fix missing bytes</PackageReleaseNotes>
<FileVersion>6.5.4</FileVersion>
<PackageReleaseNotes>v6.5.4 - Fix clearsign encoding</PackageReleaseNotes>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
Expand Down