Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DetachedSignatureFactory accepts pre-hashed content as payload #53

Merged
merged 9 commits into from
Oct 25, 2023
18 changes: 13 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# Changelog

## [v0.3.1-pre.11](https://github.com/microsoft/CoseSignTool/tree/v0.3.1-pre.11) (2023-10-11)

[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v1.1.0...v0.3.1-pre.11)

**Merged pull requests:**

- Add password support for certificate files [\#52](https://github.com/microsoft/CoseSignTool/pull/52) ([lemccomb](https://github.com/lemccomb))

## [v1.1.0](https://github.com/microsoft/CoseSignTool/tree/v1.1.0) (2023-10-10)

[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.1-pre.10...v1.1.0)

## [v0.3.1-pre.10](https://github.com/microsoft/CoseSignTool/tree/v0.3.1-pre.10) (2023-10-10)

[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.1-pre.9...v0.3.1-pre.10)
[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.2...v0.3.1-pre.10)

**Merged pull requests:**

Expand All @@ -16,13 +24,13 @@
- Port changes from ADO repo to GitHub repo [\#46](https://github.com/microsoft/CoseSignTool/pull/46) ([lemccomb](https://github.com/lemccomb))
- Re-enable CodeQL [\#45](https://github.com/microsoft/CoseSignTool/pull/45) ([lemccomb](https://github.com/lemccomb))

## [v0.3.1-pre.9](https://github.com/microsoft/CoseSignTool/tree/v0.3.1-pre.9) (2023-09-28)
## [v0.3.2](https://github.com/microsoft/CoseSignTool/tree/v0.3.2) (2023-09-28)

[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.2...v0.3.1-pre.9)
[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.1-pre.9...v0.3.2)

## [v0.3.2](https://github.com/microsoft/CoseSignTool/tree/v0.3.2) (2023-09-28)
## [v0.3.1-pre.9](https://github.com/microsoft/CoseSignTool/tree/v0.3.1-pre.9) (2023-09-28)

[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.1-pre.8...v0.3.2)
[Full Changelog](https://github.com/microsoft/CoseSignTool/compare/v0.3.1-pre.8...v0.3.1-pre.9)

**Merged pull requests:**

Expand Down
111 changes: 111 additions & 0 deletions CoseSign1.Tests/DetachedSignatureFactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

namespace CoseSign1.Tests;

using System.Runtime.Intrinsics.Arm;

/// <summary>
/// Class for Testing Methods of <see cref="DetachedSignatureFactory"/>
/// </summary>
Expand Down Expand Up @@ -74,6 +76,49 @@ public async Task TestCreateDetachedSignatureAsync()
memStream.Seek(0, SeekOrigin.Begin);
}

[Test]
public async Task TestCreateDetachedSignatureHashProvidedAsync()
{
ICoseSigningKeyProvider coseSigningKeyProvider = SetupMockSigningKeyProvider(nameof(TestCreateDetachedSignatureHashProvidedAsync));
using DetachedSignatureFactory factory = new();
byte[] randomBytes = new byte[50];
new Random().NextBytes(randomBytes);
using HashAlgorithm hasher = CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName(factory.HashAlgorithmName)
?? throw new Exception($"Failed to get hash algorithm from {nameof(CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName)}");
byte[] hash = hasher!.ComputeHash(randomBytes);
using MemoryStream hashStream = new(hash);

// test the sync method
Assert.Throws<ArgumentNullException>(() => factory.CreateDetachedSignatureFromHash(hash, coseSigningKeyProvider, string.Empty));
CoseSign1Message detachedSignature = factory.CreateDetachedSignatureFromHash(hash, coseSigningKeyProvider, "application/test.payload");
detachedSignature.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature.SignatureMatches(randomBytes).Should().BeTrue();

Assert.Throws<ArgumentNullException>(() => factory.CreateDetachedSignature(hashStream, coseSigningKeyProvider, string.Empty));
hashStream.Seek(0, SeekOrigin.Begin);
CoseSign1Message detachedSignature2 = factory.CreateDetachedSignatureFromHash(hashStream, coseSigningKeyProvider, "application/test.payload");
detachedSignature2.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature2.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature2.SignatureMatches(randomBytes).Should().BeTrue();
hashStream.Seek(0, SeekOrigin.Begin);

// test the async methods
Assert.ThrowsAsync<ArgumentNullException>(() => factory.CreateDetachedSignatureFromHashAsync(hash, coseSigningKeyProvider, string.Empty));
CoseSign1Message detachedSignature3 = await factory.CreateDetachedSignatureFromHashAsync(hash, coseSigningKeyProvider, "application/test.payload");
detachedSignature3.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature3.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature3.SignatureMatches(randomBytes).Should().BeTrue();

Assert.ThrowsAsync<ArgumentNullException>(() => factory.CreateDetachedSignatureFromHashAsync(hashStream, coseSigningKeyProvider, string.Empty));
hashStream.Seek(0, SeekOrigin.Begin);
CoseSign1Message detachedSignature4 = await factory.CreateDetachedSignatureFromHashAsync(hashStream, coseSigningKeyProvider, "application/test.payload");
detachedSignature4.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature4.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature4.SignatureMatches(randomBytes).Should().BeTrue();
hashStream.Seek(0, SeekOrigin.Begin);
}

[Test]
public async Task TestCreateDetachedSignatureBytesAsync()
{
Expand Down Expand Up @@ -114,6 +159,49 @@ public async Task TestCreateDetachedSignatureBytesAsync()
detachedSignature4.SignatureMatches(memStream).Should().BeTrue();
}

[Test]
public async Task TestCreateDetachedSignatureBytesHashProvidedAsync()
{
ICoseSigningKeyProvider coseSigningKeyProvider = SetupMockSigningKeyProvider(nameof(TestCreateDetachedSignatureBytesHashProvidedAsync));
using DetachedSignatureFactory factory = new();
byte[] randomBytes = new byte[50];
new Random().NextBytes(randomBytes);
using HashAlgorithm hasher = CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName(factory.HashAlgorithmName)
?? throw new Exception($"Failed to get hash algorithm from {nameof(CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName)}");
byte[] hash = hasher!.ComputeHash(randomBytes);
using MemoryStream hashStream = new(hash);

// test the sync method
Assert.Throws<ArgumentNullException>(() => factory.CreateDetachedSignatureBytesFromHash(hash, coseSigningKeyProvider, string.Empty));
CoseSign1Message detachedSignature = CoseMessage.DecodeSign1(factory.CreateDetachedSignatureBytesFromHash(hash, coseSigningKeyProvider, "application/test.payload").ToArray());
detachedSignature.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature.SignatureMatches(randomBytes).Should().BeTrue();

Assert.Throws<ArgumentNullException>(() => factory.CreateDetachedSignatureBytesFromHash(hashStream, coseSigningKeyProvider, string.Empty));
hashStream.Seek(0, SeekOrigin.Begin);
CoseSign1Message detachedSignature2 = CoseMessage.DecodeSign1(factory.CreateDetachedSignatureBytesFromHash(hashStream, coseSigningKeyProvider, "application/test.payload").ToArray());
detachedSignature2.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature2.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature2.SignatureMatches(randomBytes).Should().BeTrue();
hashStream.Seek(0, SeekOrigin.Begin);

// test the async methods
Assert.ThrowsAsync<ArgumentNullException>(() => factory.CreateDetachedSignatureBytesFromHashAsync(hash, coseSigningKeyProvider, string.Empty));
CoseSign1Message detachedSignature3 = CoseMessage.DecodeSign1((await factory.CreateDetachedSignatureBytesFromHashAsync(hash, coseSigningKeyProvider, "application/test.payload")).ToArray());
detachedSignature3.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature3.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
detachedSignature3.SignatureMatches(randomBytes).Should().BeTrue();

Assert.ThrowsAsync<ArgumentNullException>(() => factory.CreateDetachedSignatureBytesFromHashAsync(hashStream, coseSigningKeyProvider, string.Empty));
hashStream.Seek(0, SeekOrigin.Begin);
CoseSign1Message detachedSignature4 = CoseMessage.DecodeSign1((await factory.CreateDetachedSignatureBytesFromHashAsync(hashStream, coseSigningKeyProvider, "application/test.payload")).ToArray());
detachedSignature4.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature4.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-sha256");
hashStream.Seek(0, SeekOrigin.Begin);
detachedSignature4.SignatureMatches(randomBytes).Should().BeTrue();
}

[Test]
public void TestCreateDetachedSignatureMd5()
{
Expand All @@ -130,6 +218,29 @@ public void TestCreateDetachedSignatureMd5()
detachedSignature.SignatureMatches(randomBytes).Should().BeTrue();
}

[Test]
public void TestCreateDetachedSignatureMd5HashProvided()
{
ICoseSigningKeyProvider coseSigningKeyProvider = SetupMockSigningKeyProvider(nameof(TestCreateDetachedSignatureMd5));
using DetachedSignatureFactory factory = new();
byte[] randomBytes = new byte[50];
new Random().NextBytes(randomBytes);
using HashAlgorithm hasher = CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName(HashAlgorithmName.MD5)
?? throw new Exception($"Failed to get hash algorithm from {nameof(CoseSign1MessageDetachedSignatureExtensions.CreateHashAlgorithmFromName)}");
byte[] hash = hasher!.ComputeHash(randomBytes);

// test the sync method
Assert.Throws<ArgumentNullException>(() => factory.CreateDetachedSignatureFromHash(hash, coseSigningKeyProvider, string.Empty));
CoseSign1Message detachedSignature = CoseMessage.DecodeSign1(factory.CreateDetachedSignatureBytesFromHash(hash, coseSigningKeyProvider, "application/test.payload").ToArray());
detachedSignature.ProtectedHeaders.ContainsKey(CoseHeaderLabel.ContentType).Should().BeTrue();
detachedSignature.ProtectedHeaders[CoseHeaderLabel.ContentType].GetValueAsString().Should().Be("application/test.payload+hash-md5");
detachedSignature.SignatureMatches(randomBytes).Should().BeTrue();

// test unknown hash length
// test the sync method
Assert.Throws<ArgumentException>(() => factory.CreateDetachedSignatureFromHash(randomBytes, coseSigningKeyProvider, "application/test.payload"));
}

[Test]
public void TestCreateDetachedSignatureAlreadyProvided()
{
Expand Down
Loading
Loading