Skip to content

Commit 378c072

Browse files
feature/crypto-extensions (#90)
Added `GetHash` function to `PublicKey`, and implemented `Parse` and `TryParse` functions for `NamedHash`.
1 parent 9813ee8 commit 378c072

File tree

7 files changed

+133
-5
lines changed

7 files changed

+133
-5
lines changed

OnixLabs.Playground/Program.cs

+8
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,19 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System;
16+
using OnixLabs.Security.Cryptography;
17+
1518
namespace OnixLabs.Playground;
1619

1720
internal static class Program
1821
{
1922
private static void Main()
2023
{
24+
string value = "SHA256:043a718774c572bd8a25adbeb1bfcd5c0256ae11cecf9f9c3f925d0e52beaf89";
25+
26+
NamedHash hash = NamedHash.Parse(value);
27+
28+
Console.WriteLine(hash);
2129
}
2230
}

OnixLabs.Security.Cryptography.UnitTests/NamedHashTests.cs

+28
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System;
1516
using System.Security.Cryptography;
1617
using Xunit;
1718

@@ -33,4 +34,31 @@ public void NamedHashToStringShouldProduceExpectedResult()
3334
// Then
3435
Assert.Equal(expected, actual);
3536
}
37+
38+
[Fact(DisplayName = "NamedHash.Parse should produce the expected result")]
39+
public void NamedHashParseShouldProduceExpectedResult()
40+
{
41+
// Given
42+
const string expected = "SHA256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";
43+
44+
// When
45+
NamedHash hash = NamedHash.Parse(expected);
46+
string actual = hash.ToString();
47+
48+
// Then
49+
Assert.Equal(expected, actual);
50+
}
51+
52+
[Fact(DisplayName = "NamedHash.Parse should throw FormatException")]
53+
public void NamedHashParseShouldThrowFormatException()
54+
{
55+
// Given
56+
const string expected = "SHA256:InvalidData";
57+
58+
// When
59+
Exception exception = Assert.Throws<FormatException>(() => NamedHash.Parse(expected));
60+
61+
// Then
62+
Assert.Equal("The input string 'SHA256:InvalidData' was not in a correct format.", exception.Message);
63+
}
3664
}

OnixLabs.Security.Cryptography.UnitTests/PublicKeyTests.cs

+16
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System.Security.Cryptography;
1516
using OnixLabs.Security.Cryptography.UnitTests.Data;
1617
using Xunit;
1718

@@ -120,4 +121,19 @@ public void DifferentPublicKeyValuesShouldProduceDifferentPublicKeyCodes()
120121
// Then
121122
Assert.NotEqual(leftHashCode, rightHashCode);
122123
}
124+
125+
[Fact(DisplayName = "PublicKey.GetHash should produce the expected result")]
126+
public void PublicKeyGetHashShouldProduceTheExpectedResult()
127+
{
128+
// Given
129+
const string expected = "9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a";
130+
PublicKey publicKey = new TestPublicKey([1, 2, 3, 4]);
131+
132+
// When
133+
Hash hash = publicKey.GetHash(SHA256.Create());
134+
string actual = hash.ToString();
135+
136+
// then
137+
Assert.Equal(expected, actual);
138+
}
123139
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Diagnostics.CodeAnalysis;
17+
18+
namespace OnixLabs.Security.Cryptography;
19+
20+
public readonly partial record struct NamedHash
21+
{
22+
public static NamedHash Parse(string value, IFormatProvider? provider = null) => Parse(value.AsSpan(), provider);
23+
24+
public static NamedHash Parse(ReadOnlySpan<char> value, IFormatProvider? provider = null)
25+
{
26+
if (TryParse(value, provider, out NamedHash result)) return result;
27+
throw new FormatException($"The input string '{value}' was not in a correct format.");
28+
}
29+
30+
public static bool TryParse([NotNullWhen(true)] string? value, IFormatProvider? provider, out NamedHash result) => TryParse(value.AsSpan(), provider, out result);
31+
32+
public static bool TryParse(ReadOnlySpan<char> value, IFormatProvider? provider, out NamedHash result)
33+
{
34+
result = default;
35+
36+
int index = value.IndexOf(Separator);
37+
38+
if (index < 0) return false;
39+
40+
ReadOnlySpan<char> name = value[..index];
41+
ReadOnlySpan<char> data = value[(index + 1)..];
42+
43+
if (name.IsEmpty || data.IsEmpty) return false;
44+
45+
bool isDecoded = Hash.TryParse(data, provider, out Hash hash);
46+
47+
result = new NamedHash(hash, name.ToString());
48+
49+
return isDecoded;
50+
}
51+
}

OnixLabs.Security.Cryptography/NamedHash.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using System;
1516
using System.Security.Cryptography;
16-
using OnixLabs.Core;
1717

1818
namespace OnixLabs.Security.Cryptography;
1919

2020
/// <summary>
2121
/// Represents a named cryptographic hash.
2222
/// </summary>
23-
public readonly partial record struct NamedHash : ICryptoPrimitive<NamedHash>, ISpanBinaryConvertible
23+
public readonly partial record struct NamedHash : ICryptoPrimitive<NamedHash>, ISpanParsable<NamedHash>
2424
{
2525
private const string Separator = ":";
2626
private const string HashAlgorithmNameNullOrWhiteSpace = "Hash algorithm name must not be null or whitespace.";

OnixLabs.Security.Cryptography/NamedPublicKey.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
using OnixLabs.Core;
16-
1715
namespace OnixLabs.Security.Cryptography;
1816

1917
/// <summary>
2018
/// Represents a named cryptographic public key.
2119
/// </summary>
22-
public readonly partial record struct NamedPublicKey : ICryptoPrimitive<NamedPublicKey>, ISpanBinaryConvertible
20+
public readonly partial record struct NamedPublicKey : ICryptoPrimitive<NamedPublicKey>
2321
{
2422
private const string Separator = ":";
2523
private const string KeyAlgorithmNameNullOrWhiteSpace = "Key algorithm name must not be null or whitespace.";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2020 ONIXLabs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System.Security.Cryptography;
16+
17+
namespace OnixLabs.Security.Cryptography;
18+
19+
public abstract partial class PublicKey
20+
{
21+
/// <summary>
22+
/// Gets a <see cref="Hash"/> representation of the current <see cref="PublicKey"/> instance.
23+
/// </summary>
24+
/// <param name="algorithm">The <see cref="HashAlgorithm"/> that will be used to hash the public key data.</param>
25+
/// <returns>Returns a <see cref="Hash"/> representation of the current <see cref="PublicKey"/> instance.</returns>
26+
public Hash GetHash(HashAlgorithm algorithm) => Hash.Compute(algorithm, KeyData);
27+
}

0 commit comments

Comments
 (0)