diff --git a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json index a5899bb3f361..fb6df820c985 100644 --- a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json +++ b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json @@ -2001,7 +2001,8 @@ "BaselineVersion": "4.0.0", "AssemblyVersionInPackageVersion": { "4.0.0.0": "4.0.0", - "4.0.1.0": "4.3.0" + "4.0.1.0": "4.0.1", + "4.1.0.0": "4.3.0" } }, "System.Security.Cryptography.ProtectedData": { diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs index 3c422acbbcc0..6a3f6b7ff696 100644 --- a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs +++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs @@ -50,49 +50,18 @@ public static void SignAndVerifyDataExplicit2048() [Fact] public static void VerifyKnownSignature() { - // The parameters and signature come from FIPS 186-2 APPENDIX 5. EXAMPLE OF THE DSA using (DSA dsa = DSAFactory.Create()) { - DSAParameters dsaParameters = new DSAParameters - { - P = ( - "8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7" + - "cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac" + - "49693dfbf83724c2ec0736ee31c80291").HexToByteArray(), - - Q = ("c773218c737ec8ee993b4f2ded30f48edace915f").HexToByteArray(), - - G = ( - "626d027839ea0a13413163a55b4cb500299d5522956cefcb" + - "3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9c" + - "c42e9f6f464b088cc572af53e6d78802").HexToByteArray(), - - X = ("2070b3223dba372fde1c0ffc7b2e3b498b260614").HexToByteArray(), - - Y = ( - "19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a85" + - "9bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74" + - "858fba33f44c06699630a76b030ee333").HexToByteArray(), - }; - - byte[] signature = ( - // r - "8bac1ab66410435cb7181f95b16ab97c92b341c0" + - // s - "41e2345f1f56df2458f426d155b4ba2db6dcd8c8" - ).HexToByteArray(); - - byte[] data = Encoding.ASCII.GetBytes("abc"); + byte[] data; + byte[] signature; + DSAParameters dsaParameters; + DSATestData.GetDSA1024_186_2(out dsaParameters, out signature, out data); dsa.ImportParameters(dsaParameters); - Assert.True(dsa.VerifyData(data, signature, HashAlgorithmName.SHA1)); // Negative case - unchecked - { - --signature[signature.Length - 1]; - } + signature[signature.Length - 1] ^= 0xff; Assert.False(dsa.VerifyData(data, signature, HashAlgorithmName.SHA1)); } } diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs new file mode 100644 index 000000000000..fb6fbe8d78d3 --- /dev/null +++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; +using Xunit; + +namespace System.Security.Cryptography.Dsa.Tests +{ + public partial class DSASignatureFormatterTests : AsymmetricSignatureFormatterTests + { + [Fact] + public static void VerifySignature_SHA1() + { + using (DSA dsa = DSAFactory.Create()) + { + var formatter = new DSASignatureFormatter(dsa); + var deformatter = new DSASignatureDeformatter(dsa); + using (SHA1 alg = SHA1.Create()) + { + VerifySignature(formatter, deformatter, alg, "SHA1"); + VerifySignature(formatter, deformatter, alg, "sha1"); + } + } + } + + [Fact] + public static void InvalidHashAlgorithm() + { + using (DSA dsa = DSAFactory.Create()) + { + var formatter = new DSASignatureFormatter(dsa); + var deformatter = new DSASignatureDeformatter(dsa); + + // Unlike RSA, DSA will throw during SetHashAlgorithm + Assert.Throws(() => + formatter.SetHashAlgorithm("INVALIDVALUE")); + Assert.Throws(() => + deformatter.SetHashAlgorithm("INVALIDVALUE")); + + // Currently anything other than SHA1 fails + Assert.Throws(() => + formatter.SetHashAlgorithm("SHA256")); + Assert.Throws(() => + deformatter.SetHashAlgorithm("SHA256")); + } + } + + [Fact] + public static void VerifyKnownSignature() + { + using (DSA dsa = DSAFactory.Create()) + { + byte[] data; + byte[] signature; + DSAParameters dsaParameters; + DSATestData.GetDSA1024_186_2(out dsaParameters, out signature, out data); + + byte[] hash; + using (SHA1 alg = SHA1.Create()) + { + hash = alg.ComputeHash(data); + } + + dsa.ImportParameters(dsaParameters); + var deformatter = new DSASignatureDeformatter(dsa); + deformatter.VerifySignature(hash, signature); + + // Negative case + signature[signature.Length - 1] ^= 0xff; + Assert.False(deformatter.VerifySignature(hash, signature)); + } + } + + public static bool SupportsFips186_3 + { + get + { + return DSAFactory.SupportsFips186_3; + } + } + } +} diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSATestData.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSATestData.cs index 92c4fe35f6f1..f19707f74680 100644 --- a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSATestData.cs +++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSATestData.cs @@ -67,5 +67,33 @@ internal static DSAParameters GetDSA2048Params() "081025751572").HexToByteArray(); return p; } + + // The parameters and signature come from FIPS 186-2 APPENDIX 5. EXAMPLE OF THE DSA + internal static void GetDSA1024_186_2(out DSAParameters parameters, out byte[] signature, out byte[] data) + { + parameters = new DSAParameters() + { + P = ( + "8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac" + + "49693dfbf83724c2ec0736ee31c80291").HexToByteArray(), + Q = ("c773218c737ec8ee993b4f2ded30f48edace915f").HexToByteArray(), + G = ( + "626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9c" + + "c42e9f6f464b088cc572af53e6d78802").HexToByteArray(), + X = ("2070b3223dba372fde1c0ffc7b2e3b498b260614").HexToByteArray(), + Y = ( + "19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74" + + "858fba33f44c06699630a76b030ee333").HexToByteArray() + }; + + signature = ( + // r + "8bac1ab66410435cb7181f95b16ab97c92b341c0" + + // s + "41e2345f1f56df2458f426d155b4ba2db6dcd8c8" + ).HexToByteArray(); + + data = Encoding.ASCII.GetBytes("abc"); + } } } diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs new file mode 100644 index 000000000000..e17d5b9d4bdf --- /dev/null +++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Rsa.Tests +{ + public partial class RSAKeyExchangeFormatterTests + { + [Fact] + public static void VerifyDecryptKeyExchangeOaep() + { + using (RSA rsa = RSAFactory.Create()) + { + var formatter = new RSAOAEPKeyExchangeFormatter(rsa); + var deformatter = new RSAOAEPKeyExchangeDeformatter(rsa); + VerifyDecryptKeyExchange(formatter, deformatter); + } + } + + [Fact] + public static void VerifyDecryptKeyExchangePkcs1() + { + using (RSA rsa = RSAFactory.Create()) + { + var formatter = new RSAPKCS1KeyExchangeFormatter(rsa); + var deformatter = new RSAPKCS1KeyExchangeDeformatter(rsa); + VerifyDecryptKeyExchange(formatter, deformatter); + } + } + + [Fact] + public static void TestKnownValueOaep() + { + using (RSA rsa = RSAFactory.Create()) + { + rsa.ImportParameters(TestData.RSA1024Params); + byte[] encrypted = + ( "19134ffba4025a1c651120ca07258a46e005a327c3927f615465060734dc0339114cabfd13803288883abf9329296a3e3a5cb1587927" + + "a6e8a2e736f0a756e342b4adb0f1de5bba9ba5faee30456fb7409678eb71a70185606eda3303d9425fbeb730ab7803bea50e208b563f" + + "e9bfa97a8966deefb211a3bd6abe08cd15e0b927").HexToByteArray(); + RSAOAEPKeyExchangeDeformatter deformatter = new RSAOAEPKeyExchangeDeformatter(rsa); + byte[] plain = deformatter.DecryptKeyExchange(encrypted); + byte[] expectedPlain = { 0x41, 0x42, 0x43 }; + Assert.Equal(expectedPlain, plain); + } + } + + [Fact] + public static void TestKnownValuePkcs1() + { + using (RSA rsa = RSAFactory.Create()) + { + rsa.ImportParameters(TestData.RSA1024Params); + byte[] encrypted = + ( "7061adb87a8759f0a0dc6ece42f5b63bf186f845237c6b16bf824b303812486efbb8f5febb681902228a609d4330a6c21abf0fc0d271" + + "ba63d1d0d9e486668270c2dbf73ab33055dfc0b797938557b99c0e9a535605c0a4bceefe5a37594732bb566ab026e4e8d5ce47d0967d" + + "f1c66e7ee4d39d804f6d558670222d708f943eb0").HexToByteArray(); + RSAPKCS1KeyExchangeDeformatter deformatter = new RSAPKCS1KeyExchangeDeformatter(rsa); + byte[] plain = deformatter.DecryptKeyExchange(encrypted); + byte[] expectedPlain = { 0x41, 0x42, 0x43 }; + Assert.Equal(expectedPlain, plain); + } + } + + private static void VerifyDecryptKeyExchange(AsymmetricKeyExchangeFormatter formatter, AsymmetricKeyExchangeDeformatter deformatter) + { + byte[] encrypted = formatter.CreateKeyExchange(TestData.HelloBytes); + byte[] decrypted = deformatter.DecryptKeyExchange(encrypted); + Assert.Equal(TestData.HelloBytes, decrypted); + + encrypted[encrypted.Length - 1] ^= 0xff; + Assert.ThrowsAny(() => deformatter.DecryptKeyExchange(encrypted)); + } + } +} diff --git a/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs new file mode 100644 index 000000000000..9489c0a2144c --- /dev/null +++ b/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Rsa.Tests +{ + public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTests + { + [Fact] + public static void VerifySignature_SHA1() + { + using (RSA rsa = RSAFactory.Create()) + { + var formatter = new RSAPKCS1SignatureFormatter(rsa); + var deformatter = new RSAPKCS1SignatureDeformatter(rsa); + + using (SHA1 alg = SHA1.Create()) + { + VerifySignature(formatter, deformatter, alg, "SHA1"); + VerifySignature(formatter, deformatter, alg, "sha1"); + } + } + } + + [Fact] + public static void VerifySignature_SHA256() + { + using (RSA rsa = RSAFactory.Create()) + { + var formatter = new RSAPKCS1SignatureFormatter(rsa); + var deformatter = new RSAPKCS1SignatureDeformatter(rsa); + + using (SHA256 alg = SHA256.Create()) + { + VerifySignature(formatter, deformatter, alg, "SHA256"); + VerifySignature(formatter, deformatter, alg, "sha256"); + } + } + } + + [Fact] + public static void InvalidHashAlgorithm() + { + using (RSA rsa = RSAFactory.Create()) + { + var formatter = new RSAPKCS1SignatureFormatter(rsa); + var deformatter = new RSAPKCS1SignatureDeformatter(rsa); + + // Exception is deferred until VerifySignature + formatter.SetHashAlgorithm("INVALIDVALUE"); + deformatter.SetHashAlgorithm("INVALIDVALUE"); + + using (SHA1 alg = SHA1.Create()) + { + Assert.Throws(() => + VerifySignature(formatter, deformatter, alg, "INVALIDVALUE")); + } + } + } + + [Fact] + public static void VerifyKnownSignature() + { + byte[] hash = "012d161304fa0c6321221516415813022320620c".HexToByteArray(); + byte[] sig; + + using (RSA key = RSAFactory.Create()) + { + key.ImportParameters(TestData.RSA1024Params); + RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); + formatter.SetHashAlgorithm("SHA1"); + sig = formatter.CreateSignature(hash); + + byte[] expectedSig = + ("566390012605b1c4c01c3c2f91ce27d19476ab7131d9ee9cd1b811afb2be02ab6b498b862f0b2368ed6b09ccc9e0ec0d4f97a4f318f4f11" + + "ae882a1131012dc35d2e0b810a38e05da71d291e88b306605c9d34815091641370bd7db7a87b115bd427fcb9993bc5ba2bd518745aef80c" + + "a4557cfa1d827ff1610595d8eeb4c15073").HexToByteArray(); + Assert.Equal(expectedSig, sig); + } + + using (RSA key = RSAFactory.Create()) // Test against a different instance + { + key.ImportParameters(TestData.RSA1024Params); + RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); + deformatter.SetHashAlgorithm("SHA1"); + bool verified = deformatter.VerifySignature(hash, sig); + Assert.True(verified); + + sig[3] ^= 0xff; + verified = deformatter.VerifySignature(hash, sig); + Assert.False(verified); + } + } + } +} diff --git a/src/Common/tests/System/Security/Cryptography/AsymmetricSignatureFormatter.cs b/src/Common/tests/System/Security/Cryptography/AsymmetricSignatureFormatter.cs new file mode 100644 index 000000000000..35a9194ad22c --- /dev/null +++ b/src/Common/tests/System/Security/Cryptography/AsymmetricSignatureFormatter.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + /// + /// Helper methods for DSASignatureFormatterTests and RSASignatureFormatterTests + /// + public partial class AsymmetricSignatureFormatterTests + { + private static readonly byte[] HelloBytes = new ASCIIEncoding().GetBytes("Hello"); + + protected static void VerifySignature(AsymmetricSignatureFormatter formatter, AsymmetricSignatureDeformatter deformatter, HashAlgorithm hashAlgorithm, string hashAlgorithmName) + { + formatter.SetHashAlgorithm(hashAlgorithmName); + deformatter.SetHashAlgorithm(hashAlgorithmName); + + byte[] hash = hashAlgorithm.ComputeHash(HelloBytes); + + VerifySignatureWithHashBytes(formatter, deformatter, hash); + VerifySignatureWithHashAlgorithm(formatter, deformatter, hashAlgorithm); + } + + private static void VerifySignatureWithHashBytes(AsymmetricSignatureFormatter formatter, AsymmetricSignatureDeformatter deformatter, byte[] hash) + { + byte[] signature = formatter.CreateSignature(hash); + Assert.True(deformatter.VerifySignature(hash, signature)); + + signature[signature.Length - 1] ^= 0xff; + Assert.False(deformatter.VerifySignature(hash, signature)); + } + + private static void VerifySignatureWithHashAlgorithm(AsymmetricSignatureFormatter formatter, AsymmetricSignatureDeformatter deformatter, HashAlgorithm hashAlgorithm) + { + byte[] signature = formatter.CreateSignature(hashAlgorithm); + Assert.True(deformatter.VerifySignature(hashAlgorithm, signature)); + + signature[signature.Length - 1] ^= 0xff; + Assert.False(deformatter.VerifySignature(hashAlgorithm, signature)); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs index 491b31ab0cd1..aa6b710b3efe 100644 --- a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs +++ b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs @@ -15,6 +15,37 @@ protected Aes() { } public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get { return default(System.Security.Cryptography.KeySizes[]); } } public static System.Security.Cryptography.Aes Create() { return default(System.Security.Cryptography.Aes); } } + public abstract partial class AsymmetricKeyExchangeDeformatter + { + protected AsymmetricKeyExchangeDeformatter() { } + public abstract string Parameters { get; set; } + public abstract byte[] DecryptKeyExchange(byte[] rgb); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } + public abstract partial class AsymmetricKeyExchangeFormatter + { + protected AsymmetricKeyExchangeFormatter() { } + public abstract string Parameters { get; } + public abstract byte[] CreateKeyExchange(byte[] data); + public abstract byte[] CreateKeyExchange(byte[] data, System.Type symAlgType); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } + public abstract partial class AsymmetricSignatureDeformatter + { + protected AsymmetricSignatureDeformatter() { } + public abstract void SetHashAlgorithm(string strName); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + public abstract bool VerifySignature(byte[] rgbHash, byte[] rgbSignature); + public virtual bool VerifySignature(System.Security.Cryptography.HashAlgorithm hash, byte[] rgbSignature) { return default(bool); } + } + public abstract partial class AsymmetricSignatureFormatter + { + protected AsymmetricSignatureFormatter() { } + public abstract byte[] CreateSignature(byte[] rgbHash); + public virtual byte[] CreateSignature(System.Security.Cryptography.HashAlgorithm hash) { return default(byte[]); } + public abstract void SetHashAlgorithm(string strName); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } public abstract partial class DeriveBytes : System.IDisposable { protected DeriveBytes() { } @@ -52,6 +83,22 @@ public partial struct DSAParameters public byte[] X; public byte[] Y; } + public partial class DSASignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter + { + public DSASignatureDeformatter() { } + public DSASignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override void SetHashAlgorithm(string strName) { } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { return default(bool); } + } + public partial class DSASignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter + { + public DSASignatureFormatter() { } + public DSASignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override byte[] CreateSignature(byte[] rgbHash) { return default(byte[]); } + public override void SetHashAlgorithm(string strName) { } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct ECCurve { @@ -273,6 +320,24 @@ public enum RSAEncryptionPaddingMode Oaep = 1, Pkcs1 = 0, } + public partial class RSAOAEPKeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter + { + public RSAOAEPKeyExchangeDeformatter() { } + public RSAOAEPKeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override string Parameters { get { return default(string); } set { } } + public override byte[] DecryptKeyExchange(byte[] rgbData) { return default(byte[]); } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } + public partial class RSAOAEPKeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter + { + public RSAOAEPKeyExchangeFormatter() { } + public RSAOAEPKeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public byte[] Parameter { get { return default(byte[]); } set { } } + public override string Parameters { get { return default(string); } } + public override byte[] CreateKeyExchange(byte[] rgbData) { return default(byte[]); } + public override byte[] CreateKeyExchange(byte[] rgbData, System.Type symAlgType) { return default(byte[]); } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct RSAParameters { @@ -285,6 +350,39 @@ public partial struct RSAParameters public byte[] P; public byte[] Q; } + public partial class RSAPKCS1KeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter + { + public RSAPKCS1KeyExchangeDeformatter() { } + public RSAPKCS1KeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override string Parameters { get { return default(string); } set { } } + public override byte[] DecryptKeyExchange(byte[] rgbIn) { return default(byte[]); } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } + public partial class RSAPKCS1KeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter + { + public RSAPKCS1KeyExchangeFormatter() { } + public RSAPKCS1KeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override string Parameters { get { return default(string); } } + public override byte[] CreateKeyExchange(byte[] rgbData) { return default(byte[]); } + public override byte[] CreateKeyExchange(byte[] rgbData, System.Type symAlgType) { return default(byte[]); } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } + public partial class RSAPKCS1SignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter + { + public RSAPKCS1SignatureDeformatter() { } + public RSAPKCS1SignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override void SetHashAlgorithm(string strName) { } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { return default(bool); } + } + public partial class RSAPKCS1SignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter + { + public RSAPKCS1SignatureFormatter() { } + public RSAPKCS1SignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) { } + public override byte[] CreateSignature(byte[] rgbHash) { return default(byte[]); } + public override void SetHashAlgorithm(string strName) { } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) { } + } public sealed partial class RSASignaturePadding : System.IEquatable { internal RSASignaturePadding() { } @@ -333,3 +431,4 @@ protected TripleDES() { } public static bool IsWeakKey(byte[] rgbKey) { return default(bool); } } } + diff --git a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.csproj b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.csproj index 846905e02f3a..fa96adb7965a 100644 --- a/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.csproj +++ b/src/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.csproj @@ -7,6 +7,11 @@ + + + + System.Security.Cryptography.Primitives + diff --git a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashAlgorithmNames.cs b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashAlgorithmNames.cs index 132c498600cb..4dcf1df08246 100644 --- a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashAlgorithmNames.cs +++ b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashAlgorithmNames.cs @@ -3,20 +3,66 @@ // See the LICENSE file in the project root for more information. using System; -using System.Diagnostics; +using System.Collections.Generic; +using System.Security.Cryptography; namespace Internal.Cryptography { internal static class HashAlgorithmNames { // These are accepted by CNG - public const String MD5 = "MD5"; - public const String SHA1 = "SHA1"; - public const String SHA256 = "SHA256"; - public const String SHA384 = "SHA384"; - public const String SHA512 = "SHA512"; - } -} + public const string MD5 = "MD5"; + public const string SHA1 = "SHA1"; + public const string SHA256 = "SHA256"; + public const string SHA384 = "SHA384"; + public const string SHA512 = "SHA512"; + + private static readonly HashSet s_allNames = CreateAllNames(); + + /// + /// Map HashAlgorithm type to string; desktop uses CryptoConfig functionality. + /// + public static string ToAlgorithmName(this HashAlgorithm hashAlgorithm) + { + if (hashAlgorithm is SHA1) + return HashAlgorithmNames.SHA1; + if (hashAlgorithm is SHA256) + return HashAlgorithmNames.SHA256; + if (hashAlgorithm is SHA384) + return HashAlgorithmNames.SHA384; + if (hashAlgorithm is SHA512) + return HashAlgorithmNames.SHA512; + if (hashAlgorithm is MD5) + return HashAlgorithmNames.MD5; + + // Fallback to ToString() which can be extended by derived classes + return hashAlgorithm.ToString(); + } + /// + /// Uppercase known hash algorithms. BCrypt is case-sensitive and requires uppercase. + /// + public static string ToUpper(string hashAlgorithName) + { + if (s_allNames.Contains(hashAlgorithName)) + { + return hashAlgorithName.ToUpperInvariant(); + } + return hashAlgorithName; + } + private static HashSet CreateAllNames() + { + var allNames = new HashSet(StringComparer.OrdinalIgnoreCase); + + allNames.Add(HashAlgorithmNames.SHA1); + allNames.Add(HashAlgorithmNames.SHA256); + allNames.Add(HashAlgorithmNames.SHA384); + allNames.Add(HashAlgorithmNames.SHA512); + allNames.Add(HashAlgorithmNames.MD5); + + return allNames; + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx index 381729c2edb7..17596b11c18b 100644 --- a/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx +++ b/src/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx @@ -195,6 +195,9 @@ Specified initialization vector (IV) does not match the block size for this algorithm. + + This operation is not supported for this class. + Specified padding mode is not valid for this algorithm. @@ -210,6 +213,12 @@ The cipher mode specified requires that an initialization vector (IV) be used. + + No asymmetric key object has been associated with this formatter object. + + + Required object identifier (OID) cannot be found. + TransformBlock may only process bytes in block sized increments. diff --git a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.builds b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.builds index 26ced0093aa6..3daa6f65ad9e 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.builds +++ b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.builds @@ -2,7 +2,7 @@ - + Unix diff --git a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index 80c3473ec929..4e6abb439b54 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -26,9 +26,15 @@ + + + + + + @@ -51,7 +57,13 @@ + + + + + + @@ -390,5 +402,11 @@ + + + + System.Security.Cryptography.Primitives + + \ No newline at end of file diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeDeformatter.cs new file mode 100644 index 000000000000..83c3ef505087 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeDeformatter.cs @@ -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. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public abstract class AsymmetricKeyExchangeDeformatter + { + protected AsymmetricKeyExchangeDeformatter() {} + public abstract string Parameters {get; set;} + public abstract void SetKey(AsymmetricAlgorithm key); + public abstract byte[] DecryptKeyExchange(byte[] rgb); + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeFormatter.cs new file mode 100644 index 000000000000..3aff1224f278 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricKeyExchangeFormatter.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public abstract class AsymmetricKeyExchangeFormatter + { + protected AsymmetricKeyExchangeFormatter() {} + + public abstract string Parameters {get;} + + public abstract void SetKey(AsymmetricAlgorithm key); + public abstract byte[] CreateKeyExchange(byte[] data); + + // For desktop compat, keep this even though symAlgType is not used. + public abstract byte[] CreateKeyExchange(byte[] data, Type symAlgType); + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureDeformatter.cs new file mode 100644 index 000000000000..014ce941e4fc --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureDeformatter.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public abstract class AsymmetricSignatureDeformatter + { + protected AsymmetricSignatureDeformatter() {} + + public abstract void SetKey(AsymmetricAlgorithm key); + public abstract void SetHashAlgorithm(string strName); + + public virtual bool VerifySignature(HashAlgorithm hash, byte[] rgbSignature) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); + + SetHashAlgorithm(hash.ToAlgorithmName()); + return VerifySignature(hash.Hash, rgbSignature); + } + + public abstract bool VerifySignature(byte[] rgbHash, byte[] rgbSignature); + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureFormatter.cs new file mode 100644 index 000000000000..24fdad5767b1 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AsymmetricSignatureFormatter.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public abstract class AsymmetricSignatureFormatter + { + protected AsymmetricSignatureFormatter() {} + + public abstract void SetKey(AsymmetricAlgorithm key); + public abstract void SetHashAlgorithm(string strName); + + public virtual byte[] CreateSignature(HashAlgorithm hash) + { + if (hash == null) + throw new ArgumentNullException(nameof(hash)); + + SetHashAlgorithm(hash.ToAlgorithmName()); + return CreateSignature(hash.Hash); + } + + public abstract byte[] CreateSignature(byte[] rgbHash); + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureDeformatter.cs new file mode 100644 index 000000000000..eec79188b823 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureDeformatter.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public class DSASignatureDeformatter : AsymmetricSignatureDeformatter + { + private DSA _dsaKey; + + public DSASignatureDeformatter() { } + + public DSASignatureDeformatter(AsymmetricAlgorithm key) : this() + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _dsaKey = (DSA)key; + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _dsaKey = (DSA)key; + } + + public override void SetHashAlgorithm(string strName) + { + if (strName.ToUpperInvariant() != HashAlgorithmNames.SHA1) + { + // To match desktop, throw here + throw new CryptographicUnexpectedOperationException(SR.Cryptography_InvalidOperation); + } + } + + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (rgbSignature == null) + throw new ArgumentNullException(nameof(rgbSignature)); + if (_dsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _dsaKey.VerifySignature(rgbHash, rgbSignature); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureFormatter.cs new file mode 100644 index 000000000000..d14d38d4a2c6 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSASignatureFormatter.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public class DSASignatureFormatter : AsymmetricSignatureFormatter + { + private DSA _dsaKey; + + public DSASignatureFormatter() { } + + public DSASignatureFormatter(AsymmetricAlgorithm key) : this() + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _dsaKey = (DSA)key; + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _dsaKey = (DSA)key; + } + + public override void SetHashAlgorithm(string strName) + { + if (strName.ToUpperInvariant() != HashAlgorithmNames.SHA1) + { + // To match desktop, throw here + throw new CryptographicUnexpectedOperationException(SR.Cryptography_InvalidOperation); + } + } + + public override byte[] CreateSignature(byte[] rgbHash) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (_dsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _dsaKey.CreateSignature(rgbHash); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeDeformatter.cs new file mode 100644 index 000000000000..9c4df0da9774 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeDeformatter.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public class RSAOAEPKeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter + { + private RSA _rsaKey; + + public RSAOAEPKeyExchangeDeformatter() { } + public RSAOAEPKeyExchangeDeformatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override string Parameters + { + get {return null;} + set { } + } + + public override byte[] DecryptKeyExchange(byte[] rgbData) + { + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.Decrypt(rgbData, RSAEncryptionPadding.OaepSHA1); + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeFormatter.cs new file mode 100644 index 000000000000..cda0ff0e54a3 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAOAEPKeyExchangeFormatter.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public class RSAOAEPKeyExchangeFormatter : AsymmetricKeyExchangeFormatter + { + private byte[] ParameterValue; + private RSA _rsaKey; + + public RSAOAEPKeyExchangeFormatter() { } + public RSAOAEPKeyExchangeFormatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public byte[] Parameter + { + get + { + if (ParameterValue != null) + { + return (byte[])ParameterValue.Clone(); + } + + return null; + } + set + { + if (value != null) + { + ParameterValue = (byte[])value.Clone(); + } + else + { + ParameterValue = null; + } + } + } + + public override string Parameters + { + get {return null;} + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) + { + return CreateKeyExchange(rgbData); + } + + public override byte[] CreateKeyExchange(byte[] rgbData) + { + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.OaepSHA1); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeDeformatter.cs new file mode 100644 index 000000000000..75b74539432d --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeDeformatter.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public class RSAPKCS1KeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter + { + private RSA _rsaKey; + + public RSAPKCS1KeyExchangeDeformatter() { } + + public RSAPKCS1KeyExchangeDeformatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override string Parameters + { + get {return null;} + set { } + } + + public override byte[] DecryptKeyExchange(byte[] rgbIn) + { + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.Decrypt(rgbIn, RSAEncryptionPadding.Pkcs1); + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeFormatter.cs new file mode 100644 index 000000000000..59065c9ec04d --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1KeyExchangeFormatter.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + public class RSAPKCS1KeyExchangeFormatter : AsymmetricKeyExchangeFormatter + { + private RSA _rsaKey; + + public RSAPKCS1KeyExchangeFormatter() { } + + public RSAPKCS1KeyExchangeFormatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override string Parameters + { + get + { + return ""; + } + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override byte[] CreateKeyExchange(byte[] rgbData, Type symAlgType) + { + return CreateKeyExchange(rgbData); + } + + public override byte[] CreateKeyExchange(byte[] rgbData) + { + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.Encrypt(rgbData, RSAEncryptionPadding.Pkcs1); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureDeformatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureDeformatter.cs new file mode 100644 index 000000000000..c8d75906524e --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureDeformatter.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public class RSAPKCS1SignatureDeformatter : AsymmetricSignatureDeformatter + { + private RSA _rsaKey; + private string _algName; + + public RSAPKCS1SignatureDeformatter() { } + public RSAPKCS1SignatureDeformatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override void SetHashAlgorithm(string strName) + { + try + { + // Verify the name + Oid.FromFriendlyName(strName, OidGroup.HashAlgorithm); + + // Uppercase known names as required for BCrypt + _algName = HashAlgorithmNames.ToUpper(strName); + } + catch (CryptographicException) + { + // For desktop compat, exception is deferred until VerifySignature + _algName = null; + } + } + + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (rgbSignature == null) + throw new ArgumentNullException(nameof(rgbSignature)); + if (_algName == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingOID); + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.VerifyHash(rgbHash, rgbSignature, new HashAlgorithmName(_algName), RSASignaturePadding.Pkcs1); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureFormatter.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureFormatter.cs new file mode 100644 index 000000000000..cb4fdf80cff0 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSAPKCS1SignatureFormatter.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.Cryptography; + +namespace System.Security.Cryptography +{ + public class RSAPKCS1SignatureFormatter : AsymmetricSignatureFormatter + { + private RSA _rsaKey; + private string _algName; + + public RSAPKCS1SignatureFormatter() { } + + public RSAPKCS1SignatureFormatter(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override void SetKey(AsymmetricAlgorithm key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + _rsaKey = (RSA)key; + } + + public override void SetHashAlgorithm(string strName) + { + try + { + // Verify the name + Oid.FromFriendlyName(strName, OidGroup.HashAlgorithm); + + // Uppercase known names as required for BCrypt + _algName = HashAlgorithmNames.ToUpper(strName); + } + catch (CryptographicException) + { + // For desktop compat, exception is deferred until VerifySignature + _algName = null; + } + } + + public override byte[] CreateSignature(byte[] rgbHash) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (_algName == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingOID); + if (_rsaKey == null) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_MissingKey); + + return _rsaKey.SignHash(rgbHash, new HashAlgorithmName(_algName), RSASignaturePadding.Pkcs1); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/tests/AsymmetricSignatureFormatterTests.cs b/src/System.Security.Cryptography.Algorithms/tests/AsymmetricSignatureFormatterTests.cs new file mode 100644 index 000000000000..1073b4ab7c95 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/tests/AsymmetricSignatureFormatterTests.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + /// + /// Helper methods for DSASignatureFormatterTests and RSASignatureFormatterTests + /// + public partial class AsymmetricSignatureFormatterTests + { + protected static void InvalidFormatterArguments(AsymmetricSignatureFormatter formatter) + { + Assert.Throws(() => formatter.SetKey(null)); + Assert.Throws(() => formatter.CreateSignature((byte[])null)); + Assert.Throws(() => formatter.CreateSignature(new byte[] { 0, 1, 2, 3 })); + } + + protected static void InvalidDeformatterArguments(AsymmetricSignatureDeformatter deformatter) + { + Assert.Throws(() => deformatter.SetKey(null)); + Assert.Throws(() => deformatter.VerifySignature((byte[])null, new byte[] { 0, 1, 2 })); + Assert.Throws(() => deformatter.VerifySignature(new byte[] { 0, 1, 2 }, new byte[] { 0, 1, 2 })); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/tests/DSASignatureFormatterTests.cs b/src/System.Security.Cryptography.Algorithms/tests/DSASignatureFormatterTests.cs new file mode 100644 index 000000000000..915ee3fa6f84 --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/tests/DSASignatureFormatterTests.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; +using Xunit; + +namespace System.Security.Cryptography.Dsa.Tests +{ + public partial class DSASignatureFormatterTests : AsymmetricSignatureFormatterTests + { + [Fact] + public static void InvalidFormatterArguments() + { + InvalidFormatterArguments(new DSASignatureFormatter()); + } + + [Fact] + public static void InvalidDeformatterArguments() + { + InvalidDeformatterArguments(new DSASignatureDeformatter()); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs b/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs index 724af7140640..d5117503e938 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.IO; using Test.Cryptography; using Xunit; @@ -17,7 +18,7 @@ protected void Verify(string input, string output) Verify(ByteUtils.AsciiBytes(input), output); } - protected void Verify(Stream input, string output) + private void VerifyComputeHashStream(Stream input, string output) { byte[] expected = ByteUtils.HexToByteArray(output); byte[] actual; @@ -31,6 +32,171 @@ protected void Verify(Stream input, string output) Assert.Equal(expected, actual); } +#if netstandard17 + private void VerifyICryptoTransformStream(Stream input, string output) + { + byte[] expected = ByteUtils.HexToByteArray(output); + byte[] actual; + + using (HashAlgorithm hash = Create()) + using (CryptoStream cryptoStream = new CryptoStream(input, hash, CryptoStreamMode.Read)) + { + byte[] buffer = new byte[1024]; // A different default than HashAlgorithm which uses 4K + int bytesRead; + while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0) + { + // CryptoStream will build up the hash + } + + actual = hash.Hash; + } + + Assert.Equal(expected, actual); + } +#endif + + protected void VerifyMultiBlock(string block1, string block2, string expectedHash, string emptyHash) + { +#if netstandard17 + byte[] block1_bytes = ByteUtils.AsciiBytes(block1); + byte[] block2_bytes = ByteUtils.AsciiBytes(block2); + byte[] expected_bytes = ByteUtils.HexToByteArray(expectedHash); + byte[] emptyHash_bytes = ByteUtils.HexToByteArray(emptyHash); + + VerifyTransformBlockOutput(block1_bytes, block2_bytes); + VerifyTransformBlockHash(block1_bytes, block2_bytes, expected_bytes, emptyHash_bytes); + VerifyTransformBlockComputeHashInteraction(block1_bytes, block2_bytes, expected_bytes, emptyHash_bytes); +#endif + } + +#if netstandard17 + private void VerifyTransformBlockOutput(byte[] block1, byte[] block2) + { + using (HashAlgorithm hash = Create()) + { + byte[] actualBlock1 = new byte[block1.Length]; + int byteCount = hash.TransformBlock(block1, 0, block1.Length, actualBlock1, 0); + Assert.Equal(block1.Length, byteCount); + Assert.Equal(block1, actualBlock1); + + byte[] actualBlock2 = hash.TransformFinalBlock(block2, 0, block2.Length); + Assert.Equal(block2, actualBlock2); + } + } + + private void VerifyTransformBlockHash(byte[] block1, byte[] block2, byte[] expected, byte[] expectedEmpty) + { + using (HashAlgorithm hash = Create()) + { + // Verify Empty Hash + hash.TransformBlock(Array.Empty(), 0, 0, null, 0); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + Assert.Equal(hash.Hash, expectedEmpty); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + Assert.Equal(hash.Hash, expectedEmpty); + + // Verify Hash + hash.TransformBlock(block1, 0, block1.Length, null, 0); + hash.TransformFinalBlock(block2, 0, block2.Length); + Assert.Equal(expected, hash.Hash); + Assert.Equal(expected, hash.Hash); // .Hash doesn't clear hash + + // Verify bad State + hash.TransformBlock(block1, 0, block1.Length, null, 0); + // Can't access hash until TransformFinalBlock is called + Assert.Throws(() => hash.Hash); + hash.TransformFinalBlock(block2, 0, block2.Length); + Assert.Equal(expected, hash.Hash); + + // Verify clean State + hash.TransformFinalBlock(Array.Empty(), 0, 0); + Assert.Equal(hash.Hash, expectedEmpty); + } + } + + private void VerifyTransformBlockComputeHashInteraction(byte[] block1, byte[] block2, byte[] expected, byte[] expectedEmpty) + { + using (HashAlgorithm hash = Create()) + { + // TransformBlock + ComputeHash + hash.TransformBlock(block1, 0, block1.Length, null, 0); + byte[] actual = hash.ComputeHash(block2, 0, block2.Length); + Assert.Equal(expected, actual); + + // ComputeHash does not reset State variable + Assert.Throws(() => hash.Hash); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + Assert.Equal(expectedEmpty, hash.Hash); + actual = hash.ComputeHash(Array.Empty(), 0, 0); + Assert.Equal(expectedEmpty, actual); + + // TransformBlock + TransformBlock + ComputeHash(empty) + hash.TransformBlock(block1, 0, block1.Length, null, 0); + hash.TransformBlock(block2, 0, block2.Length, null, 0); + actual = hash.ComputeHash(Array.Empty(), 0, 0); + Assert.Equal(expected, actual); + } + } + + [Fact] + public void VerifyObjectDisposedException() + { + HashAlgorithm hash = Create(); + hash.Dispose(); + Assert.Throws(() => hash.Hash); + Assert.Throws(() => hash.ComputeHash(Array.Empty())); + Assert.Throws(() => hash.ComputeHash(Array.Empty(), 0, 0)); + Assert.Throws(() => hash.ComputeHash((Stream)null)); + Assert.Throws(() => hash.TransformBlock(Array.Empty(), 0, 0, null, 0)); + Assert.Throws(() => hash.TransformFinalBlock(Array.Empty(), 0, 0)); + } + + [Fact] + public void VerifyHashNotYetFinalized() + { + using (HashAlgorithm hash = Create()) + { + hash.TransformBlock(Array.Empty(), 0, 0, null, 0); + Assert.Throws(() => hash.Hash); + } + } + + [Fact] + public void InvalidInput_ComputeHash() + { + using (HashAlgorithm hash = Create()) + { + Assert.Throws("buffer", () => hash.ComputeHash((byte[])null)); + Assert.Throws("buffer", () => hash.ComputeHash(null, 0, 0)); + } + } + + [Fact] + public void InvalidInput_TransformBlock() + { + using (HashAlgorithm hash = Create()) + { + Assert.Throws("inputBuffer", () => hash.TransformBlock(null, 0, 0, null, 0)); + Assert.Throws("inputOffset", () => hash.TransformBlock(Array.Empty(), -1, 0, null, 0)); + Assert.Throws(null, () => hash.TransformBlock(Array.Empty(), 0, 1, null, 0)); + Assert.Throws(null, () => hash.TransformBlock(Array.Empty(), 1, 0, null, 0)); + } + } + + [Fact] + public void InvalidInput_TransformFinalBlock() + { + using (HashAlgorithm hash = Create()) + { + Assert.Throws("inputBuffer", () => hash.TransformFinalBlock(null, 0, 0)); + Assert.Throws("inputOffset", () => hash.TransformFinalBlock(Array.Empty(), -1, 0)); + Assert.Throws(null, () => hash.TransformFinalBlock(Array.Empty(), 1, 0)); + Assert.Throws(null, () => hash.TransformFinalBlock(Array.Empty(), 0, -1)); + Assert.Throws(null, () => hash.TransformFinalBlock(Array.Empty(), 0, 1)); + } + } +#endif + protected void Verify(byte[] input, string output) { byte[] expected = ByteUtils.HexToByteArray(output); @@ -40,17 +206,29 @@ protected void Verify(byte[] input, string output) { Assert.True(hash.HashSize > 0); actual = hash.ComputeHash(input, 0, input.Length); - } - Assert.Equal(expected, actual); + Assert.Equal(expected, actual); + +#if netstandard17 + actual = hash.Hash; + Assert.Equal(expected, actual); +#endif + } } protected void VerifyRepeating(string input, int repeatCount, string output) { using (Stream stream = new DataRepeatingStream(input, repeatCount)) { - Verify(stream, output); + VerifyComputeHashStream(stream, output); } + +#if netstandard17 + using (Stream stream = new DataRepeatingStream(input, repeatCount)) + { + VerifyICryptoTransformStream(stream, output); + } +#endif } [Fact] @@ -166,14 +344,14 @@ public override int Read(byte[] buffer, int offset, int count) throw new NotSupportedException(); } - if (count < _data.Length) + if (_remaining == 0) { - throw new InvalidOperationException(); + return 0; } - if (_remaining == 0) + if (count < _data.Length) { - return 0; + throw new InvalidOperationException(); } int multiple = count / _data.Length; diff --git a/src/System.Security.Cryptography.Algorithms/tests/MD5Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/MD5Tests.cs index fa3eb2100cbb..3dbff8fe7822 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/MD5Tests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/MD5Tests.cs @@ -33,6 +33,16 @@ public void MD5_Rfc1321_3() Verify("abc", "900150983cd24fb0d6963f7d28e17f72"); } + [Fact] + public void MD5_Rfc1321_MultiBlock() + { + VerifyMultiBlock( + "a", + "bc", + "900150983cd24fb0d6963f7d28e17f72", + "d41d8cd98f00b204e9800998ecf8427e"); + } + [Fact] public void MD5_Rfc1321_4() { diff --git a/src/System.Security.Cryptography.Algorithms/tests/RSAKeyExchangeFormatterTests.cs b/src/System.Security.Cryptography.Algorithms/tests/RSAKeyExchangeFormatterTests.cs new file mode 100644 index 000000000000..e03b344c40ed --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/tests/RSAKeyExchangeFormatterTests.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Security.Cryptography.Rsa.Tests +{ + public partial class RSAKeyExchangeFormatterTests + { + [Fact] + public static void RSAOAEPFormatterArguments() + { + InvalidFormatterArguments(new RSAOAEPKeyExchangeFormatter()); + } + + [Fact] + public static void RSAOAEPDeformatterArguments() + { + InvalidDeformatterArguments(new RSAOAEPKeyExchangeDeformatter()); + } + + [Fact] + public static void RSAPKCS1FormatterArguments() + { + InvalidFormatterArguments(new RSAPKCS1KeyExchangeFormatter()); + } + + [Fact] + public static void RSAPKCS1DeformatterArguments() + { + InvalidDeformatterArguments(new RSAPKCS1KeyExchangeDeformatter()); + } + + private static void InvalidFormatterArguments(AsymmetricKeyExchangeFormatter formatter) + { + Assert.Throws(() => formatter.SetKey(null)); + Assert.Throws(() => formatter.CreateKeyExchange(new byte[] { 0, 1, 2, 3 })); + } + + private static void InvalidDeformatterArguments(AsymmetricKeyExchangeDeformatter deformatter) + { + Assert.Throws(() => deformatter.SetKey(null)); + Assert.Throws(() => deformatter.DecryptKeyExchange(new byte[] { 0, 1, 2 })); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/tests/RSASignatureFormatterTests.cs b/src/System.Security.Cryptography.Algorithms/tests/RSASignatureFormatterTests.cs new file mode 100644 index 000000000000..40b86a82fded --- /dev/null +++ b/src/System.Security.Cryptography.Algorithms/tests/RSASignatureFormatterTests.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; +using Xunit; + +namespace System.Security.Cryptography.Rsa.Tests +{ + public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTests + { + [Fact] + public static void InvalidFormatterArguments() + { + InvalidFormatterArguments(new RSAPKCS1SignatureFormatter()); + } + + [Fact] + public static void InvalidDeformatterArguments() + { + InvalidDeformatterArguments(new RSAPKCS1SignatureDeformatter()); + } + } +} diff --git a/src/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs index 30dde3a83f95..1480173911e4 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs @@ -27,6 +27,12 @@ public void Sha1_Rfc3174_1() Verify("abc", "A9993E364706816ABA3E25717850C26C9CD0D89D"); } + [Fact] + public void Sha1_Rfc3174_MultiBlock() + { + VerifyMultiBlock("ab", "c", "A9993E364706816ABA3E25717850C26C9CD0D89D", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + } + [Fact] public void Sha1_Rfc3174_2() { diff --git a/src/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs index 85cf406e0efd..336ca89e8a1a 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs @@ -30,6 +30,16 @@ public void Sha256_Fips180_1() "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); } + [Fact] + public void Sha256_Fips180_MultiBlock() + { + VerifyMultiBlock( + "ab", + "c", + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + } + [Fact] public void Sha256_Fips180_2() { diff --git a/src/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs index 3525283a5a4f..bb5230c521ed 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs @@ -30,6 +30,16 @@ public void Sha384_NistShaAll_1() "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7"); } + [Fact] + public void Sha256_Fips180_MultiBlock() + { + VerifyMultiBlock( + "a", + "bc", + "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7", + "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B"); + } + [Fact] public void Sha384_NistShaAll_2() { diff --git a/src/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs b/src/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs index d3a35cff1a7d..4027a1acf11a 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs @@ -30,6 +30,16 @@ public void Sha512_Fips180_1() "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); } + [Fact] + public void Sha512_Fips180_MultiBlock() + { + VerifyMultiBlock( + "a", + "bc", + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + [Fact] public void Sha512_Fips180_2() { diff --git a/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj b/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj index 7a76e09f8cac..d0434bda541b 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj +++ b/src/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj @@ -10,7 +10,8 @@ Library System.Security.Cryptography.Algorithms.Tests System.Security.Cryptography.Algorithms.Tests - .NETStandard,Version=v1.7 + $(DefineConstants);netstandard17 + .NETStandard,Version=v1.7 @@ -132,10 +133,20 @@ + + + + + + CommonTest\System\Security\Cryptography\AsymmetricSignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAFactory.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAImportExport.cs @@ -148,10 +159,22 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSATestData.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyExchangeFormatter.cs + + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSASignatureFormatter.cs + + + + + System.Security.Cryptography.Primitives + + diff --git a/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj b/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj index 324376f62dc2..64dcfa8ff325 100644 --- a/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj +++ b/src/System.Security.Cryptography.Cng/ref/System.Security.Cryptography.Cng.csproj @@ -7,6 +7,15 @@ + + + + System.Security.Cryptography.Algorithms + + + + System.Security.Cryptography.Primitives + diff --git a/src/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj b/src/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj index a41b2459de00..9801bb6a5446 100644 --- a/src/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj +++ b/src/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj @@ -254,6 +254,16 @@ Common\System\Security\Cryptography\RSACng.SignVerify.cs + + + + System.Security.Cryptography.Algorithms + + + + System.Security.Cryptography.Primitives + + diff --git a/src/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj b/src/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj index 6d9a0af35cb3..58c1eb8c4efe 100644 --- a/src/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj +++ b/src/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj @@ -130,6 +130,9 @@ + + CommonTest\System\Security\Cryptography\AsymmetricSignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAFactory.cs @@ -139,15 +142,34 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyGeneration.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignVerify.cs CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSATestData.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyExchangeFormatter.cs + + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSASignatureFormatter.cs + + + + + System.Security.Cryptography.Primitives + + + + System.Security.Cryptography.Algorithms + + \ No newline at end of file diff --git a/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj b/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj index 0e5bc01cf7de..f7dc09c46613 100644 --- a/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj +++ b/src/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.csproj @@ -7,6 +7,15 @@ + + + + System.Security.Cryptography.Primitives + + + + System.Security.Cryptography.Algorithms + diff --git a/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj b/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj index e7c160d21927..2dd5e06c69c0 100644 --- a/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj +++ b/src/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj @@ -48,5 +48,15 @@ + + + + System.Security.Cryptography.Primitives + + + + System.Security.Cryptography.Algorithms + + \ No newline at end of file diff --git a/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj b/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj index 40e71f49e2bd..4e914bcae5a7 100644 --- a/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj +++ b/src/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj @@ -55,6 +55,9 @@ + + CommonTest\System\Security\Cryptography\AsymmetricSignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAFactory.cs @@ -64,15 +67,34 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyGeneration.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignVerify.cs CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSATestData.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyExchangeFormatter.cs + + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSASignatureFormatter.cs + + + + + System.Security.Cryptography.Primitives + + + + System.Security.Cryptography.Algorithms + + \ No newline at end of file diff --git a/src/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj b/src/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj index 476459f0fd61..f69e524598f3 100644 --- a/src/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj +++ b/src/System.Security.Cryptography.OpenSsl/ref/System.Security.Cryptography.OpenSsl.csproj @@ -7,6 +7,15 @@ + + + + System.Security.Cryptography.Algorithms + + + + System.Security.Cryptography.Primitives + diff --git a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj index 4dd4e11b39e7..d0df5a375621 100644 --- a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +++ b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj @@ -113,5 +113,15 @@ + + + + System.Security.Cryptography.Primitives + + + + System.Security.Cryptography.Algorithms + + \ No newline at end of file diff --git a/src/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj b/src/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj index 4f9847f66e2b..86a5c63e0703 100644 --- a/src/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj +++ b/src/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj @@ -81,6 +81,9 @@ + + CommonTest\System\Security\Cryptography\AsymmetricSignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAFactory.cs @@ -90,12 +93,21 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyGeneration.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignatureFormatter.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignVerify.cs CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSATestData.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyExchangeFormatter.cs + + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSASignatureFormatter.cs + @@ -105,6 +117,14 @@ {78452f3e-ba91-47e7-bb0f-02e8a5c116c4} System.Security.Cryptography.OpenSsl + + + System.Security.Cryptography.Algorithms + + + + System.Security.Cryptography.Primitives + \ No newline at end of file diff --git a/src/System.Security.Cryptography.Primitives/dir.props b/src/System.Security.Cryptography.Primitives/dir.props index 38aaf93ed7aa..0769c12aaa28 100644 --- a/src/System.Security.Cryptography.Primitives/dir.props +++ b/src/System.Security.Cryptography.Primitives/dir.props @@ -1,7 +1,7 @@ - 4.0.1.0 + 4.1.0.0 diff --git a/src/System.Security.Cryptography.Primitives/pkg/System.Security.Cryptography.Primitives.pkgproj b/src/System.Security.Cryptography.Primitives/pkg/System.Security.Cryptography.Primitives.pkgproj index d521c7e4b3d5..251b75c079d0 100644 --- a/src/System.Security.Cryptography.Primitives/pkg/System.Security.Cryptography.Primitives.pkgproj +++ b/src/System.Security.Cryptography.Primitives/pkg/System.Security.Cryptography.Primitives.pkgproj @@ -3,7 +3,7 @@ - net46;netcore50;netcoreapp1.0;$(AllXamarinFrameworks) + net463;netcoreapp1.1;$(AllXamarinFrameworks) diff --git a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs index 0e706800632e..055c9bf7bc7c 100644 --- a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs +++ b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs @@ -10,13 +10,13 @@ namespace System.Security.Cryptography { public abstract partial class AsymmetricAlgorithm : System.IDisposable { + protected int KeySizeValue; + protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; protected AsymmetricAlgorithm() { } public virtual int KeySize { get { return default(int); } set { } } public virtual System.Security.Cryptography.KeySizes[] LegalKeySizes { get { return default(System.Security.Cryptography.KeySizes[]); } } public void Dispose() { } protected virtual void Dispose(bool disposing) { } - protected int KeySizeValue; - protected KeySizes[] LegalKeySizesValue; } public enum CipherMode { @@ -28,10 +28,19 @@ public partial class CryptographicException : System.Exception { public CryptographicException() { } public CryptographicException(int hr) { } + protected CryptographicException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public CryptographicException(string message) { } public CryptographicException(string message, System.Exception inner) { } public CryptographicException(string format, string insert) { } } + public partial class CryptographicUnexpectedOperationException : System.Security.Cryptography.CryptographicException + { + public CryptographicUnexpectedOperationException() { } + protected CryptographicUnexpectedOperationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + public CryptographicUnexpectedOperationException(string message) { } + public CryptographicUnexpectedOperationException(string message, System.Exception inner) { } + public CryptographicUnexpectedOperationException(string format, string insert) { } + } public partial class CryptoStream : System.IO.Stream, System.IDisposable { public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICryptoTransform transform, System.Security.Cryptography.CryptoStreamMode mode) { } @@ -43,24 +52,32 @@ public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICrypt public override long Position { get { return default(long); } set { } } protected override void Dispose(bool disposing) { } public override void Flush() { } - public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { return default(System.Threading.Tasks.Task); } public void FlushFinalBlock() { } - public override int Read(byte[] buffer, int offset, int count) { buffer = default(byte[]); return default(int); } + public override int Read(byte[] buffer, int offset, int count) { return default(int); } public override System.Threading.Tasks.Task ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { return default(System.Threading.Tasks.Task); } + public override int ReadByte() { return default(int); } public override long Seek(long offset, System.IO.SeekOrigin origin) { return default(long); } public override void SetLength(long value) { } public override void Write(byte[] buffer, int offset, int count) { } public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { return default(System.Threading.Tasks.Task); } + public override void WriteByte(byte value) { } } public enum CryptoStreamMode { Read = 0, Write = 1, } - public abstract partial class HashAlgorithm : System.IDisposable + public abstract partial class HashAlgorithm : System.IDisposable, System.Security.Cryptography.ICryptoTransform { + protected internal byte[] HashValue; + protected int State; protected HashAlgorithm() { } + public virtual bool CanReuseTransform { get { return default(bool); } } + public virtual bool CanTransformMultipleBlocks { get { return default(bool); } } + public virtual byte[] Hash { get { return default(byte[]); } } public virtual int HashSize { get { return default(int); } } + public virtual int InputBlockSize { get { return default(int); } } + public virtual int OutputBlockSize { get { return default(int); } } public byte[] ComputeHash(byte[] buffer) { return default(byte[]); } public byte[] ComputeHash(byte[] buffer, int offset, int count) { return default(byte[]); } public byte[] ComputeHash(System.IO.Stream inputStream) { return default(byte[]); } @@ -69,6 +86,8 @@ protected virtual void Dispose(bool disposing) { } protected abstract void HashCore(byte[] array, int ibStart, int cbSize); protected abstract byte[] HashFinal(); public abstract void Initialize(); + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { return default(int); } + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { return default(byte[]); } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct HashAlgorithmName : System.IEquatable @@ -108,6 +127,7 @@ public partial interface ICryptoTransform : System.IDisposable } public abstract partial class KeyedHashAlgorithm : System.Security.Cryptography.HashAlgorithm { + protected byte[] KeyValue; protected KeyedHashAlgorithm() { } public virtual byte[] Key { get { return default(byte[]); } set { } } protected override void Dispose(bool disposing) { } @@ -127,6 +147,14 @@ public enum PaddingMode } public abstract partial class SymmetricAlgorithm : System.IDisposable { + protected int BlockSizeValue; + protected byte[] IVValue; + protected int KeySizeValue; + protected byte[] KeyValue; + protected System.Security.Cryptography.KeySizes[] LegalBlockSizesValue; + protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; + protected System.Security.Cryptography.CipherMode ModeValue; + protected System.Security.Cryptography.PaddingMode PaddingValue; protected SymmetricAlgorithm() { } public virtual int BlockSize { get { return default(int); } set { } } public virtual byte[] IV { get { return default(byte[]); } set { } } @@ -144,13 +172,5 @@ public void Dispose() { } protected virtual void Dispose(bool disposing) { } public abstract void GenerateIV(); public abstract void GenerateKey(); - protected CipherMode ModeValue; - protected PaddingMode PaddingValue; - protected byte[] KeyValue; - protected byte[] IVValue; - protected int BlockSizeValue; - protected int KeySizeValue; - protected KeySizes[] LegalBlockSizesValue; - protected KeySizes[] LegalKeySizesValue; } } diff --git a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.csproj b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.csproj index 167d83a16ab2..980ed1f40ad2 100644 --- a/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.csproj +++ b/src/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.csproj @@ -3,7 +3,7 @@ Library - .NETStandard,Version=v1.3 + .NETStandard,Version=v1.7 diff --git a/src/System.Security.Cryptography.Primitives/ref/project.json b/src/System.Security.Cryptography.Primitives/ref/project.json index 39a6433e4d04..ccc9bc9dacaa 100644 --- a/src/System.Security.Cryptography.Primitives/ref/project.json +++ b/src/System.Security.Cryptography.Primitives/ref/project.json @@ -1,13 +1,13 @@ { "dependencies": { - "System.Runtime": "4.0.0", - "System.IO": "4.0.0", - "System.Threading.Tasks": "4.0.0" + "System.Runtime": "4.3.0-beta-24601-02", + "System.IO": "4.3.0-beta-24601-02", + "System.Threading.Tasks": "4.3.0-beta-24601-02" }, "frameworks": { - "netstandard1.3": { + "netstandard1.7": { "imports": [ - "dotnet5.4" + "dotnet5.8" ] } } diff --git a/src/System.Security.Cryptography.Primitives/src/Resources/Strings.resx b/src/System.Security.Cryptography.Primitives/src/Resources/Strings.resx index ef85e54b5a46..bb9526c9c181 100644 --- a/src/System.Security.Cryptography.Primitives/src/Resources/Strings.resx +++ b/src/System.Security.Cryptography.Primitives/src/Resources/Strings.resx @@ -135,9 +135,15 @@ Non-negative number required. + + Hash not valid for use in specified state. + FlushFinalBlock() method was called twice on a CryptoStream. It can only be called once. + + Hash must be finalized before the hash value is retrieved. + Specified block size is not valid for this algorithm. diff --git a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.builds b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.builds index f8f1674accbc..f8ea0bace7d8 100644 --- a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.builds +++ b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.builds @@ -4,7 +4,7 @@ - net46 + net463 diff --git a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj index 60c57d16dd19..b1692e380274 100644 --- a/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj +++ b/src/System.Security.Cryptography.Primitives/src/System.Security.Cryptography.Primitives.csproj @@ -4,18 +4,19 @@ {DF73E985-E143-4BF5-9FA4-E199E7D36235} System.Security.Cryptography.Primitives - true - None - .NETStandard,Version=v1.3 + true + None + .NETStandard,Version=v1.7 - + + @@ -31,7 +32,7 @@ Common\System\Threading\Tasks\ForceAsyncAwaiter.cs - + diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicException.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicException.cs index 19ec15e49390..9de4dff1e9b8 100644 --- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicException.cs +++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicException.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Globalization; +using System.Runtime.Serialization; namespace System.Security.Cryptography { @@ -33,5 +34,10 @@ public CryptographicException(string format, string insert) : base(string.Format(CultureInfo.CurrentCulture, format, insert)) { } + + protected CryptographicException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } } } diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicUnexpectedOperationException.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicUnexpectedOperationException.cs new file mode 100644 index 000000000000..d6a20b46f97c --- /dev/null +++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicUnexpectedOperationException.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Globalization; +using System.Runtime.Serialization; + +namespace System.Security.Cryptography +{ + public class CryptographicUnexpectedOperationException : CryptographicException + { + public CryptographicUnexpectedOperationException() + : base(SR.Arg_CryptographyException) + { + } + + public CryptographicUnexpectedOperationException(string message) + : base(message) + { + } + + public CryptographicUnexpectedOperationException(string message, Exception inner) + : base(message, inner) + { + } + + public CryptographicUnexpectedOperationException(string format, string insert) + : base(string.Format(CultureInfo.CurrentCulture, format, insert)) + { + } + + protected CryptographicUnexpectedOperationException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs index 7a14b5d4a383..6c3792e7ded6 100644 --- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs +++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs @@ -2,17 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.IO; -using System.Diagnostics; namespace System.Security.Cryptography { - public abstract class HashAlgorithm : IDisposable + public abstract class HashAlgorithm : IDisposable, ICryptoTransform { - protected HashAlgorithm() - { - } + protected HashAlgorithm() { } public virtual int HashSize { @@ -22,6 +18,19 @@ public virtual int HashSize } } + public virtual byte[] Hash + { + get + { + if (_disposed) + throw new ObjectDisposedException(null); + if (State != 0) + throw new CryptographicUnexpectedOperationException(SR.Cryptography_HashNotYetFinalized); + + return (byte[])HashValue.Clone(); + } + } + public byte[] ComputeHash(byte[] buffer) { if (_disposed) @@ -68,12 +77,13 @@ public byte[] ComputeHash(Stream inputStream) private byte[] CaptureHashCodeAndReinitialize() { - byte[] hashValue = HashFinal(); + HashValue = HashFinal(); + // Clone the hash value prior to invoking Initialize in case the user-defined Initialize // manipulates the array. - hashValue = hashValue.CloneByteArray(); + byte[] tmp = (byte[])HashValue.Clone(); Initialize(); - return hashValue; + return tmp; } public void Dispose() @@ -94,11 +104,89 @@ protected virtual void Dispose(bool disposing) return; } + // ICryptoTransform methods + + // We assume any HashAlgorithm can take input a byte at a time + public virtual int InputBlockSize + { + get { return (1); } + } + + public virtual int OutputBlockSize + { + get { return (1); } + } + + public virtual bool CanTransformMultipleBlocks + { + get { return true; } + } + + public virtual bool CanReuseTransform + { + get { return true; } + } + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + + // Change the State value + State = 1; + + HashCore(inputBuffer, inputOffset, inputCount); + if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset))) + { + // We let BlockCopy do the destination array validation + Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount); + } + return inputCount; + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + + HashCore(inputBuffer, inputOffset, inputCount); + HashValue = CaptureHashCodeAndReinitialize(); + byte[] outputBytes; + if (inputCount != 0) + { + outputBytes = new byte[inputCount]; + Buffer.BlockCopy(inputBuffer, inputOffset, outputBytes, 0, inputCount); + } + else + { + outputBytes = Array.Empty(); + } + + // Reset the State value + State = 0; + + return outputBytes; + } + + private void ValidateTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + if (inputBuffer == null) + throw new ArgumentNullException(nameof(inputBuffer)); + if (inputOffset < 0) + throw new ArgumentOutOfRangeException(nameof(inputOffset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (inputCount < 0 || inputCount > inputBuffer.Length) + throw new ArgumentException(SR.Argument_InvalidValue); + if ((inputBuffer.Length - inputCount) < inputOffset) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + if (_disposed) + throw new ObjectDisposedException(null); + } + protected abstract void HashCore(byte[] array, int ibStart, int cbSize); protected abstract byte[] HashFinal(); public abstract void Initialize(); private bool _disposed; + protected internal byte[] HashValue; + protected int State = 0; } } - diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/KeyedHashAlgorithm.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/KeyedHashAlgorithm.cs index 07d976ce428e..293f26d0d888 100644 --- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/KeyedHashAlgorithm.cs +++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/KeyedHashAlgorithm.cs @@ -17,12 +17,12 @@ public virtual byte[] Key { get { - return _key.CloneByteArray(); + return KeyValue.CloneByteArray(); } set { - _key = value.CloneByteArray(); + KeyValue = value.CloneByteArray(); } } @@ -31,16 +31,16 @@ protected override void Dispose(bool disposing) // For keyed hash algorithms, we always want to zero out the key value if (disposing) { - if (_key != null) + if (KeyValue != null) { - Array.Clear(_key, 0, _key.Length); + Array.Clear(KeyValue, 0, KeyValue.Length); } - _key = null; + KeyValue = null; } base.Dispose(disposing); } - private byte[] _key; + protected byte[] KeyValue; } } diff --git a/src/System.Security.Cryptography.Primitives/src/project.json b/src/System.Security.Cryptography.Primitives/src/project.json index 56a07084eb12..36057d4272f4 100644 --- a/src/System.Security.Cryptography.Primitives/src/project.json +++ b/src/System.Security.Cryptography.Primitives/src/project.json @@ -1,20 +1,21 @@ { "frameworks": { - "netstandard1.3": { + "netstandard1.7": { "dependencies": { - "System.Diagnostics.Contracts": "4.0.0", - "System.Diagnostics.Debug": "4.0.0", - "System.IO": "4.0.10", - "System.Resources.ResourceManager": "4.0.0", - "System.Runtime": "4.0.20", - "System.Threading": "4.0.0", - "System.Threading.Tasks": "4.0.0" + "System.Diagnostics.Contracts": "4.3.0-beta-24601-02", + "System.Diagnostics.Debug": "4.3.0-beta-24601-02", + "System.Globalization": "4.3.0-beta-24601-02", + "System.IO": "4.3.0-beta-24601-02", + "System.Resources.ResourceManager": "4.3.0-beta-24601-02", + "System.Runtime": "4.3.0-beta-24601-02", + "System.Threading": "4.3.0-beta-24601-02", + "System.Threading.Tasks": "4.3.0-beta-24601-02" }, "imports": [ - "dotnet5.4" + "dotnet5.8" ] }, - "net46": { + "net463": { "dependencies": { "Microsoft.TargetingPack.NETFramework.v4.6": "1.0.1" } diff --git a/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.builds b/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.builds index f368a64352ba..368e8141fad8 100644 --- a/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.builds +++ b/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.builds @@ -4,7 +4,8 @@ - netcore50;net46 + netstandard1.7 + netcoreapp1.1 Windows_NT diff --git a/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj b/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj index f785e6f0ebca..f0bc26ca2bfe 100644 --- a/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj +++ b/src/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj @@ -9,7 +9,8 @@ Library System.Security.Cryptography.Primitives.Tests System.Security.Cryptography.Primitives.Tests - .NETStandard,Version=v1.3 + .NETStandard,Version=v1.7 + .NETStandard,Version=v1.3 diff --git a/src/System.Security.Cryptography.Primitives/tests/project.json b/src/System.Security.Cryptography.Primitives/tests/project.json index 91e310fbcb26..8667a1e15f73 100644 --- a/src/System.Security.Cryptography.Primitives/tests/project.json +++ b/src/System.Security.Cryptography.Primitives/tests/project.json @@ -5,6 +5,7 @@ "System.ObjectModel": "4.3.0-beta-24601-02", "System.Runtime": "4.3.0-beta-24601-02", "System.Runtime.Extensions": "4.3.0-beta-24601-02", + "System.Text.Encoding": "4.3.0-beta-24601-02", "System.Text.RegularExpressions": "4.3.0-beta-24601-02", "test-runtime": { "target": "project", @@ -14,7 +15,8 @@ "Microsoft.DotNet.BuildTools.TestSuite": "1.0.0-prerelease-00830-02" }, "frameworks": { - "netstandard1.3": {} + "netstandard1.3": {}, + "netstandard1.7": {} }, "supports": { "coreFx.Test.netcore50": {}, @@ -22,6 +24,22 @@ "coreFx.Test.net46": {}, "coreFx.Test.net461": {}, "coreFx.Test.net462": {}, - "coreFx.Test.net463": {} + "coreFx.Test.net463": {}, + "coreFx.Test.netcoreapp1.1-ns17": { + "netstandard1.7": [ + "win7-x86", + "win7-x64", + "win10-arm64", + "osx.10.10-x64", + "centos.7-x64", + "debian.8-x64", + "rhel.7-x64", + "ubuntu.14.04-x64", + "ubuntu.16.04-x64", + "fedora.23-x64", + "linux-x64", + "opensuse.13.2-x64" + ] + } } }