Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improve AesCtr documentation #169

Merged
merged 1 commit into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 36 additions & 35 deletions AesExtra/AesCmac.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Dorssel.Security.Cryptography;
/// <summary>
/// Computes a Cipher-based Message Authentication Code (CMAC) by using the symmetric key AES block cipher.
/// </summary>
/// <seealso href="https://csrc.nist.gov/publications/detail/sp/800-38b/final"/>
/// <seealso href="https://www.rfc-editor.org/rfc/rfc4493.html"/>
public sealed class AesCmac
: KeyedHashAlgorithm
{
Expand Down Expand Up @@ -343,6 +345,7 @@ static async ValueTask UncheckedOneShotAsync(byte[] key, Stream source, Memory<b
}
}

/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
static void ThrowIfInvalidKey(ReadOnlySpan<byte> key)
{
if (key.Length is not (16 or 24 or 32))
Expand All @@ -351,6 +354,8 @@ static void ThrowIfInvalidKey(ReadOnlySpan<byte> key)
}
}

/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
static void ThrowIfInvalidKey(byte[] key)
{
if (key is null)
Expand All @@ -360,6 +365,7 @@ static void ThrowIfInvalidKey(byte[] key)
ThrowIfInvalidKey(key.AsSpan());
}

/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
static void ThrowIfInvalidSource(byte[] source)
{
if (source is null)
Expand All @@ -368,6 +374,8 @@ static void ThrowIfInvalidSource(byte[] source)
}
}

/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
static void ThrowIfInvalidSource(Stream source)
{
if (source is null)
Expand All @@ -380,6 +388,10 @@ static void ThrowIfInvalidSource(Stream source)
}
}

