Skip to content

Commit

Permalink
Implement {Try}HashData on asymmetric algorithms
Browse files Browse the repository at this point in the history
Historically, the asymmetric algorithm base classes have had the hashing routines as abstract (or virtual+throw).

Now the base classes provide an implementation for these methods, reducing the amount of redundant effort on the part of derived types.
  • Loading branch information
vcsjones authored Mar 24, 2022
1 parent 5705c98 commit 5697987
Show file tree
Hide file tree
Showing 31 changed files with 355 additions and 223 deletions.
12 changes: 1 addition & 11 deletions src/libraries/Common/src/System/Security/Cryptography/DSACng.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace System.Security.Cryptography
{
public sealed partial class DSACng : DSA
public sealed partial class DSACng : DSA, IRuntimeAlgorithm
{
/// <summary>
/// Create a DSACng algorithm with a random 2048 bit key pair.
Expand Down Expand Up @@ -45,16 +45,6 @@ public override KeySizes[] LegalKeySizes
public override string SignatureAlgorithm => "DSA";
public override string? KeyExchangeAlgorithm => null;

// Need to override since base methods throw a "override me" exception: makes SignData/VerifyData function.
protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> source, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, source, destination, out bytesWritten);

private void ForceSetKeySize(int newKeySize)
{
// Our LegalKeySizes value stores the values that we encoded as being the correct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace System.Security.Cryptography
{
public sealed partial class DSAOpenSsl : DSA
public sealed partial class DSAOpenSsl : DSA, IRuntimeAlgorithm
{
// The biggest key allowed by FIPS 186-4 has N=256 (bit), which
// maximally produces a 72-byte DER signature.
Expand Down Expand Up @@ -193,23 +193,6 @@ private SafeDsaHandle GenerateKey()
return key;
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
{
// we're sealed and the base should have checked this already
Debug.Assert(data != null);
Debug.Assert(offset >= 0 && offset <= data.Length);
Debug.Assert(count >= 0 && count <= data.Length);
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

return HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));
}

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

public override byte[] CreateSignature(byte[] rgbHash!!)
{
SafeDsaHandle key = GetKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Security.Cryptography
{
internal static partial class DSAImplementation
{
public sealed partial class DSASecurityTransforms : DSA
public sealed partial class DSASecurityTransforms : DSA, IRuntimeAlgorithm
{
private SecKeyPair? _keys;
private bool _disposed;
Expand Down Expand Up @@ -118,12 +118,6 @@ protected override byte[] HashData(byte[] data, int offset, int count, HashAlgor
return HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));
}

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

protected override void Dispose(bool disposing)
{
if (disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.Security.Cryptography
{
internal static partial class ECDsaImplementation
{
public sealed partial class ECDsaAndroid : ECDsa
public sealed partial class ECDsaAndroid : ECDsa, IRuntimeAlgorithm
{
// secp521r1 maxes out at 139 bytes, so 256 should always be enough
private const int SignatureStackBufSize = 256;
Expand Down Expand Up @@ -240,15 +240,6 @@ protected override bool VerifyHashCore(
return verifyResult == 1;
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

protected override void Dispose(bool disposing)
{
if (disposing)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace System.Security.Cryptography
{
public sealed partial class ECDsaCng : ECDsa
public sealed partial class ECDsaCng : ECDsa, IRuntimeAlgorithm
{
/// <summary>
/// Create an ECDsaCng algorithm with a named curve.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace System.Security.Cryptography
{
public sealed partial class ECDsaOpenSsl : ECDsa
public sealed partial class ECDsaOpenSsl : ECDsa, IRuntimeAlgorithm
{
// secp521r1 maxes out at 139 bytes, so 256 should always be enough
private const int SignatureStackBufSize = 256;
Expand Down Expand Up @@ -250,15 +250,6 @@ protected override bool VerifyHashCore(
return verifyResult == 1;
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

protected override void Dispose(bool disposing)
{
if (disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Security.Cryptography
{
internal static partial class ECDsaImplementation
{
public sealed partial class ECDsaSecurityTransforms : ECDsa
public sealed partial class ECDsaSecurityTransforms : ECDsa, IRuntimeAlgorithm
{
private readonly EccSecurityTransforms _ecc = new EccSecurityTransforms(nameof(ECDsa));

Expand Down Expand Up @@ -135,15 +135,6 @@ public override bool VerifyHash(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> sign
Interop.AppleCrypto.PAL_SignatureAlgorithm.EC);
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> source, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, source, destination, out bytesWritten);

private void ThrowIfDisposed()
{
_ecc.ThrowIfDisposed();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Formats.Asn1;
using System.Numerics;

namespace System.Security.Cryptography
{
// Marker interface that goes on runtime-provided algorithms.
internal interface IRuntimeAlgorithm
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace System.Security.Cryptography
{
internal static partial class RSAImplementation
{
public sealed partial class RSAAndroid : RSA
public sealed partial class RSAAndroid : RSA, IRuntimeAlgorithm
{
private const int BitsPerByte = 8;

Expand Down Expand Up @@ -647,15 +647,6 @@ private SafeRsaHandle GenerateKey()
return key;
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
{
ArgumentNullException.ThrowIfNull(hash);
Expand Down
11 changes: 1 addition & 10 deletions src/libraries/Common/src/System/Security/Cryptography/RSACng.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace System.Security.Cryptography
{
public sealed partial class RSACng : RSA
public sealed partial class RSACng : RSA, IRuntimeAlgorithm
{
/// <summary>
/// Create an RSACng algorithm with a random 2048 bit key pair.
Expand Down Expand Up @@ -45,15 +45,6 @@ public override KeySizes[] LegalKeySizes
}
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

private void ForceSetKeySize(int newKeySize)
{
// Our LegalKeySizes value stores the values that we encoded as being the correct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace System.Security.Cryptography
{
public sealed partial class RSAOpenSsl : RSA
public sealed partial class RSAOpenSsl : RSA, IRuntimeAlgorithm
{
private const int BitsPerByte = 8;

Expand Down Expand Up @@ -717,15 +717,6 @@ private SafeEvpPKeyHandle GenerateKey()
return Interop.Crypto.RsaGenerateKey(KeySize);
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
{
ArgumentNullException.ThrowIfNull(hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace System.Security.Cryptography
{
internal static partial class RSAImplementation
{
public sealed partial class RSASecurityTransforms : RSA
public sealed partial class RSASecurityTransforms : RSA, IRuntimeAlgorithm
{
private SecKeyPair? _keys;

Expand Down Expand Up @@ -555,15 +555,6 @@ public override bool VerifyHash(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> sign
throw new CryptographicException(SR.Cryptography_InvalidPaddingMode);
}

protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, new ReadOnlySpan<byte>(data, offset, count));

protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
HashOneShotHelpers.HashData(hashAlgorithm, data);

protected override bool TryHashData(ReadOnlySpan<byte> data, Span<byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
HashOneShotHelpers.TryHashData(hashAlgorithm, data, destination, out bytesWritten);

protected override void Dispose(bool disposing)
{
if (disposing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ public static void TestShimProperties()
}

[Fact]
public static void TestShimOverloads()
public static void TestShimOverrides()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(AesCryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(AesCryptoServiceProvider));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public static void TestShimProperties()

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Only Unix has _impl shim pattern
public static void TestShimOverloads_Unix()
public static void TestShimOverrides_Unix()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(DESCryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(DESCryptoServiceProvider));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,9 @@ public static void SignatureAlgorithm_Success()

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Only Unix has _impl shim pattern
public static void TestShimOverloads_Unix()
public static void TestShimOverrides_Unix()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(DSACryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(DSACryptoServiceProvider));
}

private sealed class DsaKeyLifetime : IDisposable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ public static void TestShimProperties()

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Only Unix has _impl shim pattern
public static void TestShimOverloads_Unix()
public static void TestShimOverrides_Unix()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(RC2CryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(RC2CryptoServiceProvider));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ public static void SignData_VerifyHash_CaseInsensitive_Success()

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Only Unix has _impl shim pattern
public static void TestShimOverloads_Unix()
public static void TestShimOverrides_Unix()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(RSACryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(RSACryptoServiceProvider));
}

private sealed class RsaKeyLifetime : IDisposable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static void TestSymmetricAlgorithmProperties(SymmetricAlgorithm alg, int
}

// Shims should override all virtual members and forward to their _impl.
public static void VerifyAllBaseMembersOverloaded(Type shimType)
public static void VerifyAllBaseMembersOverridden(Type shimType)
{
string[] namesToNotVerify =
{
Expand All @@ -65,6 +65,8 @@ public static void VerifyAllBaseMembersOverloaded(Type shimType)
"ExportPkcs8PrivateKey",
"ExportEncryptedPkcs8PrivateKey",
"ExportRSAPrivateKey",
"HashData",
"TryHashData",
"TryExportRSAPrivateKey",
"TryExportRSAPublicKey",
"TryExportSubjectPublicKeyInfo",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ public static void TestShimProperties()
}

[Fact]
public static void TestShimOverloads()
public static void TestShimOverrides()
{
ShimHelpers.VerifyAllBaseMembersOverloaded(typeof(TripleDESCryptoServiceProvider));
ShimHelpers.VerifyAllBaseMembersOverridden(typeof(TripleDESCryptoServiceProvider));
}
}
}
Loading

0 comments on commit 5697987

Please sign in to comment.