diff --git a/OnixLabs.Core.UnitTests/StringExtensionTests.cs b/OnixLabs.Core.UnitTests/StringExtensionTests.cs
new file mode 100644
index 0000000..614d237
--- /dev/null
+++ b/OnixLabs.Core.UnitTests/StringExtensionTests.cs
@@ -0,0 +1,117 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Xunit;
+
+namespace OnixLabs.Core.UnitTests
+{
+ public sealed class StringExtensionTests
+ {
+ [Theory(DisplayName = "SubstringBefore should return the expected result (char)")]
+ [InlineData("First:Second", "First", ':')]
+ [InlineData("12345+678910", "12345", '+')]
+ public void SubstringBeforeShouldReturnTheExpectedResultC(string value, string expected, char delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringBefore(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringBefore should return the expected result (string)")]
+ [InlineData("First:Second", "First", ":")]
+ [InlineData("12345+678910", "12345", "+")]
+ public void SubstringBeforeShouldReturnTheExpectedResultS(string value, string expected, string delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringBefore(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringBeforeLast should return the expected result (char)")]
+ [InlineData("First:Second:Third", "First:Second", ':')]
+ [InlineData("12345+678910+12345", "12345+678910", '+')]
+ public void SubstringBeforeLastShouldReturnTheExpectedResultC(string value, string expected, char delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringBeforeLast(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringBeforeLast should return the expected result (string)")]
+ [InlineData("First:Second:Third", "First:Second", ":")]
+ [InlineData("12345+678910+12345", "12345+678910", "+")]
+ public void SubstringBeforeLastShouldReturnTheExpectedResultS(string value, string expected, string delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringBeforeLast(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringAfter should return the expected result (char)")]
+ [InlineData("First:Second", "Second", ':')]
+ [InlineData("12345+678910", "678910", '+')]
+ public void SubstringAfterShouldReturnTheExpectedResultC(string value, string expected, char delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringAfter(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringAfter should return the expected result (string)")]
+ [InlineData("First:Second", "Second", ":")]
+ [InlineData("12345+678910", "678910", "+")]
+ public void SubstringAfterShouldReturnTheExpectedResultS(string value, string expected, string delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringAfter(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringAfterLast should return the expected result (char)")]
+ [InlineData("First:Second:Third", "Third", ':')]
+ [InlineData("12345+678910+12345", "12345", '+')]
+ public void SubstringAfterLastShouldReturnTheExpectedResultC(string value, string expected, char delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringAfterLast(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory(DisplayName = "SubstringAfterLast should return the expected result (string)")]
+ [InlineData("First:Second:Third", "Third", ":")]
+ [InlineData("12345+678910+12345", "12345", "+")]
+ public void SubstringAfterLastShouldReturnTheExpectedResultS(string value, string expected, string delimiter)
+ {
+ // Arrange / Act
+ string actual = value.SubstringAfterLast(delimiter);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+}
diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj
index 55772a8..8f94224 100644
--- a/OnixLabs.Core/OnixLabs.Core.csproj
+++ b/OnixLabs.Core/OnixLabs.Core.csproj
@@ -8,10 +8,11 @@
OnixLabs.Core
ONIXLabs
ONIXLabs Core API for .NET
- 1.0.0
+ 2.0.0
en
Copyright © ONIXLabs 2020-2021
https://github.com/onix-labs/onixlabs-dotnet
+ 2.0.0
@@ -19,4 +20,9 @@
bin\Debug\net5.0\OnixLabs.Core.xml
+
+ bin\Release\net5.0\OnixLabs.Core.xml
+ true
+
+
diff --git a/OnixLabs.Core/StringExtensions.cs b/OnixLabs.Core/StringExtensions.cs
new file mode 100644
index 0000000..e0c208a
--- /dev/null
+++ b/OnixLabs.Core/StringExtensions.cs
@@ -0,0 +1,207 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.ComponentModel;
+
+namespace OnixLabs.Core
+{
+ ///
+ /// Provides extension methods for strings.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class StringExtensions
+ {
+ ///
+ /// The value of an index not found.
+ ///
+ private const int IndexNotFound = -1;
+
+ ///
+ /// Returns a substring before the first occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Returns a substring before the first occurrence of the specified delimiter.
+ public static string SubstringBefore(
+ this string value,
+ char delimiter,
+ string? defaultValue = null)
+ {
+ int index = value.IndexOf(delimiter);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[..index]
+ };
+ }
+
+ ///
+ /// Returns a substring before the first occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Specifies the string comparison rule for the search.
+ /// Returns a substring before the first occurrence of the specified delimiter.
+ public static string SubstringBefore(
+ this string value,
+ string delimiter,
+ string? defaultValue = null,
+ StringComparison comparison = StringComparison.Ordinal)
+ {
+ int index = value.IndexOf(delimiter, comparison);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[..index]
+ };
+ }
+
+ ///
+ /// Returns a substring before the last occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Returns a substring before the last occurrence of the specified delimiter.
+ public static string SubstringBeforeLast(
+ this string value,
+ char delimiter,
+ string? defaultValue = null)
+ {
+ int index = value.LastIndexOf(delimiter);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[..index]
+ };
+ }
+
+ ///
+ /// Returns a substring before the last occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Specifies the string comparison rule for the search.
+ /// Returns a substring before the last occurrence of the specified delimiter.
+ public static string SubstringBeforeLast(
+ this string value,
+ string delimiter,
+ string? defaultValue = null,
+ StringComparison comparison = StringComparison.Ordinal)
+ {
+ int index = value.LastIndexOf(delimiter, comparison);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[..index]
+ };
+ }
+
+ ///
+ /// Returns a substring after the first occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Returns a substring after the first occurrence of the specified delimiter.
+ public static string SubstringAfter(
+ this string value,
+ char delimiter,
+ string? defaultValue = null)
+ {
+ int index = value.IndexOf(delimiter);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[(index + 1)..value.Length]
+ };
+ }
+
+ ///
+ /// Returns a substring after the first occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Specifies the string comparison rule for the search.
+ /// Returns a substring after the first occurrence of the specified delimiter.
+ public static string SubstringAfter(
+ this string value,
+ string delimiter,
+ string? defaultValue = null,
+ StringComparison comparison = StringComparison.Ordinal)
+ {
+ int index = value.IndexOf(delimiter, comparison);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[(index + delimiter.Length)..value.Length]
+ };
+ }
+
+ ///
+ /// Returns a substring after the last occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Returns a substring after the last occurrence of the specified delimiter.
+ public static string SubstringAfterLast(
+ this string value,
+ char delimiter,
+ string? defaultValue = null)
+ {
+ int index = value.LastIndexOf(delimiter);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[(index + 1)..value.Length]
+ };
+ }
+
+ ///
+ /// Returns a substring after the last occurrence of the specified delimiter.
+ ///
+ /// The original from which to obtain a sub-string.
+ /// The delimiter to find within the original string.
+ /// The value to return if the delimiter is not found, which defaults to the original string.
+ /// Specifies the string comparison rule for the search.
+ /// Returns a substring after the last occurrence of the specified delimiter.
+ public static string SubstringAfterLast(
+ this string value,
+ string delimiter,
+ string? defaultValue = null,
+ StringComparison comparison = StringComparison.Ordinal)
+ {
+ int index = value.LastIndexOf(delimiter, comparison);
+
+ return index switch
+ {
+ IndexNotFound => defaultValue ?? value,
+ _ => value[(index + delimiter.Length)..value.Length]
+ };
+ }
+ }
+}
diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs
index 022e921..b34f0f3 100644
--- a/OnixLabs.Core/Text/Base16.Equatable.cs
+++ b/OnixLabs.Core/Text/Base16.Equatable.cs
@@ -51,7 +51,7 @@ namespace OnixLabs.Core.Text
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(Base16 other)
{
- return other.value.SequenceEqual(value);
+ return other.Value.SequenceEqual(Value);
}
///
@@ -70,7 +70,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value);
+ return HashCode.Combine(Value);
}
}
}
diff --git a/OnixLabs.Core/Text/Base16.To.cs b/OnixLabs.Core/Text/Base16.To.cs
index 73cb131..47e054f 100644
--- a/OnixLabs.Core/Text/Base16.To.cs
+++ b/OnixLabs.Core/Text/Base16.To.cs
@@ -28,7 +28,7 @@ public readonly partial struct Base16
/// Returns a array that represents the current object.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -47,7 +47,7 @@ public string ToPlainTextString()
/// Returns a that represents the current object in plain text.
public string ToPlainTextString(Encoding encoding)
{
- return encoding.GetString(value);
+ return encoding.GetString(Value);
}
///
@@ -56,7 +56,7 @@ public string ToPlainTextString(Encoding encoding)
/// A that represents the current object.
public override string ToString()
{
- return Convert.ToHexString(value).ToLower();
+ return Convert.ToHexString(Value).ToLower();
}
}
}
diff --git a/OnixLabs.Core/Text/Base16.cs b/OnixLabs.Core/Text/Base16.cs
index 7a66bff..1dde93f 100644
--- a/OnixLabs.Core/Text/Base16.cs
+++ b/OnixLabs.Core/Text/Base16.cs
@@ -19,18 +19,18 @@ namespace OnixLabs.Core.Text
///
public readonly partial struct Base16
{
- ///
- /// The underlying value.
- ///
- private readonly byte[] value;
-
///
/// Initializes a new instance of the struct.
///
/// The underlying value.
private Base16(byte[] value)
{
- this.value = value;
+ Value = value;
}
+
+ ///
+ /// Gets the underlying value.
+ ///
+ private byte[] Value { get; }
}
}
diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs
index 340427e..0272094 100644
--- a/OnixLabs.Core/Text/Base32.Equatable.cs
+++ b/OnixLabs.Core/Text/Base32.Equatable.cs
@@ -51,9 +51,9 @@ namespace OnixLabs.Core.Text
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(Base32 other)
{
- return other.value.SequenceEqual(value)
- && other.alphabet == alphabet
- && other.padding == padding;
+ return other.Value.SequenceEqual(Value)
+ && other.Alphabet == Alphabet
+ && other.Padding == Padding;
}
///
@@ -72,7 +72,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value);
+ return HashCode.Combine(Value);
}
}
}
diff --git a/OnixLabs.Core/Text/Base32.To.cs b/OnixLabs.Core/Text/Base32.To.cs
index c449694..e4de54c 100644
--- a/OnixLabs.Core/Text/Base32.To.cs
+++ b/OnixLabs.Core/Text/Base32.To.cs
@@ -27,7 +27,7 @@ public readonly partial struct Base32
/// Returns a array that represents the current object.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -46,7 +46,7 @@ public string ToPlainTextString()
/// Returns a that represents the current object in plain text.
public string ToPlainTextString(Encoding encoding)
{
- return encoding.GetString(value);
+ return encoding.GetString(Value);
}
///
@@ -55,7 +55,7 @@ public string ToPlainTextString(Encoding encoding)
/// A that represents the current object.
public override string ToString()
{
- return Encode(value, alphabet.Alphabet, padding);
+ return Encode(Value, Alphabet.Alphabet, Padding);
}
}
}
diff --git a/OnixLabs.Core/Text/Base32.cs b/OnixLabs.Core/Text/Base32.cs
index 0a18f2c..1637779 100644
--- a/OnixLabs.Core/Text/Base32.cs
+++ b/OnixLabs.Core/Text/Base32.cs
@@ -20,31 +20,31 @@ namespace OnixLabs.Core.Text
public readonly partial struct Base32
{
///
- /// The underlying value.
+ /// Initializes a new instance of the struct.
///
- private readonly byte[] value;
+ /// The underlying value.
+ /// The alphabet that will be used for Base-32 encoding and decoding operations.
+ /// Determines whether padding should be applied for Base-32 encoding and decoding operations.
+ private Base32(byte[] value, Base32Alphabet alphabet, bool padding)
+ {
+ Value = value;
+ Alphabet = alphabet;
+ Padding = padding;
+ }
///
- /// The alphabet that will be used for Base-32 encoding and decoding operations.
+ /// Gets the underlying value.
///
- private readonly Base32Alphabet alphabet;
+ private byte[] Value { get; }
///
- /// Determines whether padding should be applied for Base-32 encoding and decoding operations.
+ /// Gets the alphabet that will be used for Base-32 encoding and decoding operations.
///
- private readonly bool padding;
+ private Base32Alphabet Alphabet { get; }
///
- /// Initializes a new instance of the struct.
+ /// Gets a value that determines whether padding should be applied for Base-32 encoding and decoding operations.
///
- /// The underlying value.
- /// The alphabet that will be used for Base-32 encoding and decoding operations.
- /// Determines whether padding should be applied for Base-32 encoding and decoding operations.
- private Base32(byte[] value, Base32Alphabet alphabet, bool padding)
- {
- this.value = value;
- this.alphabet = alphabet;
- this.padding = padding;
- }
+ private bool Padding { get; }
}
}
diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs
index 9e56587..844a4cf 100644
--- a/OnixLabs.Core/Text/Base58.Equatable.cs
+++ b/OnixLabs.Core/Text/Base58.Equatable.cs
@@ -51,8 +51,8 @@ namespace OnixLabs.Core.Text
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(Base58 other)
{
- return other.value.SequenceEqual(value)
- && other.alphabet == alphabet;
+ return other.Value.SequenceEqual(Value)
+ && other.Alphabet == Alphabet;
}
///
@@ -71,7 +71,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value);
+ return HashCode.Combine(Value);
}
}
}
diff --git a/OnixLabs.Core/Text/Base58.To.cs b/OnixLabs.Core/Text/Base58.To.cs
index 97d27c8..a9d47b4 100644
--- a/OnixLabs.Core/Text/Base58.To.cs
+++ b/OnixLabs.Core/Text/Base58.To.cs
@@ -27,7 +27,7 @@ public readonly partial struct Base58
/// Returns a array that represents the current object.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -36,8 +36,8 @@ public byte[] ToByteArray()
/// A that represents the current object, with a checksum.
public string ToStringWithChecksum()
{
- byte[] valueWithChecksum = AddChecksum(value);
- return Encode(valueWithChecksum, alphabet.Alphabet);
+ byte[] valueWithChecksum = AddChecksum(Value);
+ return Encode(valueWithChecksum, Alphabet.Alphabet);
}
///
@@ -56,7 +56,7 @@ public string ToPlainTextString()
/// Returns a that represents the current object in plain text.
public string ToPlainTextString(Encoding encoding)
{
- return encoding.GetString(value);
+ return encoding.GetString(Value);
}
@@ -66,7 +66,7 @@ public string ToPlainTextString(Encoding encoding)
/// A that represents the current object.
public override string ToString()
{
- return Encode(value, alphabet.Alphabet);
+ return Encode(Value, Alphabet.Alphabet);
}
}
}
diff --git a/OnixLabs.Core/Text/Base58.cs b/OnixLabs.Core/Text/Base58.cs
index 42028e4..0e8c674 100644
--- a/OnixLabs.Core/Text/Base58.cs
+++ b/OnixLabs.Core/Text/Base58.cs
@@ -19,16 +19,6 @@ namespace OnixLabs.Core.Text
///
public readonly partial struct Base58
{
- ///
- /// The underlying value.
- ///
- private readonly byte[] value;
-
- ///
- /// The alphabet that will be used for Base-58 encoding and decoding operations.
- ///
- private readonly Base58Alphabet alphabet;
-
///
/// Initializes a new instance of the struct.
///
@@ -36,8 +26,18 @@ public readonly partial struct Base58
/// The alphabet that will be used for Base-58 encoding and decoding operations.
private Base58(byte[] value, Base58Alphabet alphabet)
{
- this.value = value;
- this.alphabet = alphabet;
+ Value = value;
+ Alphabet = alphabet;
}
+
+ ///
+ /// Gets the underlying value.
+ ///
+ private byte[] Value { get; }
+
+ ///
+ /// Gets the alphabet that will be used for Base-58 encoding and decoding operations.
+ ///
+ private Base58Alphabet Alphabet { get; }
}
}
diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs
index d9cdcf4..302f1a2 100644
--- a/OnixLabs.Core/Text/Base64.Equatable.cs
+++ b/OnixLabs.Core/Text/Base64.Equatable.cs
@@ -51,7 +51,7 @@ namespace OnixLabs.Core.Text
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(Base64 other)
{
- return other.value.SequenceEqual(value);
+ return other.Value.SequenceEqual(Value);
}
///
@@ -70,7 +70,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value);
+ return HashCode.Combine(Value);
}
}
}
diff --git a/OnixLabs.Core/Text/Base64.To.cs b/OnixLabs.Core/Text/Base64.To.cs
index 831a46e..7eef932 100644
--- a/OnixLabs.Core/Text/Base64.To.cs
+++ b/OnixLabs.Core/Text/Base64.To.cs
@@ -28,7 +28,7 @@ public readonly partial struct Base64
/// Returns a array that represents the current object.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -47,7 +47,7 @@ public string ToPlainTextString()
/// Returns a that represents the current object in plain text.
public string ToPlainTextString(Encoding encoding)
{
- return encoding.GetString(value);
+ return encoding.GetString(Value);
}
///
@@ -56,7 +56,7 @@ public string ToPlainTextString(Encoding encoding)
/// A that represents the current object.
public override string ToString()
{
- return Convert.ToBase64String(value);
+ return Convert.ToBase64String(Value);
}
}
}
diff --git a/OnixLabs.Core/Text/Base64.cs b/OnixLabs.Core/Text/Base64.cs
index 051d05d..9c99edc 100644
--- a/OnixLabs.Core/Text/Base64.cs
+++ b/OnixLabs.Core/Text/Base64.cs
@@ -19,18 +19,18 @@ namespace OnixLabs.Core.Text
///
public readonly partial struct Base64
{
- ///
- /// The underlying value.
- ///
- private readonly byte[] value;
-
///
/// Initializes a new instance of the struct.
///
/// The underlying value.
private Base64(byte[] value)
{
- this.value = value;
+ Value = value;
}
+
+ ///
+ /// Gets the underlying value.
+ ///
+ private byte[] Value { get; }
}
}
diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj
index af40665..c26e393 100644
--- a/OnixLabs.Playground/OnixLabs.Playground.csproj
+++ b/OnixLabs.Playground/OnixLabs.Playground.csproj
@@ -8,6 +8,7 @@
+
diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs
index 26f430e..714fab0 100644
--- a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs
+++ b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs
@@ -39,5 +39,34 @@ public void DifferentHashesShouldNotBeConsideredEqual()
// Assert
Assert.NotEqual(a, b);
}
+
+ [Fact(DisplayName = "Parse should be able to parse a known hash")]
+ public void ParseShouldBeAbleToParseAKnownHash()
+ {
+ // Arrange
+ const string expected = "Sha2Hash256:dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f";
+
+ // Act
+ Hash hash = Hash.Parse(expected);
+ string actual = hash.ToStringWithAlgorithmType();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Fact(DisplayName = "Parse should be able to parse an unknown hash")]
+ public void ParseShouldBeAbleToParseAnUnknownHash()
+ {
+ // Arrange
+ const string value = "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f";
+ const string expected = "Unknown:dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f";
+
+ // Act
+ Hash hash = Hash.Parse(value);
+ string actual = hash.ToStringWithAlgorithmType();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
}
}
diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs
new file mode 100644
index 0000000..c1a9896
--- /dev/null
+++ b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs
@@ -0,0 +1,69 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Xunit;
+
+namespace OnixLabs.Security.Cryptography.UnitTests
+{
+ public sealed class HmacTests
+ {
+ [Fact(DisplayName = "Identical HMACs should be considered equal")]
+ public void IdenticalHashesShouldBeConsideredEqual()
+ {
+ // Arrange
+ Hmac a = Hmac.ComputeSha2Hmac256("abc", "key");
+ Hmac b = Hmac.ComputeSha2Hmac256("abc", "key");
+
+ // Assert
+ Assert.Equal(a, b);
+ }
+
+ [Fact(DisplayName = "Different HMACs should not be considered equal (different data)")]
+ public void DifferentHashesShouldNotBeConsideredEqualWithDifferentData()
+ {
+ // Arrange
+ Hmac a = Hmac.ComputeSha2Hmac256("abc", "key");
+ Hmac b = Hmac.ComputeSha2Hmac256("xyz", "key");
+
+ // Assert
+ Assert.NotEqual(a, b);
+ }
+
+ [Fact(DisplayName = "Different HMACs should not be considered equal (different keys)")]
+ public void DifferentHashesShouldNotBeConsideredEqualWithDifferentKeys()
+ {
+ // Arrange
+ Hmac a = Hmac.ComputeSha2Hmac256("abc", "key");
+ Hmac b = Hmac.ComputeSha2Hmac256("abc", "123");
+
+ // Assert
+ Assert.NotEqual(a, b);
+ }
+
+ [Fact(DisplayName = "Parse should be able to parse a known hash")]
+ public void ParseShouldBeAbleToParseAKnownHash()
+ {
+ // Arrange
+ const string expected =
+ "Sha2Hmac256:73ac6fa8599f4bde8dfee594c7f5f6ff03023b2d99ca71a7eccf729a8fc5c324:48656c6c6f2c20576f726c6421";
+
+ // Act
+ Hmac hash = Hmac.Parse(expected);
+ string actual = hash.ToStringWithAlgorithmType();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs
index 5750a94..706289c 100644
--- a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs
+++ b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs
@@ -51,7 +51,7 @@ namespace OnixLabs.Security.Cryptography
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(DigitalSignature other)
{
- return other.value.SequenceEqual(value);
+ return other.Value.SequenceEqual(Value);
}
///
@@ -70,7 +70,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value);
+ return HashCode.Combine(Value);
}
}
}
diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs
index 47e7fe1..acfe520 100644
--- a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs
+++ b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs
@@ -29,7 +29,7 @@ public readonly partial struct DigitalSignature
/// A byte array containing the underlying signed data.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -38,7 +38,7 @@ public byte[] ToByteArray()
/// Returns a value that represents the underlying signature data.
public Base16 ToBase16()
{
- return Base16.FromByteArray(value);
+ return Base16.FromByteArray(Value);
}
///
@@ -57,7 +57,7 @@ public Base32 ToBase32()
/// Returns a value that represents the underlying signature data.
public Base32 ToBase32(Base32Alphabet alphabet)
{
- return Base32.FromByteArray(value, alphabet);
+ return Base32.FromByteArray(Value, alphabet);
}
///
@@ -76,7 +76,7 @@ public Base58 ToBase58()
/// Returns a value that represents the underlying signature data.
public Base58 ToBase58(Base58Alphabet alphabet)
{
- return Base58.FromByteArray(value, alphabet);
+ return Base58.FromByteArray(Value, alphabet);
}
///
@@ -85,7 +85,7 @@ public Base58 ToBase58(Base58Alphabet alphabet)
/// Returns a value that represents the underlying signature data.
public Base64 ToBase64()
{
- return Base64.FromByteArray(value);
+ return Base64.FromByteArray(Value);
}
///
@@ -94,7 +94,7 @@ public Base64 ToBase64()
/// A that represents the current object.
public override string ToString()
{
- return Convert.ToHexString(value).ToLower();
+ return Convert.ToHexString(Value).ToLower();
}
}
}
diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.cs b/OnixLabs.Security.Cryptography/DigitalSignature.cs
index 159adea..c89644a 100644
--- a/OnixLabs.Security.Cryptography/DigitalSignature.cs
+++ b/OnixLabs.Security.Cryptography/DigitalSignature.cs
@@ -19,18 +19,18 @@ namespace OnixLabs.Security.Cryptography
///
public readonly partial struct DigitalSignature
{
- ///
- /// The underlying digitally signed data.
- ///
- private readonly byte[] value;
-
///
/// Initializes a new instance of the struct.
///
/// The digitally signed data.
private DigitalSignature(byte[] value)
{
- this.value = value;
+ Value = value;
}
+
+ ///
+ /// Gets the underlying digitally signed data.
+ ///
+ private byte[] Value { get; }
}
}
diff --git a/OnixLabs.Security.Cryptography/Hash.Equatable.cs b/OnixLabs.Security.Cryptography/Hash.Equatable.cs
index f7f25c1..9d30459 100644
--- a/OnixLabs.Security.Cryptography/Hash.Equatable.cs
+++ b/OnixLabs.Security.Cryptography/Hash.Equatable.cs
@@ -51,7 +51,8 @@ namespace OnixLabs.Security.Cryptography
/// true if the object is equal to this instance; otherwise, false.
public bool Equals(Hash other)
{
- return other.value.SequenceEqual(value) && other.AlgorithmType == AlgorithmType;
+ return other.AlgorithmType == AlgorithmType
+ && other.Value.SequenceEqual(Value);
}
///
@@ -61,7 +62,7 @@ public bool Equals(Hash other)
/// true if the object is equal to this instance; otherwise, false.
public override bool Equals(object? obj)
{
- return obj is Hash hash && Equals(hash);
+ return obj is Hash other && Equals(other);
}
///
@@ -70,7 +71,7 @@ public override bool Equals(object? obj)
/// A hash code for this instance.
public override int GetHashCode()
{
- return HashCode.Combine(value, AlgorithmType);
+ return HashCode.Combine(Value, AlgorithmType);
}
}
}
diff --git a/OnixLabs.Security.Cryptography/Hash.Parse.cs b/OnixLabs.Security.Cryptography/Hash.Parse.cs
index 9b3d8d0..6e22d53 100644
--- a/OnixLabs.Security.Cryptography/Hash.Parse.cs
+++ b/OnixLabs.Security.Cryptography/Hash.Parse.cs
@@ -13,6 +13,7 @@
// limitations under the License.
using System;
+using OnixLabs.Core;
namespace OnixLabs.Security.Cryptography
{
@@ -22,26 +23,81 @@ namespace OnixLabs.Security.Cryptography
public readonly partial struct Hash
{
///
- /// Converts a hexadecimal representation of a hash into a instance.
- /// This will create a hash of an unknown type.
+ /// Parses a hexadecimal representation of a hash into a instance.
///
/// A that contains a hash to convert.
+ /// The hash algorithm type of the hash.
/// A new instance.
- public static Hash Parse(string value)
+ public static Hash Parse(string value, HashAlgorithmType? type = null)
{
- return Parse(value, HashAlgorithmType.Unknown);
+ HashAlgorithmType parsedType = GetParsedHashAlgorithmType(value);
+ byte[] parsedValue = GetParsedHashValue(value);
+
+ if (type is not null)
+ {
+ CheckMatchingHashAlgorithms(parsedType, type);
+ }
+
+ return FromByteArray(parsedValue, parsedType);
}
///
- /// Converts a hexadecimal representation of a hash into a instance.
+ /// Attempts to parse a hexadecimal representation of a hash into a instance.
///
/// A that contains a hash to convert.
/// The hash algorithm type of the hash.
- /// A new instance.
- public static Hash Parse(string value, HashAlgorithmType type)
+ /// The result if conversion was successful.
+ /// Returns true if the hash conversion was successful; otherwise, false.
+ public static bool TryParse(string value, HashAlgorithmType? type, out Hash hash)
+ {
+ try
+ {
+ hash = Parse(value, type);
+ return true;
+ }
+ catch
+ {
+ hash = default;
+ return false;
+ }
+ }
+
+ ///
+ /// Parses a from the specified value.
+ ///
+ /// The hash value to parse.
+ /// Returns a from the specified value.
+ private static HashAlgorithmType GetParsedHashAlgorithmType(string value)
+ {
+ string defaultHashAlgorithmType = HashAlgorithmType.Unknown.Name;
+ string parsedType = value.SubstringBefore(':', defaultHashAlgorithmType);
+ return HashAlgorithmType.FromName(parsedType);
+ }
+
+ ///
+ /// Parses a array from the specified value.
+ ///
+ /// The hash value to parse.
+ /// Returns a array from the specified value.
+ private static byte[] GetParsedHashValue(string value)
+ {
+ string parsedValue = value.SubstringAfter(':');
+ return Convert.FromHexString(parsedValue);
+ }
+
+ ///
+ /// Checks that the parsed and specified instances match.
+ ///
+ /// The parsed to check.
+ /// The specified to check.
+ /// If the instances do not match.
+ private static void CheckMatchingHashAlgorithms(HashAlgorithmType parsed, HashAlgorithmType specified)
{
- byte[] bytes = Convert.FromHexString(value);
- return new Hash(bytes, type);
+ if (parsed != specified)
+ {
+ throw new InvalidOperationException(
+ $"The parsed hash algorithm type '{parsed}' does not match the expected hash algorithm type '{specified}'.");
+ }
}
}
}
diff --git a/OnixLabs.Security.Cryptography/Hash.To.cs b/OnixLabs.Security.Cryptography/Hash.To.cs
index 49c80d2..c2af356 100644
--- a/OnixLabs.Security.Cryptography/Hash.To.cs
+++ b/OnixLabs.Security.Cryptography/Hash.To.cs
@@ -29,7 +29,7 @@ public readonly partial struct Hash
/// A array containing the underlying hash data.
public byte[] ToByteArray()
{
- return value.Copy();
+ return Value.Copy();
}
///
@@ -38,7 +38,7 @@ public byte[] ToByteArray()
/// Returns a value that represents the underlying hash data.
public Base16 ToBase16()
{
- return Base16.FromByteArray(value);
+ return Base16.FromByteArray(Value);
}
///
@@ -57,7 +57,7 @@ public Base32 ToBase32()
/// Returns a value that represents the underlying hash data.
public Base32 ToBase32(Base32Alphabet alphabet)
{
- return Base32.FromByteArray(value, alphabet);
+ return Base32.FromByteArray(Value, alphabet);
}
///
@@ -76,7 +76,7 @@ public Base58 ToBase58()
/// Returns a value that represents the underlying hash data.
public Base58 ToBase58(Base58Alphabet alphabet)
{
- return Base58.FromByteArray(value, alphabet);
+ return Base58.FromByteArray(Value, alphabet);
}
///
@@ -85,7 +85,7 @@ public Base58 ToBase58(Base58Alphabet alphabet)
/// Returns a value that represents the underlying hash data.
public Base64 ToBase64()
{
- return Base64.FromByteArray(value);
+ return Base64.FromByteArray(Value);
}
///
@@ -94,7 +94,16 @@ public Base64 ToBase64()
/// A that represents the current object.
public override string ToString()
{
- return Convert.ToHexString(value).ToLower();
+ return Convert.ToHexString(Value).ToLower();
+ }
+
+ ///
+ /// Returns a that represents the current object, including the hash algorithm type.
+ ///
+ /// A that represents the current object, including the hash algorithm type.
+ public string ToStringWithAlgorithmType()
+ {
+ return $"{AlgorithmType.Name}:{ToString()}";
}
}
}
diff --git a/OnixLabs.Security.Cryptography/Hash.cs b/OnixLabs.Security.Cryptography/Hash.cs
index 99ca022..c97952c 100644
--- a/OnixLabs.Security.Cryptography/Hash.cs
+++ b/OnixLabs.Security.Cryptography/Hash.cs
@@ -19,11 +19,6 @@ namespace OnixLabs.Security.Cryptography
///
public readonly partial struct Hash
{
- ///
- /// The underlying hexadecimal value of the hash.
- ///
- private readonly byte[] value;
-
///
/// Initializes a new instance of the struct.
///
@@ -33,13 +28,18 @@ private Hash(byte[] value, HashAlgorithmType type)
{
type.VerifyHashLength(value);
- this.value = value;
AlgorithmType = type;
+ Value = value;
}
///
/// Gets the hash algorithm type of the hash.
///
public HashAlgorithmType AlgorithmType { get; }
+
+ ///
+ /// Gets the underlying value of the hash.
+ ///
+ private byte[] Value { get; }
}
}
diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs
new file mode 100644
index 0000000..a411c56
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs
@@ -0,0 +1,107 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Specifies values that define known hash algorithm types.
+ ///
+ public sealed partial class HashAlgorithmType
+ {
+ ///
+ /// An unknown hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Unknown = new(0, nameof(Unknown), UnknownLength, false);
+
+ ///
+ /// The MD5 hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Md5Hash = new(1, nameof(Md5Hash), 16, false);
+
+ ///
+ /// The SHA-1 hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha1Hash = new(2, nameof(Sha1Hash), 20, false);
+
+ ///
+ /// The SHA-2 256-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hash256 = new(3, nameof(Sha2Hash256), 32, false);
+
+ ///
+ /// The SHA-2 384-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hash384 = new(4, nameof(Sha2Hash384), 48, false);
+
+ ///
+ /// The SHA-2 512-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hash512 = new(5, nameof(Sha2Hash512), 64, false);
+
+ ///
+ /// The SHA-3 224-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Hash224 = new(6, nameof(Sha3Hash224), 28, false);
+
+ ///
+ /// The SHA-3 256-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Hash256 = new(7, nameof(Sha3Hash256), 32, false);
+
+ ///
+ /// The SHA-3 384-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Hash384 = new(8, nameof(Sha3Hash384), 48, false);
+
+ ///
+ /// The SHA-3 512-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Hash512 = new(9, nameof(Sha3Hash512), 64, false);
+
+ ///
+ /// The SHA-3 Shake 128-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Shake128 = new(10, nameof(Sha3Shake128), UnknownLength, false);
+
+ ///
+ /// The SHA-3 Shake 256-bit hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha3Shake256 = new(11, nameof(Sha3Shake256), UnknownLength, false);
+
+ ///
+ /// The MD5 HMAC keyed hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Md5Hmac = new(12, nameof(Md5Hmac), 16, true);
+
+ ///
+ /// The SHA-1 HMAC keyed hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha1Hmac = new(13, nameof(Sha1Hmac), 20, true);
+
+ ///
+ /// The SHA-2 256-bit HMAC keyed hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hmac256 = new(14, nameof(Sha2Hmac256), 32, true);
+
+ ///
+ /// The SHA-2 384-bit HMAC keyed hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hmac384 = new(15, nameof(Sha2Hmac384), 48, true);
+
+ ///
+ /// The SHA-2 512-bit HMAC keyed hash algorithm.
+ ///
+ public static readonly HashAlgorithmType Sha2Hmac512 = new(16, nameof(Sha2Hmac512), 64, true);
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Equatable.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Equatable.cs
new file mode 100644
index 0000000..2d99054
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Equatable.cs
@@ -0,0 +1,38 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Specifies values that define known hash algorithm types.
+ ///
+ public sealed partial class HashAlgorithmType
+ {
+ ///
+ /// Checks for equality between this and another .
+ /// This will return false if either this, or the other is .
+ ///
+ /// The object to check for equality.
+ ///
+ /// Returns true if this is equal to the other; otherwise, false.
+ /// If either is , this always returns false.
+ ///
+ public override bool Equals(HashAlgorithmType? other)
+ {
+ return !ReferenceEquals(this, Unknown)
+ && !ReferenceEquals(other, Unknown)
+ && base.Equals(other);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs
new file mode 100644
index 0000000..d53777e
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs
@@ -0,0 +1,98 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Security.Cryptography;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Specifies values that define known hash algorithm types.
+ ///
+ public sealed partial class HashAlgorithmType
+ {
+ ///
+ /// Gets the hash algorithm for this instance.
+ ///
+ /// Specifies the expected output hash length.
+ /// Returns a for this .
+ /// If the hash algorithm does not expect an output length.
+ /// If the hash algorithm is unknown.
+ public HashAlgorithm GetHashAlgorithm(int length = UnknownLength)
+ {
+ if (length != UnknownLength && Length > UnknownLength)
+ {
+ throw new ArgumentException($"Output length not expected for the specified hash algorithm: {Name}");
+ }
+
+ return Name switch
+ {
+ nameof(Md5Hash) => MD5.Create(),
+ nameof(Sha1Hash) => SHA1.Create(),
+ nameof(Sha2Hash256) => SHA256.Create(),
+ nameof(Sha2Hash384) => SHA384.Create(),
+ nameof(Sha2Hash512) => SHA512.Create(),
+ nameof(Sha3Hash224) => Sha3.CreateSha3Hash224(),
+ nameof(Sha3Hash256) => Sha3.CreateSha3Hash256(),
+ nameof(Sha3Hash384) => Sha3.CreateSha3Hash384(),
+ nameof(Sha3Hash512) => Sha3.CreateSha3Hash512(),
+ nameof(Sha3Shake128) => Sha3.CreateSha3Shake128(length),
+ nameof(Sha3Shake256) => Sha3.CreateSha3Shake256(length),
+ _ => throw new ArgumentException($"Hash algorithm '{Name}' is unknown.")
+ };
+ }
+
+ ///
+ /// Gets the keyed hash algorithm for this instance.
+ ///
+ /// The key that should be used by the keyed hash algorithm.
+ /// Returns a for this .
+ /// If the hash algorithm is unknown or is not a keyed hash algorithm.
+ public KeyedHashAlgorithm GetKeyedHashAlgorithm(byte[]? key = null)
+ {
+ if (!Keyed)
+ {
+ throw new ArgumentException($"Hash algorithm type '{Name}' is not a keyed hash algorithm.");
+ }
+
+ return Name switch
+ {
+ nameof(Md5Hmac) => key is null ? new HMACMD5() : new HMACMD5(key),
+ nameof(Sha1Hmac) => key is null ? new HMACSHA1() : new HMACSHA1(key),
+ nameof(Sha2Hmac256) => key is null ? new HMACSHA256() : new HMACSHA256(key),
+ nameof(Sha2Hmac384) => key is null ? new HMACSHA384() : new HMACSHA384(key),
+ nameof(Sha2Hmac512) => key is null ? new HMACSHA512() : new HMACSHA512(key),
+ _ => throw new ArgumentException($"Hash algorithm '{Name}' is unknown.")
+ };
+ }
+
+ ///
+ /// Gets the equivalent for this .
+ ///
+ /// Returns the equivalent for this .
+ /// If there is no corresponding equivalent for this .
+ public HashAlgorithmName GetHashAlgorithmName()
+ {
+ return Name switch
+ {
+ nameof(Md5Hash) => HashAlgorithmName.MD5,
+ nameof(Sha1Hash) => HashAlgorithmName.SHA1,
+ nameof(Sha2Hash256) => HashAlgorithmName.SHA256,
+ nameof(Sha2Hash384) => HashAlgorithmName.SHA384,
+ nameof(Sha2Hash512) => HashAlgorithmName.SHA512,
+ _ => throw new ArgumentException($"No corresponding {nameof(HashAlgorithmName)} for '{Name}'.")
+ };
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs
new file mode 100644
index 0000000..f5deb72
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs
@@ -0,0 +1,47 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Specifies values that define known hash algorithm types.
+ ///
+ public sealed partial class HashAlgorithmType
+ {
+ ///
+ /// Determines whether the length of a byte array is valid.
+ ///
+ /// The byte array to length check.
+ /// Returns true if the length of the byte array is valid; otherwise, false.
+ public bool IsValidHashLength(byte[] value)
+ {
+ return Length == -1 || Length == value.Length;
+ }
+
+ ///
+ /// Verifies that the length of a byte array is valid.
+ ///
+ /// The byte array to length check.
+ /// If the length of the byte array is invalid.
+ public void VerifyHashLength(byte[] value)
+ {
+ if (!IsValidHashLength(value))
+ {
+ throw new ArgumentException("The length of the hash is invalid.", nameof(value));
+ }
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs
index 1ed691f..20645f4 100644
--- a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs
+++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.Security.Cryptography;
using OnixLabs.Core;
namespace OnixLabs.Security.Cryptography
@@ -21,7 +19,7 @@ namespace OnixLabs.Security.Cryptography
///
/// Specifies values that define known hash algorithm types.
///
- public sealed class HashAlgorithmType : Enumeration
+ public sealed partial class HashAlgorithmType : Enumeration
{
///
/// A constant that defines an unknown hash algorithm length.
@@ -29,74 +27,16 @@ public sealed class HashAlgorithmType : Enumeration
public const int UnknownLength = -1;
///
- /// An unknown hash algorithm.
- ///
- public static readonly HashAlgorithmType Unknown = new(0, nameof(Unknown), UnknownLength);
-
- ///
- /// The MD5 hash algorithm.
- ///
- public static readonly HashAlgorithmType Md5Hash = new(1, nameof(Md5Hash), 16);
-
- ///
- /// The SHA-1 hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha1Hash = new(3, nameof(Sha1Hash), 20);
-
- ///
- /// The SHA-2 256-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha2Hash256 = new(4, nameof(Sha2Hash256), 32);
-
- ///
- /// The SHA-2 384-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha2Hash384 = new(5, nameof(Sha2Hash384), 48);
-
- ///
- /// The SHA-2 512-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha2Hash512 = new(6, nameof(Sha2Hash512), 64);
-
- ///
- /// The SHA-3 224-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Hash224 = new(7, nameof(Sha3Hash224), 28);
-
- ///
- /// The SHA-3 256-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Hash256 = new(8, nameof(Sha3Hash256), 32);
-
- ///
- /// The SHA-3 384-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Hash384 = new(9, nameof(Sha3Hash384), 48);
-
- ///
- /// The SHA-3 512-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Hash512 = new(10, nameof(Sha3Hash512), 64);
-
- ///
- /// The SHA-3 Shake 128-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Shake128 = new(11, nameof(Sha3Shake128), UnknownLength);
-
- ///
- /// The SHA-3 Shake 256-bit hash algorithm.
- ///
- public static readonly HashAlgorithmType Sha3Shake256 = new(12, nameof(Sha3Shake256), UnknownLength);
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The value of the hash algorithm type.
/// The name of the hash algorithm type.
/// The length in bytes of the hash algorithm type.
- private HashAlgorithmType(int value, string name, int length) : base(value, name)
+ /// Determines whether the algorithm is a keyed hash algorithm.
+ private HashAlgorithmType(int value, string name, int length, bool keyed) : base(value, name)
{
Length = length;
+ Keyed = keyed;
}
///
@@ -106,94 +46,8 @@ private HashAlgorithmType(int value, string name, int length) : base(value, name
public int Length { get; }
///
- /// Gets the hash algorithm for this instance.
- ///
- /// Specifies the expected output hash length.
- /// Returns a for this .
- /// If the hash algorithm does not expect an output length.
- /// If the hash algorithm is unknown.
- public HashAlgorithm GetHashAlgorithm(int length = UnknownLength)
- {
- if (length != UnknownLength && Length > UnknownLength)
- {
- throw new ArgumentException($"Output length not expected for the specified hash algorithm: {Name}");
- }
-
- return Name switch
- {
- nameof(Md5Hash) => MD5.Create(),
- nameof(Sha1Hash) => SHA1.Create(),
- nameof(Sha2Hash256) => SHA256.Create(),
- nameof(Sha2Hash384) => SHA384.Create(),
- nameof(Sha2Hash512) => SHA512.Create(),
- nameof(Sha3Hash224) => Sha3.CreateSha3Hash224(),
- nameof(Sha3Hash256) => Sha3.CreateSha3Hash256(),
- nameof(Sha3Hash384) => Sha3.CreateSha3Hash384(),
- nameof(Sha3Hash512) => Sha3.CreateSha3Hash512(),
- nameof(Sha3Shake128) => Sha3.CreateSha3Shake128(length),
- nameof(Sha3Shake256) => Sha3.CreateSha3Shake256(length),
- _ => throw new ArgumentException($"Unknown hash algorithm: {Name}.")
- };
- }
-
- ///
- /// Gets the equivalent for this .
- ///
- /// Returns the equivalent for this .
- /// If there is no corresponding equivalent for this .
- public HashAlgorithmName GetHashAlgorithmName()
- {
- return Name switch
- {
- nameof(Md5Hash) => HashAlgorithmName.MD5,
- nameof(Sha1Hash) => HashAlgorithmName.SHA1,
- nameof(Sha2Hash256) => HashAlgorithmName.SHA256,
- nameof(Sha2Hash384) => HashAlgorithmName.SHA384,
- nameof(Sha2Hash512) => HashAlgorithmName.SHA512,
- _ => throw new ArgumentException($"No corresponding {nameof(HashAlgorithmName)} for {Name}.")
- };
- }
-
- ///
- /// Determines whether the length of a byte array is valid.
- ///
- /// The byte array to length check.
- /// Returns true if the length of the byte array is valid; otherwise, false.
- public bool IsValidHashLength(byte[] value)
- {
- return Length == -1 || Length == value.Length;
- }
-
- ///
- /// Verifies that the length of a byte array is valid.
+ /// Gets a value that determines whether the algorithm is a keyed hash algorithm.
///
- /// The byte array to length check.
- /// If the length of the byte array is invalid.
- public void VerifyHashLength(byte[] value)
- {
- if (!IsValidHashLength(value))
- {
- throw new ArgumentException("The length of the hash is invalid.", nameof(value));
- }
- }
-
- ///
- /// Checks for equality between this and another .
- /// This will return false if either this, or the other is .
- ///
- /// The object to check for equality.
- ///
- /// Returns true if this is equal to the other; otherwise, false.
- /// If either is , this always returns false.
- ///
- public override bool Equals(HashAlgorithmType? other)
- {
- if (ReferenceEquals(this, Unknown) || ReferenceEquals(other, Unknown))
- {
- return false;
- }
-
- return base.Equals(other);
- }
+ public bool Keyed { get; }
}
}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs
new file mode 100644
index 0000000..d8a2105
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs
@@ -0,0 +1,62 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes an MD5 HMAC from the specified value and key.
+ /// This will use the default encoding to convert the input value and key into a byte array.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeMd5Hmac(string value, string key)
+ {
+ return ComputeMd5Hmac(value, key, Encoding.Default);
+ }
+
+ ///
+ /// Computes an MD5 HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeMd5Hmac(string value, string key, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeMd5Hmac(valueBytes, keyBytes);
+ }
+
+ ///
+ /// Computes an MD5 HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeMd5Hmac(byte[] value, byte[] key)
+ {
+ return ComputeHmac(value, key, HashAlgorithmType.Md5Hmac);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs
new file mode 100644
index 0000000..0f62496
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs
@@ -0,0 +1,62 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes a SHA-1 HMAC from the specified value and key.
+ /// This will use the default encoding to convert the input value and key into a byte array.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha1Hmac(string value, string key)
+ {
+ return ComputeSha1Hmac(value, key, Encoding.Default);
+ }
+
+ ///
+ /// Computes a SHA-1 HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha1Hmac(string value, string key, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeSha1Hmac(valueBytes, keyBytes);
+ }
+
+ ///
+ /// Computes a SHA-1 HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha1Hmac(byte[] value, byte[] key)
+ {
+ return ComputeHmac(value, key, HashAlgorithmType.Sha1Hmac);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs
new file mode 100644
index 0000000..f7d863d
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs
@@ -0,0 +1,62 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes a SHA-2 256-bit HMAC from the specified value and key.
+ /// This will use the default encoding to convert the input value and key into a byte array.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac256(string value, string key)
+ {
+ return ComputeSha2Hmac256(value, key, Encoding.Default);
+ }
+
+ ///
+ /// Computes a SHA-2 256-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac256(string value, string key, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeSha2Hmac256(valueBytes, keyBytes);
+ }
+
+ ///
+ /// Computes a SHA-2 256-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac256(byte[] value, byte[] key)
+ {
+ return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac256);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs
new file mode 100644
index 0000000..ac7e34f
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs
@@ -0,0 +1,62 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes a SHA-2 384-bit HMAC from the specified value and key.
+ /// This will use the default encoding to convert the input value and key into a byte array.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac384(string value, string key)
+ {
+ return ComputeSha2Hmac384(value, key, Encoding.Default);
+ }
+
+ ///
+ /// Computes a SHA-2 384-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac384(string value, string key, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeSha2Hmac384(valueBytes, keyBytes);
+ }
+
+ ///
+ /// Computes a SHA-2 384-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac384(byte[] value, byte[] key)
+ {
+ return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac384);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs
new file mode 100644
index 0000000..5c4eb3a
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs
@@ -0,0 +1,62 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes a SHA-2 512-bit HMAC from the specified value and key.
+ /// This will use the default encoding to convert the input value and key into a byte array.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac512(string value, string key)
+ {
+ return ComputeSha2Hmac512(value, key, Encoding.Default);
+ }
+
+ ///
+ /// Computes a SHA-2 512-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac512(string value, string key, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeSha2Hmac512(valueBytes, keyBytes);
+ }
+
+ ///
+ /// Computes a SHA-2 512-bit HMAC from the specified value and key.
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// Returns a of the input value and key.
+ public static Hmac ComputeSha2Hmac512(byte[] value, byte[] key)
+ {
+ return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac512);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.cs
new file mode 100644
index 0000000..da80dc7
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Compute.cs
@@ -0,0 +1,70 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Security.Cryptography;
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Computes a hashed message authentication code (HMAC).
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The hash algorithm type of the computed HMAC.
+ /// Returns a representing the specified value and key.
+ public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type)
+ {
+ return ComputeHmac(value, key, type, Encoding.Default);
+ }
+
+ ///
+ /// Computes a hashed message authentication code (HMAC).
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The hash algorithm type of the computed HMAC.
+ /// The encoding which will be used to convert the value and key into a byte array.
+ /// Returns a representing the specified value and key.
+ public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type, Encoding encoding)
+ {
+ byte[] valueBytes = encoding.GetBytes(value);
+ byte[] keyBytes = encoding.GetBytes(key);
+
+ return ComputeHmac(valueBytes, keyBytes, type);
+ }
+
+ ///
+ /// Computes a hashed message authentication code (HMAC).
+ ///
+ /// The value for which to compute a HMAC.
+ /// The key for which to compute a HMAC.
+ /// The hash algorithm type of the computed HMAC.
+ /// Returns a representing the specified value and key.
+ public static Hmac ComputeHmac(byte[] value, byte[] key, HashAlgorithmType type)
+ {
+ using KeyedHashAlgorithm algorithm = type.GetKeyedHashAlgorithm(key);
+
+ byte[] data = algorithm.ComputeHash(value);
+ Hash hash = Hash.FromByteArray(data, type);
+
+ return Create(hash, value);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Create.cs b/OnixLabs.Security.Cryptography/Hmac.Create.cs
new file mode 100644
index 0000000..395b682
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Create.cs
@@ -0,0 +1,33 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Creates a hashed message authentication code (HMAC).
+ ///
+ /// The representing the HMAC.
+ /// The underlying un-hashed data.
+ /// Returns a new instance.
+ public static Hmac Create(Hash hash, byte[] data)
+ {
+ return new Hmac(hash, data);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs
new file mode 100644
index 0000000..72608ec
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs
@@ -0,0 +1,77 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Linq;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac : IEquatable
+ {
+ ///
+ /// Performs an equality check between two object instances.
+ ///
+ /// Instance a.
+ /// Instance b.
+ /// True if the instances are equal; otherwise, false.
+ public static bool operator ==(Hmac a, Hmac b)
+ {
+ return Equals(a, b);
+ }
+
+ ///
+ /// Performs an inequality check between two object instances.
+ ///
+ /// Instance a.
+ /// Instance b.
+ /// True if the instances are not equal; otherwise, false.
+ public static bool operator !=(Hmac a, Hmac b)
+ {
+ return !Equals(a, b);
+ }
+
+ ///
+ /// Checks for equality between this instance and another object.
+ ///
+ /// The object to check for equality.
+ /// true if the object is equal to this instance; otherwise, false.
+ public bool Equals(Hmac other)
+ {
+ return other.Hash == Hash
+ && other.Data.SequenceEqual(Data);
+ }
+
+ ///
+ /// Checks for equality between this instance and another object.
+ ///
+ /// The object to check for equality.
+ /// true if the object is equal to this instance; otherwise, false.
+ public override bool Equals(object? obj)
+ {
+ return obj is Hmac other && Equals(other);
+ }
+
+ ///
+ /// Serves as a hash code function for this instance.
+ ///
+ /// A hash code for this instance.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Hash, Data);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Parse.cs b/OnixLabs.Security.Cryptography/Hmac.Parse.cs
new file mode 100644
index 0000000..e85dc1a
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Parse.cs
@@ -0,0 +1,63 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using OnixLabs.Core;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Parses a hexadecimal representation of a HMAC into a instance.
+ ///
+ /// A that contains a HMAC to convert.
+ /// The hash algorithm type of the HMAC.
+ /// A new instance.
+ public static Hmac Parse(string value, HashAlgorithmType? type = null)
+ {
+ string hashComponent = value.SubstringBeforeLast(':');
+ string dataComponent = value.SubstringAfterLast(':');
+
+ Hash hash = Hash.Parse(hashComponent, type);
+ byte[] data = Convert.FromHexString(dataComponent);
+
+ return Create(hash, data);
+ }
+
+ ///
+ /// Attempts to parse a hexadecimal representation of a HMAC into a instance.
+ ///
+ /// A that contains a HMAC to convert.
+ /// The hash algorithm type of the hash.
+ /// The result if conversion was successful.
+ /// Returns true if the hash conversion was successful; otherwise, false.
+ public static bool TryParse(string value, HashAlgorithmType? type, out Hmac hmac)
+ {
+ try
+ {
+ hmac = Parse(value, type);
+ return true;
+ }
+ catch
+ {
+ hmac = default;
+ return false;
+ }
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.To.cs b/OnixLabs.Security.Cryptography/Hmac.To.cs
new file mode 100644
index 0000000..de0eb00
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.To.cs
@@ -0,0 +1,42 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Returns a that represents the current object.
+ ///
+ /// A that represents the current object.
+ public override string ToString()
+ {
+ return $"{Hash}:{Convert.ToHexString(Data).ToLower()}";
+ }
+
+ ///
+ /// Returns a that represents the current object, including the hash algorithm type.
+ ///
+ /// A that represents the current object, including the hash algorithm type.
+ public string ToStringWithAlgorithmType()
+ {
+ return $"{Hash.AlgorithmType.Name}:{ToString()}";
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.Verify.cs b/OnixLabs.Security.Cryptography/Hmac.Verify.cs
new file mode 100644
index 0000000..36e7d55
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.Verify.cs
@@ -0,0 +1,89 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Security.Cryptography;
+using System.Text;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Determines whether the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The key to validate against this .
+ /// Returns true if this was created with the specified key; otherwise, false.
+ public bool IsValid(string key)
+ {
+ return IsValid(key, Encoding.Default);
+ }
+
+ ///
+ /// Determines whether the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The key to validate against this .
+ /// The encoding which will be used to convert the key into a byte array.
+ /// Returns true if this was created with the specified key; otherwise, false.
+ public bool IsValid(string key, Encoding encoding)
+ {
+ byte[] keyBytes = encoding.GetBytes(key);
+ return IsValid(keyBytes);
+ }
+
+ ///
+ /// Determines whether the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The key to validate against this .
+ /// Returns true if this was created with the specified key; otherwise, false.
+ public bool IsValid(byte[] key)
+ {
+ return this == ComputeHmac(Data, key, Hash.AlgorithmType);
+ }
+
+ ///
+ /// Verifies that the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The key to validate against this .
+ public void Verify(string key)
+ {
+ Verify(key, Encoding.Default);
+ }
+
+ ///
+ /// Verifies that the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The encoding which will be used to convert the key into a byte array.
+ /// The key to validate against this .
+ public void Verify(string key, Encoding encoding)
+ {
+ byte[] keyBytes = encoding.GetBytes(key);
+ Verify(keyBytes);
+ }
+
+ ///
+ /// Verifies that the hashed message authentication code (HMAC) was created with the specified key.
+ ///
+ /// The key to validate against this .
+ public void Verify(byte[] key)
+ {
+ if (!IsValid(key))
+ {
+ throw new CryptographicException("The HMAC was could not be verified with the specified key.");
+ }
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.cs
new file mode 100644
index 0000000..aa862e8
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/Hmac.cs
@@ -0,0 +1,50 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using OnixLabs.Core;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a hashed message authentication code (HMAC).
+ ///
+ public readonly partial struct Hmac
+ {
+ ///
+ /// Represents the underlying un-hashed data.
+ ///
+ private readonly byte[] data;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The representing the HMAC.
+ /// The underlying un-hashed data.
+ private Hmac(Hash hash, byte[] data)
+ {
+ Hash = hash;
+ this.data = data;
+ }
+
+ ///
+ /// Gets the representing the HMAC.
+ ///
+ public Hash Hash { get; }
+
+ ///
+ /// Gets the underlying un-hashed data.
+ ///
+ public byte[] Data => data.Copy();
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/KeyPair.Create.cs b/OnixLabs.Security.Cryptography/KeyPair.Create.cs
new file mode 100644
index 0000000..e21914a
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/KeyPair.Create.cs
@@ -0,0 +1,124 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Security.Cryptography;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a cryptographic public/private key pair.
+ ///
+ public sealed partial class KeyPair
+ {
+ ///
+ /// Creates an ECDSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type)
+ {
+ using ECDsa asymmetricAlgorithm = ECDsa.Create();
+
+ PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
+ PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+
+ ///
+ /// Creates an ECDSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// The curve to use for key generation.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECCurve curve)
+ {
+ using ECDsa asymmetricAlgorithm = ECDsa.Create(curve);
+
+ PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
+ PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+
+ ///
+ /// Creates an ECDSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// The parameters representing the key to use.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECParameters parameters)
+ {
+ using ECDsa asymmetricAlgorithm = ECDsa.Create(parameters);
+
+ PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
+ PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+
+ ///
+ /// Creates an RSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// The for computing signature data.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding)
+ {
+ using RSA asymmetricAlgorithm = RSA.Create();
+
+ PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
+ PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+
+ ///
+ /// Creates an RSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// The for computing signature data.
+ /// The key size, in bits.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding, int keySizeInBits)
+ {
+ using RSA asymmetricAlgorithm = RSA.Create(keySizeInBits);
+
+ PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
+ PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+
+ ///
+ /// Creates an RSA public/private key pair.
+ ///
+ /// The for computing signature data.
+ /// The for computing signature data.
+ /// The parameters for the RSA algorithm.
+ /// Returns an ECDSA public/private key pair.
+ public static KeyPair CreateRsaKeyPair(
+ HashAlgorithmType type,
+ RSASignaturePadding padding,
+ RSAParameters parameters)
+ {
+ using RSA asymmetricAlgorithm = RSA.Create(parameters);
+
+ PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
+ PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
+
+ return new KeyPair(privateKey, publicKey);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs
new file mode 100644
index 0000000..840af72
--- /dev/null
+++ b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs
@@ -0,0 +1,78 @@
+// Copyright 2020-2021 ONIXLabs
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+
+namespace OnixLabs.Security.Cryptography
+{
+ ///
+ /// Represents a cryptographic public/private key pair.
+ ///
+ public sealed partial class KeyPair : IEquatable
+ {
+ ///
+ /// Performs an equality check between two object instances.
+ ///
+ /// Instance a.
+ /// Instance b.
+ /// True if the instances are equal; otherwise, false.
+ public static bool operator ==(KeyPair a, KeyPair b)
+ {
+ return Equals(a, b);
+ }
+
+ ///
+ /// Performs an inequality check between two object instances.
+ ///
+ /// Instance a.
+ /// Instance b.
+ /// True if the instances are not equal; otherwise, false.
+ public static bool operator !=(KeyPair a, KeyPair b)
+ {
+ return !Equals(a, b);
+ }
+
+ ///
+ /// Checks for equality between this instance and another object.
+ ///
+ /// The object to check for equality.
+ /// true if the object is equal to this instance; otherwise, false.
+ public bool Equals(KeyPair? other)
+ {
+ return ReferenceEquals(this, other)
+ || other is not null
+ && other.PrivateKey == PrivateKey
+ && other.PublicKey == PublicKey;
+ }
+
+ ///
+ /// Checks for equality between this instance and another object.
+ ///
+ /// The object to check for equality.
+ /// true if the object is equal to this instance; otherwise, false.
+ public override bool Equals(object? obj)
+ {
+ return Equals(obj as KeyPair);
+ }
+
+ ///
+ /// Serves as a hash code function for this instance.
+ ///
+ /// A hash code for this instance.
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(PrivateKey, PublicKey);
+ }
+ }
+}
diff --git a/OnixLabs.Security.Cryptography/KeyPair.cs b/OnixLabs.Security.Cryptography/KeyPair.cs
index f1b4ca4..26b02bc 100644
--- a/OnixLabs.Security.Cryptography/KeyPair.cs
+++ b/OnixLabs.Security.Cryptography/KeyPair.cs
@@ -12,15 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using System;
-using System.Security.Cryptography;
-
namespace OnixLabs.Security.Cryptography
{
///
/// Represents a cryptographic public/private key pair.
///
- public sealed class KeyPair : IEquatable
+ public sealed partial class KeyPair
{
///
/// Prevents new instances of the class from being created.
@@ -42,168 +39,5 @@ private KeyPair(PrivateKey privateKey, PublicKey publicKey)
/// Gets the public key component of this key pair.
///
public PublicKey PublicKey { get; }
-
- ///
- /// Performs an equality check between two object instances.
- ///
- /// Instance a.
- /// Instance b.
- /// True if the instances are equal; otherwise, false.
- public static bool operator ==(KeyPair a, KeyPair b)
- {
- return Equals(a, b);
- }
-
- ///
- /// Performs an inequality check between two object instances.
- ///
- /// Instance a.
- /// Instance b.
- /// True if the instances are not equal; otherwise, false.
- public static bool operator !=(KeyPair a, KeyPair b)
- {
- return !Equals(a, b);
- }
-
- ///
- /// Creates an ECDSA public/private key pair.
- ///
- /// The for computing signature data.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type)
- {
- using ECDsa asymmetricAlgorithm = ECDsa.Create();
-
- PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
- PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Creates an ECDSA public/private key pair.
- ///
- /// The for computing signature data.
- /// The curve to use for key generation.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECCurve curve)
- {
- using ECDsa asymmetricAlgorithm = ECDsa.Create(curve);
-
- PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
- PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Creates an ECDSA public/private key pair.
- ///
- /// The for computing signature data.
- /// The parameters representing the key to use.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECParameters parameters)
- {
- using ECDsa asymmetricAlgorithm = ECDsa.Create(parameters);
-
- PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type);
- PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Creates an RSA public/private key pair.
- ///
- /// The for computing signature data.
- /// The for computing signature data.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding)
- {
- using RSA asymmetricAlgorithm = RSA.Create();
-
- PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
- PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Creates an RSA public/private key pair.
- ///
- /// The for computing signature data.
- /// The for computing signature data.
- /// The key size, in bits.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding, int keySizeInBits)
- {
- using RSA asymmetricAlgorithm = RSA.Create(keySizeInBits);
-
- PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
- PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Creates an RSA public/private key pair.
- ///
- /// The for computing signature data.
- /// The for computing signature data.
- /// The parameters for the RSA algorithm.
- /// Returns an ECDSA public/private key pair.
- public static KeyPair CreateRsaKeyPair(
- HashAlgorithmType type,
- RSASignaturePadding padding,
- RSAParameters parameters)
- {
- using RSA asymmetricAlgorithm = RSA.Create(parameters);
-
- PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding);
- PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding);
-
- return new KeyPair(privateKey, publicKey);
- }
-
- ///
- /// Checks for equality between this instance and another object.
- ///
- /// The object to check for equality.
- /// true if the object is equal to this instance; otherwise, false.
- public bool Equals(KeyPair? other)
- {
- return ReferenceEquals(this, other)
- || other is not null
- && other.PrivateKey == PrivateKey
- && other.PublicKey == PublicKey;
- }
-
- ///
- /// Checks for equality between this instance and another object.
- ///
- /// The object to check for equality.
- /// true if the object is equal to this instance; otherwise, false.
- public override bool Equals(object? obj)
- {
- return Equals(obj as KeyPair);
- }
-
- ///
- /// Serves as a hash code function for this instance.
- ///
- /// A hash code for this instance.
- public override int GetHashCode()
- {
- return HashCode.Combine(PrivateKey, PublicKey);
- }
-
- ///
- /// Returns a that represents the current object.
- ///
- /// A that represents the current object.
- public override string ToString()
- {
- return $"{PrivateKey}:{PublicKey}";
- }
}
}
diff --git a/OnixLabs.Security.Cryptography/MerkleTree.cs b/OnixLabs.Security.Cryptography/MerkleTree.cs
index df646e8..63a4bac 100644
--- a/OnixLabs.Security.Cryptography/MerkleTree.cs
+++ b/OnixLabs.Security.Cryptography/MerkleTree.cs
@@ -81,7 +81,7 @@ private static void CheckIfMerkleTreesAreEmpty(IEnumerable merkleTre
///
/// The to check.
/// if the elements of the do not have the same hash algorithm type.
- private static void CheckNodesHaveEqualHashAlgorithms(IReadOnlyList merkleTrees)
+ private static void CheckNodesHaveEqualHashAlgorithms(IEnumerable merkleTrees)
{
if (!merkleTrees.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType))
{
diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj
index 2764246..a6072a9 100644
--- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj
+++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj
@@ -5,12 +5,22 @@
OnixLabs.Security.Cryptography
ONIXLabs
ONIXLabs Cryptography API for .NET
- 1.0.0
+ 2.0.0
en
enable
true
Copyright © ONIXLabs 2020-2021
https://github.com/onix-labs/onixlabs-dotnet
+ 2.0.0
+
+
+
+ bin\Debug\net5.0\OnixLabs.Security.Cryptography.xml
+
+
+
+ bin\Release\net5.0\OnixLabs.Security.Cryptography.xml
+ true