From 8317530a086ec0c9503601c564d455f959923604 Mon Sep 17 00:00:00 2001 From: Daniel Robinson Date: Fri, 9 Aug 2024 20:55:47 +0100 Subject: [PATCH] Updated unit test coverage for digest Validate function, as both sha256 and sha512 digest are registered the library can validate these although the library is limited to compute sha256 digest. Signed-off-by: Daniel Robinson --- src/OrasProject.Oras/Content/Digest.cs | 13 ++++++- .../Content/ContentTest.cs | 37 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/OrasProject.Oras/Content/Digest.cs b/src/OrasProject.Oras/Content/Digest.cs index bd0cb15..2e8c035 100644 --- a/src/OrasProject.Oras/Content/Digest.cs +++ b/src/OrasProject.Oras/Content/Digest.cs @@ -13,6 +13,7 @@ using OrasProject.Oras.Exceptions; using System; +using System.Collections.Generic; using System.Security.Cryptography; using System.Text.RegularExpressions; @@ -23,6 +24,9 @@ internal static class Digest private const string _digestRegexPattern = @"[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+"; private static readonly Regex _digestRegex = new Regex(_digestRegexPattern, RegexOptions.Compiled); + // List of registered and supported algorithms as per the specification + private static readonly HashSet _supportedAlgorithms = new HashSet { "sha256", "sha512" }; + /// /// Verifies the digest header and throws an exception if it is invalid. /// @@ -33,6 +37,13 @@ internal static string Validate(string? digest) { throw new InvalidDigestException($"Invalid digest: {digest}"); } + + var algorithm = digest.Split(':')[0]; + if (!_supportedAlgorithms.Contains(algorithm)) + { + throw new InvalidDigestException($"Unrecognized, unregistered or unsupported digest algorithm: {algorithm}"); + } + return digest; } @@ -48,4 +59,4 @@ internal static string ComputeSHA256(byte[] content) var output = $"sha256:{BitConverter.ToString(hash).Replace("-", "")}"; return output.ToLower(); } -} +} \ No newline at end of file diff --git a/tests/OrasProject.Oras.Tests/Content/ContentTest.cs b/tests/OrasProject.Oras.Tests/Content/ContentTest.cs index 1a583e8..d39c937 100644 --- a/tests/OrasProject.Oras.Tests/Content/ContentTest.cs +++ b/tests/OrasProject.Oras.Tests/Content/ContentTest.cs @@ -12,6 +12,7 @@ // limitations under the License. using OrasProject.Oras.Content; +using OrasProject.Oras.Exceptions; using System.Text; using Xunit; @@ -19,6 +20,7 @@ namespace OrasProject.Oras.Tests.Content; public class CalculateDigest { + /// /// This method tests if the digest is calculated properly /// @@ -30,4 +32,39 @@ public void VerifiesIfDigestMatches() var calculateHelloWorldDigest = Digest.ComputeSHA256(content); Assert.Equal(helloWorldDigest, calculateHelloWorldDigest); } + + /// + /// This method tests if the digest validation passes for registered algorithms + /// + [Theory] + [InlineData("sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b")] + [InlineData("sha512:401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b372742c513925d98f76b340d9e59a4efdc45db9f5c640a21831b3d08be")] + public void Validate_ReturnsDigest_ForRegisteredAlgorithms(string validDigest) + { + var result = Digest.Validate(validDigest); + Assert.Equal(validDigest, result); + } + + /// + /// This method tests if the digest validation throws an exception for unregistered or unsupported algorithms + /// + [Theory] + [InlineData("md5:098f6bcd4621d373cade4e832627b4f6")] // MD5, unregistered digest + [InlineData("sha1:3b8b5a6b79f6d1114a7b7e95b3e3bc74dd1b6a2a")] // SHA-1, unregistered digest + [InlineData("multihash+base58:QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8")] // Multihash, unregistered digest + public void Validate_ThrowsException_ForUnregisteredAlgorithms(string invalidDigest) + { + Assert.Throws(() => Digest.Validate(invalidDigest)); + } + + /// + /// This method tests if the digest validation throws an exception for various invalid digest formats + /// + [Theory] + [InlineData("sha256:")] // Missing encoded portion + [InlineData("sha256+b64u!LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564")] // Invalid character in encoded portion + public void Validate_ThrowsException_ForInvalidDigestFormats(string invalidDigest) + { + Assert.Throws(() => Digest.Validate(invalidDigest)); + } }