/// <exception cref="ArgumentException">
/// The buffer in <paramref name="destination"/> is too small to hold the calculated CMAC.
/// The AES-CMAC algorithm always produces a 128-bit CMAC, or 16 bytes.
/// </exception>
static void ThrowIfInvalidDestination(Span<byte> destination)
{
if (destination.Length < BLOCKSIZE)
Expand All @@ -395,11 +407,14 @@ static void ThrowIfInvalidDestination(Span<byte> destination)
/// <param name="source">The data to CMAC.</param>
/// <param name="destination">The buffer to receive the CMAC value.</param>
/// <param name="bytesWritten">When this method returns, the total number of bytes written into <paramref name="destination"/>.</param>
/// <returns><see langword="false"/> if <paramref name="destination"/> is too small to hold the calculated CMAC, <see langword="true"/> otherwise.</returns>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <returns>
/// <see langword="true"/> if <paramref name="destination"/> was large enough to receive the calculated CMAC; otherwise, <see langword="false"/>.
/// </returns>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
{
ThrowIfInvalidKey(key);

if (destination.Length < BLOCKSIZE)
{
bytesWritten = 0;
Expand All @@ -418,8 +433,8 @@ public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source
/// <param name="key">The CMAC key.</param>
/// <param name="source">The data to CMAC.</param>
/// <returns>The CMAC of the data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(byte[])"/>
/// <inheritdoc cref="ThrowIfInvalidSource(byte[])"/>
public static byte[] HashData(byte[] key, byte[] source)
{
ThrowIfInvalidKey(key);
Expand All @@ -436,7 +451,7 @@ public static byte[] HashData(byte[] key, byte[] source)
/// <param name="key">The CMAC key.</param>
/// <param name="source">The data to CMAC.</param>
/// <returns>The CMAC of the data.</returns>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source)
{
ThrowIfInvalidKey(key);
Expand All @@ -454,11 +469,8 @@ public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source)
/// <param name="source">The data to CMAC.</param>
/// <param name="destination">The buffer to receive the CMAC value.</param>
/// <returns>The total number of bytes written to <paramref name="destination"/>.</returns>
/// <exception cref="ArgumentException">
/// The buffer in <paramref name="destination"/> is too small to hold the calculated CMAC.
/// The AES-CMAC algorithm always produces a 256-bit CMAC, or 32 bytes.
/// </exception>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
/// <inheritdoc cref="ThrowIfInvalidDestination(Span{byte})"/>
public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination)
{
ThrowIfInvalidKey(key);
Expand All @@ -475,9 +487,8 @@ public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Sp
/// <param name="key">The CMAC key.</param>
/// <param name="source">The stream to CMAC.</param>
/// <returns>The CMAC of the data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(byte[])"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
public static byte[] HashData(byte[] key, Stream source)
{
ThrowIfInvalidKey(key);
Expand All @@ -494,9 +505,8 @@ public static byte[] HashData(byte[] key, Stream source)
/// <param name="key">The CMAC key.</param>
/// <param name="source">The stream to CMAC.</param>
/// <returns>The CMAC of the data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
public static byte[] HashData(ReadOnlySpan<byte> key, Stream source)
{
ThrowIfInvalidKey(key);
Expand All @@ -515,16 +525,9 @@ public static byte[] HashData(ReadOnlySpan<byte> key, Stream source)
/// <param name="source">The stream to CMAC.</param>
/// <param name="destination">The buffer to receive the CMAC value.</param>
/// <returns>The total number of bytes written to <paramref name="destination"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">
/// The buffer in <paramref name="destination"/> is too small to hold the calculated CMAC.
/// The AES-CMAC algorithm always produces a 256-bit CMAC, or 32 bytes.
///
/// -or-
///
/// <paramref name="source"/> does not support reading.
/// </exception>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
/// <inheritdoc cref="ThrowIfInvalidDestination(Span{byte})"/>
public static int HashData(ReadOnlySpan<byte> key, Stream source, Span<byte> destination)
{
ThrowIfInvalidKey(key);
Expand All @@ -543,16 +546,15 @@ public static int HashData(ReadOnlySpan<byte> key, Stream source, Span<byte> des
/// <param name="source">The stream to CMAC.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
/// <returns>The HMAC of the data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(byte[])"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
/// <exception cref="OperationCanceledException">The cancellation token was canceled. This exception is stored into the returned task.</exception>
/// <remarks>
/// This method stores in the task it returns all non-usage exceptions that the method's synchronous counterpart can throw.
/// If an exception is stored into the returned task, that exception will be thrown when the task is awaited.
/// Usage exceptions, such as <see cref="ArgumentException"/>, are still thrown synchronously.
/// For the stored exceptions, see the exceptions thrown by <see cref="HashData(byte[], Stream)"/>.
/// </remarks>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
public static async ValueTask<byte[]> HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default)
{
ThrowIfInvalidKey(key);
Expand All @@ -570,16 +572,15 @@ public static async ValueTask<byte[]> HashDataAsync(byte[] key, Stream source, C
/// <param name="source">The stream to CMAC.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
/// <returns>The HMAC of the data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
/// <exception cref="OperationCanceledException">The cancellation token was canceled. This exception is stored into the returned task.</exception>
/// <remarks>
/// This method stores in the task it returns all non-usage exceptions that the method's synchronous counterpart can throw.
/// If an exception is stored into the returned task, that exception will be thrown when the task is awaited.
/// Usage exceptions, such as <see cref="ArgumentException"/>, are still thrown synchronously.
/// For the stored exceptions, see the exceptions thrown by <see cref="HashData(ReadOnlySpan{byte}, Stream)"/>.
/// </remarks>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
public static async ValueTask<byte[]> HashDataAsync(ReadOnlyMemory<byte> key, Stream source, CancellationToken cancellationToken = default)
{
ThrowIfInvalidKey(key.Span);
Expand All @@ -599,16 +600,16 @@ public static async ValueTask<byte[]> HashDataAsync(ReadOnlyMemory<byte> key, St
/// <param name="destination">The buffer to receive the CMAC value.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
/// <returns>The total number of bytes written to <paramref name="destination"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="source"/> does not support reading.</exception>
/// <inheritdoc cref="ThrowIfInvalidKey(ReadOnlySpan{byte})"/>
/// <inheritdoc cref="ThrowIfInvalidSource(Stream)"/>
/// <inheritdoc cref="ThrowIfInvalidDestination(Span{byte})"/>
/// <exception cref="OperationCanceledException">The cancellation token was canceled. This exception is stored into the returned task.</exception>
/// <remarks>
/// This method stores in the task it returns all non-usage exceptions that the method's synchronous counterpart can throw.
/// If an exception is stored into the returned task, that exception will be thrown when the task is awaited.
/// Usage exceptions, such as <see cref="ArgumentException"/>, are still thrown synchronously.
/// For the stored exceptions, see the exceptions thrown by <see cref="HashData(ReadOnlySpan{byte}, ReadOnlySpan{byte}, Span{byte})"/>.
/// </remarks>
/// <exception cref="CryptographicException">The <paramref name="key"/> length is other than 16, 24, or 32 bytes (128, 192, or 256 bits).</exception>
public static async ValueTask<int> HashDataAsync(ReadOnlyMemory<byte> key, Stream source, Memory<byte> destination,
CancellationToken cancellationToken = default)
{
Expand Down
Loading
Loading