summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWes Haggard <Wes.Haggard@microsoft.com>2015-05-14 19:50:18 -0700
committerWes Haggard <Wes.Haggard@microsoft.com>2015-05-14 19:50:18 -0700
commit2cd11d1101f7d98ed28bbe61d6c21e5c2d0be45c (patch)
treeac3aba0e133a4d612e75b1371aa94518b953819d /src
parent08dd1c89375adbd9218475b8c6f044fe3a226c50 (diff)
downloadcoreclr-2cd11d1101f7d98ed28bbe61d6c21e5c2d0be45c.tar.gz
coreclr-2cd11d1101f7d98ed28bbe61d6c21e5c2d0be45c.tar.bz2
coreclr-2cd11d1101f7d98ed28bbe61d6c21e5c2d0be45c.zip
Merge changes from parent branch
[tfs-changeset: 1471040]
Diffstat (limited to 'src')
-rw-r--r--src/mscorlib/src/System/Security/Cryptography/RSACryptoServiceProvider.cs142
-rw-r--r--src/mscorlib/src/System/Security/Cryptography/rsa.cs198
-rw-r--r--src/mscorlib/src/mscorlib.txt25
3 files changed, 337 insertions, 28 deletions
diff --git a/src/mscorlib/src/System/Security/Cryptography/RSACryptoServiceProvider.cs b/src/mscorlib/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
index 00e1993186..650c6b925f 100644
--- a/src/mscorlib/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
+++ b/src/mscorlib/src/System/Security/Cryptography/RSACryptoServiceProvider.cs
@@ -489,5 +489,147 @@ namespace System.Security.Cryptography {
private static bool IsPublic(RSAParameters rsaParams) {
return (rsaParams.P == null);
}
+
+#if !FEATURE_CORECLR
+ //
+ // Adapt new RSA abstraction to legacy RSACryptoServiceProvider surface area.
+ //
+
+ // NOTE: For the new API, we go straight to CAPI for fixed set of hash algorithms and don't use crypto config here.
+ //
+ // Reasons:
+ // 1. We're moving away from crypto config and we won't have it when porting to .NET Core
+ //
+ // 2. It's slow to lookup and slow to use as the base HashAlgorithm adds considerable overhead
+ // (redundant defensive copy + double-initialization for the single-use case).
+ //
+
+ [SecuritySafeCritical]
+ protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) {
+ // we're sealed and the base should have checked this already
+ Contract.Assert(data != null);
+ Contract.Assert(offset >= 0 && offset <= data.Length);
+ Contract.Assert(count >= 0 && count <= data.Length);
+ Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
+
+ using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
+ Utils.HashData(hashHandle, data, offset, count);
+ return Utils.EndHash(hashHandle);
+ }
+ }
+
+ [SecuritySafeCritical]
+ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) {
+ // we're sealed and the base should have checked this already
+ Contract.Assert(data != null);
+ Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
+
+ using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
+ // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm
+ byte[] buffer = new byte[4096];
+ int bytesRead = 0;
+ do {
+ bytesRead = data.Read(buffer, 0, buffer.Length);
+ if (bytesRead > 0) {
+ Utils.HashData(hashHandle, buffer, 0, bytesRead);
+ }
+ } while (bytesRead > 0);
+
+ return Utils.EndHash(hashHandle);
+ }
+ }
+
+ private static int GetAlgorithmId(HashAlgorithmName hashAlgorithm) {
+ switch (hashAlgorithm.Name) {
+ case "MD5":
+ return Constants.CALG_MD5;
+ case "SHA1":
+ return Constants.CALG_SHA1;
+ case "SHA256":
+ return Constants.CALG_SHA_256;
+ case "SHA384":
+ return Constants.CALG_SHA_384;
+ case "SHA512":
+ return Constants.CALG_SHA_512;
+ default:
+ throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name));
+ }
+ }
+
+ public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ if (padding == RSAEncryptionPadding.Pkcs1) {
+ return Encrypt(data, fOAEP: false);
+ } else if (padding == RSAEncryptionPadding.OaepSHA1) {
+ return Encrypt(data, fOAEP: true);
+ } else {
+ throw PaddingModeNotSupported();
+ }
+ }
+
+ public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ if (padding == RSAEncryptionPadding.Pkcs1) {
+ return Decrypt(data, fOAEP: false);
+ } else if (padding == RSAEncryptionPadding.OaepSHA1) {
+ return Decrypt(data, fOAEP: true);
+ } else {
+ throw PaddingModeNotSupported();
+ }
+ }
+
+ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (hash == null) {
+ throw new ArgumentNullException("hash");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+ if (padding != RSASignaturePadding.Pkcs1) {
+ throw PaddingModeNotSupported();
+ }
+
+ return SignHash(hash, GetAlgorithmId(hashAlgorithm));
+ }
+
+ public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (hash == null) {
+ throw new ArgumentNullException("hash");
+ }
+ if (signature == null) {
+ throw new ArgumentNullException("signature");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+ if (padding != RSASignaturePadding.Pkcs1) {
+ throw PaddingModeNotSupported();
+ }
+
+ return VerifyHash(hash, GetAlgorithmId(hashAlgorithm), signature);
+ }
+
+ private static Exception PaddingModeNotSupported() {
+ return new CryptographicException(Environment.GetResourceString("Cryptography_InvalidPaddingMode"));
+ }
+#endif
}
}
diff --git a/src/mscorlib/src/System/Security/Cryptography/rsa.cs b/src/mscorlib/src/System/Security/Cryptography/rsa.cs
index 000b1be510..c10bad843f 100644
--- a/src/mscorlib/src/System/Security/Cryptography/rsa.cs
+++ b/src/mscorlib/src/System/Security/Cryptography/rsa.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace System.Security.Cryptography {
+ using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Security.Util;
@@ -27,17 +28,7 @@ namespace System.Security.Cryptography {
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class RSA : AsymmetricAlgorithm
{
- //
- // Extending this class allows us to know that you are really implementing
- // an RSA key. This is required for anybody providing a new RSA key value
- // implemention.
- //
- // The class provides no methods, fields or anything else. Its only purpose is
- // as a heirarchy member for identification of algorithm.
- //
-
protected RSA() { }
-
//
// public methods
//
@@ -50,13 +41,188 @@ namespace System.Security.Cryptography {
return (RSA) CryptoConfig.CreateFromName(algName);
}
- // Apply the private key to the data. This function represents a
- // raw RSA operation -- no implicit depadding of the imput value
- abstract public byte[] DecryptValue(byte[] rgb);
+#if !FEATURE_CORECLR
+ //
+ // New RSA encrypt/decrypt/sign/verify RSA abstractions in .NET 4.6+ and .NET Core
+ //
+ // Methods that throw DerivedClassMustOverride are effectively abstract but we
+ // cannot mark them as such as it would be a breaking change. We'll make them
+ // abstract in .NET Core.
+
+ public virtual byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) {
+ throw DerivedClassMustOverride();
+ }
+
+ public virtual byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) {
+ throw DerivedClassMustOverride();
+ }
+
+ public virtual byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ throw DerivedClassMustOverride();
+ }
+
+ public virtual bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ throw DerivedClassMustOverride();
+ }
+
+ protected virtual byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) {
+ throw DerivedClassMustOverride();
+ }
+
+ protected virtual byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) {
+ throw DerivedClassMustOverride();
+ }
+
+ public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ return SignData(data, 0, data.Length, hashAlgorithm, padding);
+ }
+
+ public virtual byte[] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (offset < 0 || offset > data.Length) {
+ throw new ArgumentOutOfRangeException("offset");
+ }
+ if (count < 0 || count > data.Length - offset) {
+ throw new ArgumentOutOfRangeException("count");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ byte[] hash = HashData(data, offset, count, hashAlgorithm);
+ return SignHash(hash, hashAlgorithm, padding);
+ }
+
+ public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ byte[] hash = HashData(data, hashAlgorithm);
+ return SignHash(hash, hashAlgorithm, padding);
+ }
+
+ public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ return VerifyData(data, 0, data.Length, signature, hashAlgorithm, padding);
+ }
+
+ public virtual bool VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (offset < 0 || offset > data.Length) {
+ throw new ArgumentOutOfRangeException("offset");
+ }
+ if (count < 0 || count > data.Length - offset) {
+ throw new ArgumentOutOfRangeException("count");
+ }
+ if (signature == null) {
+ throw new ArgumentNullException("signature");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ byte[] hash = HashData(data, offset, count, hashAlgorithm);
+ return VerifyHash(hash, signature, hashAlgorithm, padding);
+ }
+
+ public bool VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
+ if (data == null) {
+ throw new ArgumentNullException("data");
+ }
+ if (signature == null) {
+ throw new ArgumentNullException("signature");
+ }
+ if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
+ throw HashAlgorithmNameNullOrEmpty();
+ }
+ if (padding == null) {
+ throw new ArgumentNullException("padding");
+ }
+
+ byte[] hash = HashData(data, hashAlgorithm);
+ return VerifyHash(hash, signature, hashAlgorithm, padding);
+ }
+
+ private static Exception DerivedClassMustOverride() {
+ return new NotImplementedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+ internal static Exception HashAlgorithmNameNullOrEmpty() {
+ return new ArgumentException(Environment.GetResourceString("Cryptography_HashAlgorithmNameNullOrEmpty"), "hashAlgorithm");
+ }
+#endif
+
+ //
+ // Legacy encrypt/decrypt RSA abstraction from .NET < 4.6
+ //
+ // These should be obsolete, but we can't mark them as such here due to rules around not introducing
+ // source breaks to scenarios that compile against the GAC.
+ //
+ // They used to be abstract, but the only concrete implementation in RSACryptoServiceProvider threw
+ // NotSupportedException! This has been moved up to the base so all subclasses can ignore them moving forward.
+ // They will also be removed from .NET Core altogether.
+ //
+ // The original intent was for these to perform the RSA algorithm without padding/depadding. This can
+ // be seen by how the RSAXxx(De)Formatter classes call them in the non-RSACryptoServiceProvider case --
+ // they do the padding/depadding in managed code.
+ //
+ // Unfortunately, these formatter classes are still incompatible with RSACng or any derived class that does not
+ // implement EncryptValue, DecryptValue as the formatters speculatively expected non-RSACryptoServiceProvider
+ // to do. That needs to be fixed in a subsequent release. We can still do it as it would move an exception to a
+ // correct result...
+ //
+
+ // [Obsolete]
+ public virtual byte[] DecryptValue(byte[] rgb) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method"));
+ }
+
+ // [Obsolete]
+ public virtual byte[] EncryptValue(byte[] rgb) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method"));
+ }
+
+ //
+ // These should also be obsolete (on the base). They aren't well defined nor are they used
+ // anywhere in the FX apart from checking that they're not null.
+ //
+ // For new derived RSA classes, we'll just return "RSA" which is analagous to what ECDsa
+ // and ECDiffieHellman do.
+ //
+ // Note that for compat, RSACryptoServiceProvider still overrides and returns RSA-PKCS1-KEYEX
+ // and http://www.w3.org/2000/09/xmldsig#rsa-sha1
+ //
+
+ public override string KeyExchangeAlgorithm {
+ get { return "RSA"; }
+ }
+
+ public override string SignatureAlgorithm {
+ get { return "RSA"; }
+ }
- // Apply the public key to the data. Again, this is a raw operation, no
- // automatic padding.
- abstract public byte[] EncryptValue(byte[] rgb);
// Import/export functions
diff --git a/src/mscorlib/src/mscorlib.txt b/src/mscorlib/src/mscorlib.txt
index e287368297..96f2855ad3 100644
--- a/src/mscorlib/src/mscorlib.txt
+++ b/src/mscorlib/src/mscorlib.txt
@@ -1,4 +1,4 @@
-;==++==
+;==++==
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
@@ -946,6 +946,7 @@ Cryptography_CSP_NoPrivateKey = Object contains only the public half of a key pa
Cryptography_CSP_OFBNotSupported = Output feedback mode (OFB) is not supported by this implementation.
Cryptography_CSP_WrongKeySpec = The specified cryptographic service provider (CSP) does not support this key algorithm.
Cryptography_HashNameSet = Hash name cannot be changed after the first write to the stream.
+Cryptography_HashAlgorithmNameNullOrEmpty = The hash algorithm name cannot be null or empty.
Cryptography_InvalidHashSize = {0} algorithm hash size is {1} bytes.
Cryptography_InvalidKey_Weak = Specified key is a known weak key for '{0}' and cannot be used.
Cryptography_InvalidKey_SemiWeak = Specified key is a known semi-weak key for '{0}' and cannot be used.
@@ -1311,7 +1312,7 @@ IsolatedStorage_StoreNotOpen = Store must be open for this operation.
IsolatedStorage_OldQuotaLarger = The new quota must be larger than the old quota.
IsolatedStorage_UsageWillExceedQuota = There is not enough free space to perform the operation.
IsolatedStorage_NotValidOnDesktop = The Site scope is currently not supported.
-IsolatedStorage_OnlyIncreaseUserApplicationStore = Increasing the quota of this scope is not supported. Only the user application scope’s quota can be increased.
+IsolatedStorage_OnlyIncreaseUserApplicationStore = Increasing the quota of this scope is not supported. Only the user application scope’s quota can be increased.
#endif // FEATURE_ISOSTORE
; Verification Exception
@@ -2655,13 +2656,13 @@ Globalization.ci_fr-BE = French (Belgium)
Globalization.ci_fr-BF = French (Burkina Faso)
Globalization.ci_fr-BI = French (Burundi)
Globalization.ci_fr-BJ = French (Benin)
-Globalization.ci_fr-BL = French (Saint Barth‚lemy)
+Globalization.ci_fr-BL = French (Saint Barth‚lemy)
Globalization.ci_fr-CA = French (Canada)
Globalization.ci_fr-CD = French (Congo DRC)
Globalization.ci_fr-CF = French (Central African Republic)
Globalization.ci_fr-CG = French (Congo)
Globalization.ci_fr-CH = French (Switzerland)
-Globalization.ci_fr-CI = French (Côte d’Ivoire)
+Globalization.ci_fr-CI = French (Côte d’Ivoire)
Globalization.ci_fr-CM = French (Cameroon)
Globalization.ci_fr-DJ = French (Djibouti)
Globalization.ci_fr-DZ = French (Algeria)
@@ -2883,9 +2884,9 @@ Globalization.ci_my = Burmese
Globalization.ci_my-MM = Burmese (Myanmar)
Globalization.ci_naq = Nama
Globalization.ci_naq-NA = Nama (Namibia)
-Globalization.ci_nb = Norwegian (Bokmål)
-Globalization.ci_nb-NO = Norwegian, Bokmål (Norway)
-Globalization.ci_nb-SJ = Norwegian, Bokmål (Svalbard and Jan Mayen)
+Globalization.ci_nb = Norwegian (Bokmål)
+Globalization.ci_nb-NO = Norwegian, Bokmål (Norway)
+Globalization.ci_nb-SJ = Norwegian, Bokmål (Svalbard and Jan Mayen)
Globalization.ci_nd = North Ndebele
Globalization.ci_nd-ZW = North Ndebele (Zimbabwe)
Globalization.ci_ne = Nepali
@@ -2895,7 +2896,7 @@ Globalization.ci_nl = Dutch
Globalization.ci_nl-AW = Dutch (Aruba)
Globalization.ci_nl-BE = Dutch (Belgium)
Globalization.ci_nl-BQ = Dutch (Bonaire, Sint Eustatius and Saba)
-Globalization.ci_nl-CW = Dutch (Curaçao)
+Globalization.ci_nl-CW = Dutch (Curaçao)
Globalization.ci_nl-NL = Dutch (Netherlands)
Globalization.ci_nl-SR = Dutch (Suriname)
Globalization.ci_nl-SX = Dutch (Sint Maarten)
@@ -2944,7 +2945,7 @@ Globalization.ci_pt-GW = Portuguese (Guinea-Bissau)
Globalization.ci_pt-MO = Portuguese (Macao SAR)
Globalization.ci_pt-MZ = Portuguese (Mozambique)
Globalization.ci_pt-PT = Portuguese (Portugal)
-Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe)
+Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe)
Globalization.ci_pt-TL = Portuguese (Timor-Leste)
Globalization.ci_qps-ploc = Pseudo Language (Pseudo)
Globalization.ci_qps-ploca = Pseudo Language (Pseudo Asia)
@@ -3055,7 +3056,7 @@ Globalization.ci_st = Southern Sotho
Globalization.ci_st-LS = Sesotho (Lesotho)
Globalization.ci_st-ZA = Southern Sotho (South Africa)
Globalization.ci_sv = Swedish
-Globalization.ci_sv-AX = Swedish (land Islands)
+Globalization.ci_sv-AX = Swedish (Ã…land Islands)
Globalization.ci_sv-FI = Swedish (Finland)
Globalization.ci_sv-SE = Swedish (Sweden)
Globalization.ci_sw = Kiswahili
@@ -3131,8 +3132,8 @@ Globalization.ci_ve = Venda
Globalization.ci_ve-ZA = Venda (South Africa)
Globalization.ci_vi = Vietnamese
Globalization.ci_vi-VN = Vietnamese (Vietnam)
-Globalization.ci_vo = Volapk
-Globalization.ci_vo-001 = Volapk (World)
+Globalization.ci_vo = Volapük
+Globalization.ci_vo-001 = Volapük (World)
Globalization.ci_vun = Vunjo
Globalization.ci_vun-TZ = Vunjo (Tanzania)
Globalization.ci_wae = Walser