Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / rsacryptoserviceprovider.cs
blob2bbd0f6559cc4cced4b26e07f1a06f15d418767b
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 //
9 //
10 // RSACryptoServiceProvider.cs
12 // CSP-based implementation of RSA
15 namespace System.Security.Cryptography {
16 using System;
17 using System.Globalization;
18 using System.IO;
19 using System.Security;
20 using System.Runtime.InteropServices;
21 using System.Runtime.CompilerServices;
22 using System.Runtime.Versioning;
23 using System.Security.Cryptography.X509Certificates;
24 using System.Security.Permissions;
25 using System.Diagnostics.Contracts;
27 #if !MONO
28 // Object layout of the RSAParameters structure
29 internal class RSACspObject {
30 internal byte[] Exponent;
31 internal byte[] Modulus;
32 internal byte[] P;
33 internal byte[] Q;
34 internal byte[] DP;
35 internal byte[] DQ;
36 internal byte[] InverseQ;
37 internal byte[] D;
39 #endif
41 [System.Runtime.InteropServices.ComVisible(true)]
42 public sealed partial class RSACryptoServiceProvider : RSA
43 , ICspAsymmetricAlgorithm
45 #if !MONO
46 private int _dwKeySize;
47 private CspParameters _parameters;
48 private bool _randomKeyContainer;
49 [System.Security.SecurityCritical] // auto-generated
50 private SafeProvHandle _safeProvHandle;
51 [System.Security.SecurityCritical] // auto-generated
52 private SafeKeyHandle _safeKeyHandle;
53 #endif
54 private static volatile CspProviderFlags s_UseMachineKeyStore = 0;
57 // QCalls
59 #if !MONO
60 [System.Security.SecurityCritical] // auto-generated
61 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
62 [ResourceExposure(ResourceScope.None)]
63 [SuppressUnmanagedCodeSecurity]
64 private static extern void DecryptKey(SafeKeyHandle pKeyContext,
65 [MarshalAs(UnmanagedType.LPArray)] byte[] pbEncryptedKey,
66 int cbEncryptedKey,
67 [MarshalAs(UnmanagedType.Bool)] bool fOAEP,
68 ObjectHandleOnStack ohRetDecryptedKey);
70 [System.Security.SecurityCritical] // auto-generated
71 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
72 [ResourceExposure(ResourceScope.None)]
73 [SuppressUnmanagedCodeSecurity]
74 private static extern void EncryptKey(SafeKeyHandle pKeyContext,
75 [MarshalAs(UnmanagedType.LPArray)] byte[] pbKey,
76 int cbKey,
77 [MarshalAs(UnmanagedType.Bool)] bool fOAEP,
78 ObjectHandleOnStack ohRetEncryptedKey);
81 // public constructors
84 [System.Security.SecuritySafeCritical] // auto-generated
85 [ResourceExposure(ResourceScope.None)]
86 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
87 public RSACryptoServiceProvider()
88 : this(0, new CspParameters(Utils.DefaultRsaProviderType, null, null, s_UseMachineKeyStore), true) {
91 [System.Security.SecuritySafeCritical] // auto-generated
92 [ResourceExposure(ResourceScope.None)]
93 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
94 public RSACryptoServiceProvider(int dwKeySize)
95 : this(dwKeySize, new CspParameters(Utils.DefaultRsaProviderType, null, null, s_UseMachineKeyStore), false) {
98 [System.Security.SecuritySafeCritical] // auto-generated
99 public RSACryptoServiceProvider(CspParameters parameters)
100 : this(0, parameters, true) {
103 [System.Security.SecuritySafeCritical] // auto-generated
104 public RSACryptoServiceProvider(int dwKeySize, CspParameters parameters)
105 : this(dwKeySize, parameters, false) {
109 // private methods
112 [System.Security.SecurityCritical] // auto-generated
113 private RSACryptoServiceProvider(int dwKeySize, CspParameters parameters, bool useDefaultKeySize) {
114 if (dwKeySize < 0)
115 throw new ArgumentOutOfRangeException("dwKeySize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
116 Contract.EndContractBlock();
118 _parameters = Utils.SaveCspParameters(CspAlgorithmType.Rsa, parameters, s_UseMachineKeyStore, ref _randomKeyContainer);
120 LegalKeySizesValue = new KeySizes[] { new KeySizes(384, 16384, 8) };
121 _dwKeySize = useDefaultKeySize ? 1024 : dwKeySize;
123 // If this is not a random container we generate, create it eagerly
124 // in the constructor so we can report any errors now.
125 if (!_randomKeyContainer
126 #if !FEATURE_CORECLR
127 || Environment.GetCompatibilityFlag(CompatibilityFlag.EagerlyGenerateRandomAsymmKeys)
128 #endif //!FEATURE_CORECLR
130 GetKeyPair();
133 [System.Security.SecurityCritical] // auto-generated
134 private void GetKeyPair () {
135 if (_safeKeyHandle == null) {
136 lock (this) {
137 if (_safeKeyHandle == null) {
138 // We only attempt to generate a random key on desktop runtimes because the CoreCLR
139 // RSA surface area is limited to simply verifying signatures. Since generating a
140 // random key to verify signatures will always lead to failure (unless we happend to
141 // win the lottery and randomly generate the signing key ...), there is no need
142 // to add this functionality to CoreCLR at this point.
143 Utils.GetKeyPairHelper(CspAlgorithmType.Rsa, _parameters, _randomKeyContainer, _dwKeySize, ref _safeProvHandle, ref _safeKeyHandle);
149 [System.Security.SecuritySafeCritical] // overrides public transparent member
150 protected override void Dispose(bool disposing)
152 base.Dispose(disposing);
154 if (_safeKeyHandle != null && !_safeKeyHandle.IsClosed)
155 _safeKeyHandle.Dispose();
156 if (_safeProvHandle != null && !_safeProvHandle.IsClosed)
157 _safeProvHandle.Dispose();
161 // public properties
164 [System.Runtime.InteropServices.ComVisible(false)]
165 public bool PublicOnly {
166 [System.Security.SecuritySafeCritical] // auto-generated
167 get {
168 GetKeyPair();
169 byte[] publicKey = (byte[]) Utils._GetKeyParameter(_safeKeyHandle, Constants.CLR_PUBLICKEYONLY);
170 return (publicKey[0] == 1);
174 [System.Runtime.InteropServices.ComVisible(false)]
175 public CspKeyContainerInfo CspKeyContainerInfo {
176 [System.Security.SecuritySafeCritical] // auto-generated
177 get {
178 GetKeyPair();
179 return new CspKeyContainerInfo(_parameters, _randomKeyContainer);
183 public override int KeySize {
184 [System.Security.SecuritySafeCritical] // auto-generated
185 get {
186 GetKeyPair();
187 byte[] keySize = (byte[]) Utils._GetKeyParameter(_safeKeyHandle, Constants.CLR_KEYLEN);
188 _dwKeySize = (keySize[0] | (keySize[1] << 8) | (keySize[2] << 16) | (keySize[3] << 24));
189 return _dwKeySize;
193 public override string KeyExchangeAlgorithm {
194 get {
195 if (_parameters.KeyNumber == Constants.AT_KEYEXCHANGE)
196 return "RSA-PKCS1-KeyEx";
197 return null;
200 #endif
201 public override string SignatureAlgorithm {
202 get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; }
205 public static bool UseMachineKeyStore {
206 get { return (s_UseMachineKeyStore == CspProviderFlags.UseMachineKeyStore); }
207 set { s_UseMachineKeyStore = (value ? CspProviderFlags.UseMachineKeyStore : 0); }
209 #if !MONO
210 public bool PersistKeyInCsp {
211 [System.Security.SecuritySafeCritical] // auto-generated
212 get {
213 if (_safeProvHandle == null) {
214 lock (this) {
215 if (_safeProvHandle == null)
216 _safeProvHandle = Utils.CreateProvHandle(_parameters, _randomKeyContainer);
219 return Utils.GetPersistKeyInCsp(_safeProvHandle);
221 [System.Security.SecuritySafeCritical] // auto-generated
222 set {
223 bool oldPersistKeyInCsp = this.PersistKeyInCsp;
224 if (value == oldPersistKeyInCsp)
225 return;
227 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
228 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
229 if (!value) {
230 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Delete);
231 kp.AccessEntries.Add(entry);
232 } else {
233 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Create);
234 kp.AccessEntries.Add(entry);
236 kp.Demand();
239 Utils.SetPersistKeyInCsp(_safeProvHandle, value);
244 // public methods
247 [System.Security.SecuritySafeCritical] // auto-generated
248 public override RSAParameters ExportParameters (bool includePrivateParameters) {
249 GetKeyPair();
250 if (includePrivateParameters) {
251 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
252 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
253 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Export);
254 kp.AccessEntries.Add(entry);
255 kp.Demand();
258 RSACspObject rsaCspObject = new RSACspObject();
259 int blobType = includePrivateParameters ? Constants.PRIVATEKEYBLOB : Constants.PUBLICKEYBLOB;
260 // _ExportKey will check for failures and throw an exception
261 Utils._ExportKey(_safeKeyHandle, blobType, rsaCspObject);
262 return RSAObjectToStruct(rsaCspObject);
265 #if FEATURE_LEGACYNETCFCRYPTO
266 [System.Security.SecurityCritical]
267 #else
268 [System.Security.SecuritySafeCritical] // auto-generated
269 #endif
270 [System.Runtime.InteropServices.ComVisible(false)]
271 public byte[] ExportCspBlob (bool includePrivateParameters) {
272 GetKeyPair();
273 return Utils.ExportCspBlobHelper(includePrivateParameters, _parameters, _safeKeyHandle);
276 [System.Security.SecuritySafeCritical] // auto-generated
277 public override void ImportParameters(RSAParameters parameters) {
278 // Free the current key handle
279 if (_safeKeyHandle != null && !_safeKeyHandle.IsClosed) {
280 _safeKeyHandle.Dispose();
281 _safeKeyHandle = null;
284 RSACspObject rsaCspObject = RSAStructToObject(parameters);
285 _safeKeyHandle = SafeKeyHandle.InvalidHandle;
287 if (IsPublic(parameters)) {
288 // Use our CRYPT_VERIFYCONTEXT handle, CRYPT_EXPORTABLE is not applicable to public only keys, so pass false
289 Utils._ImportKey(Utils.StaticProvHandle, Constants.CALG_RSA_KEYX, (CspProviderFlags) 0, rsaCspObject, ref _safeKeyHandle);
290 } else {
291 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
292 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
293 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Import);
294 kp.AccessEntries.Add(entry);
295 kp.Demand();
297 if (_safeProvHandle == null)
298 _safeProvHandle = Utils.CreateProvHandle(_parameters, _randomKeyContainer);
299 // Now, import the key into the CSP; _ImportKey will check for failures.
300 Utils._ImportKey(_safeProvHandle, Constants.CALG_RSA_KEYX, _parameters.Flags, rsaCspObject, ref _safeKeyHandle);
304 #if FEATURE_LEGACYNETCFCRYPTO
305 [System.Security.SecurityCritical]
306 #else
307 [System.Security.SecuritySafeCritical] // auto-generated
308 #endif
309 [System.Runtime.InteropServices.ComVisible(false)]
310 public void ImportCspBlob (byte[] keyBlob) {
311 Utils.ImportCspBlobHelper(CspAlgorithmType.Rsa, keyBlob, IsPublic(keyBlob), ref _parameters, _randomKeyContainer, ref _safeProvHandle, ref _safeKeyHandle);
314 public byte[] SignData(Stream inputStream, Object halg) {
315 int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
316 HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg);
317 byte[] hashVal = hash.ComputeHash(inputStream);
318 return SignHash(hashVal, calgHash);
321 public byte[] SignData(byte[] buffer, Object halg) {
322 int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
323 HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg);
324 byte[] hashVal = hash.ComputeHash(buffer);
325 return SignHash(hashVal, calgHash);
328 public byte[] SignData(byte[] buffer, int offset, int count, Object halg) {
329 int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
330 HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg);
331 byte[] hashVal = hash.ComputeHash(buffer, offset, count);
332 return SignHash(hashVal, calgHash);
335 public bool VerifyData(byte[] buffer, Object halg, byte[] signature) {
336 int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
337 HashAlgorithm hash = Utils.ObjToHashAlgorithm(halg);
338 byte[] hashVal = hash.ComputeHash(buffer);
339 return VerifyHash(hashVal, calgHash, signature);
342 public byte[] SignHash(byte[] rgbHash, string str) {
343 if (rgbHash == null)
344 throw new ArgumentNullException("rgbHash");
345 Contract.EndContractBlock();
346 if (PublicOnly)
347 throw new CryptographicException(Environment.GetResourceString("Cryptography_CSP_NoPrivateKey"));
349 int calgHash = X509Utils.NameOrOidToAlgId(str, OidGroup.HashAlgorithm);
350 return SignHash(rgbHash, calgHash);
353 [SecuritySafeCritical]
354 internal byte[] SignHash(byte[] rgbHash, int calgHash) {
355 Contract.Requires(rgbHash != null);
357 GetKeyPair();
358 if (!CspKeyContainerInfo.RandomlyGenerated) {
359 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
360 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
361 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Sign);
362 kp.AccessEntries.Add(entry);
363 kp.Demand();
366 return Utils.SignValue(_safeKeyHandle, _parameters.KeyNumber, Constants.CALG_RSA_SIGN, calgHash, rgbHash);
369 public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature) {
370 if (rgbHash == null)
371 throw new ArgumentNullException("rgbHash");
372 if (rgbSignature == null)
373 throw new ArgumentNullException("rgbSignature");
374 Contract.EndContractBlock();
376 int calgHash = X509Utils.NameOrOidToAlgId(str, OidGroup.HashAlgorithm);
377 return VerifyHash(rgbHash, calgHash, rgbSignature);
380 [SecuritySafeCritical]
381 internal bool VerifyHash(byte[] rgbHash, int calgHash, byte[] rgbSignature) {
382 Contract.Requires(rgbHash != null);
383 Contract.Requires(rgbSignature != null);
385 GetKeyPair();
387 return Utils.VerifySign(_safeKeyHandle, Constants.CALG_RSA_SIGN, calgHash, rgbHash, rgbSignature);
390 /// <summary>
391 /// Encrypt raw data, generally used for encrypting symmetric key material.
392 /// </summary>
393 /// <remarks>
394 /// This method can only encrypt (keySize - 88 bits) of data, so should not be used for encrypting
395 /// arbitrary byte arrays. Instead, encrypt a symmetric key with this method, and use the symmetric
396 /// key to encrypt the sensitive data.
397 /// </remarks>
398 /// <param name="rgb">raw data to encryt</param>
399 /// <param name="fOAEP">true to use OAEP padding (PKCS #1 v2), false to use PKCS #1 type 2 padding</param>
400 /// <returns>Encrypted key</returns>
401 [System.Security.SecuritySafeCritical] // auto-generated
402 public byte[] Encrypt(byte[] rgb, bool fOAEP) {
403 if (rgb == null)
404 throw new ArgumentNullException("rgb");
405 Contract.EndContractBlock();
407 GetKeyPair();
409 byte[] encryptedKey = null;
410 EncryptKey(_safeKeyHandle, rgb, rgb.Length, fOAEP, JitHelpers.GetObjectHandleOnStack(ref encryptedKey));
411 return encryptedKey;
414 /// <summary>
415 /// Decrypt raw data, generally used for decrypting symmetric key material
416 /// </summary>
417 /// <param name="rgb">encrypted data</param>
418 /// <param name="fOAEP">true to use OAEP padding (PKCS #1 v2), false to use PKCS #1 type 2 padding</param>
419 /// <returns>decrypted data</returns>
420 [System.Security.SecuritySafeCritical] // auto-generated
421 public byte [] Decrypt(byte[] rgb, bool fOAEP) {
422 if (rgb == null)
423 throw new ArgumentNullException("rgb");
424 Contract.EndContractBlock();
426 GetKeyPair();
428 // size check -- must be at most the modulus size
429 if (rgb.Length > (KeySize / 8))
430 throw new CryptographicException(Environment.GetResourceString("Cryptography_Padding_DecDataTooBig", KeySize / 8));
432 if (!CspKeyContainerInfo.RandomlyGenerated) {
433 if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) {
434 KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
435 KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(_parameters, KeyContainerPermissionFlags.Decrypt);
436 kp.AccessEntries.Add(entry);
437 kp.Demand();
441 byte[] decryptedKey = null;
442 DecryptKey(_safeKeyHandle, rgb, rgb.Length, fOAEP, JitHelpers.GetObjectHandleOnStack(ref decryptedKey));
443 return decryptedKey;
446 public override byte[] DecryptValue(byte[] rgb) {
447 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method"));
450 public override byte[] EncryptValue(byte[] rgb) {
451 throw new NotSupportedException(Environment.GetResourceString("NotSupported_Method"));
455 // private static methods
458 private static RSAParameters RSAObjectToStruct (RSACspObject rsaCspObject) {
459 RSAParameters rsaParams = new RSAParameters();
460 rsaParams.Exponent = rsaCspObject.Exponent;
461 rsaParams.Modulus = rsaCspObject.Modulus;
462 rsaParams.P = rsaCspObject.P;
463 rsaParams.Q = rsaCspObject.Q;
464 rsaParams.DP = rsaCspObject.DP;
465 rsaParams.DQ = rsaCspObject.DQ;
466 rsaParams.InverseQ = rsaCspObject.InverseQ;
467 rsaParams.D = rsaCspObject.D;
468 return rsaParams;
471 private static RSACspObject RSAStructToObject (RSAParameters rsaParams) {
472 RSACspObject rsaCspObject = new RSACspObject();
473 rsaCspObject.Exponent = rsaParams.Exponent;
474 rsaCspObject.Modulus = rsaParams.Modulus;
475 rsaCspObject.P = rsaParams.P;
476 rsaCspObject.Q = rsaParams.Q;
477 rsaCspObject.DP = rsaParams.DP;
478 rsaCspObject.DQ = rsaParams.DQ;
479 rsaCspObject.InverseQ = rsaParams.InverseQ;
480 rsaCspObject.D = rsaParams.D;
481 return rsaCspObject;
484 // find whether an RSA key blob is public.
485 private static bool IsPublic (byte[] keyBlob) {
486 if (keyBlob == null)
487 throw new ArgumentNullException("keyBlob");
488 Contract.EndContractBlock();
490 // The CAPI RSA public key representation consists of the following sequence:
491 // - BLOBHEADER
492 // - RSAPUBKEY
494 // The first should be PUBLICKEYBLOB and magic should be RSA_PUB_MAGIC "RSA1"
495 if (keyBlob[0] != Constants.PUBLICKEYBLOB)
496 return false;
498 if (keyBlob[11] != 0x31 || keyBlob[10] != 0x41 || keyBlob[9] != 0x53 || keyBlob[8] != 0x52)
499 return false;
501 return true;
504 // Since P is required, we will assume its presence is synonymous to a private key.
505 private static bool IsPublic(RSAParameters rsaParams) {
506 return (rsaParams.P == null);
508 #endif
510 // Adapt new RSA abstraction to legacy RSACryptoServiceProvider surface area.
513 // NOTE: For the new API, we go straight to CAPI for fixed set of hash algorithms and don't use crypto config here.
515 // Reasons:
516 // 1. We're moving away from crypto config and we won't have it when porting to .NET Core
518 // 2. It's slow to lookup and slow to use as the base HashAlgorithm adds considerable overhead
519 // (redundant defensive copy + double-initialization for the single-use case).
522 [SecuritySafeCritical]
523 protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) {
524 // we're sealed and the base should have checked this already
525 Contract.Assert(data != null);
526 Contract.Assert(offset >= 0 && offset <= data.Length);
527 Contract.Assert(count >= 0 && count <= data.Length);
528 Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
530 #if MONO
531 var hash = HashAlgorithm.Create (hashAlgorithm.Name);
532 return hash.ComputeHash (data, offset, count);
533 #else
534 using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
535 Utils.HashData(hashHandle, data, offset, count);
536 return Utils.EndHash(hashHandle);
538 #endif
541 [SecuritySafeCritical]
542 protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) {
543 // we're sealed and the base should have checked this already
544 Contract.Assert(data != null);
545 Contract.Assert(!String.IsNullOrEmpty(hashAlgorithm.Name));
547 #if MONO
548 var hash = HashAlgorithm.Create (hashAlgorithm.Name);
549 return hash.ComputeHash (data);
550 #else
551 using (SafeHashHandle hashHandle = Utils.CreateHash(Utils.StaticProvHandle, GetAlgorithmId(hashAlgorithm))) {
552 // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm
553 byte[] buffer = new byte[4096];
554 int bytesRead = 0;
555 do {
556 bytesRead = data.Read(buffer, 0, buffer.Length);
557 if (bytesRead > 0) {
558 Utils.HashData(hashHandle, buffer, 0, bytesRead);
560 } while (bytesRead > 0);
562 return Utils.EndHash(hashHandle);
564 #endif
567 private static int GetAlgorithmId(HashAlgorithmName hashAlgorithm) {
568 switch (hashAlgorithm.Name) {
569 case "MD5":
570 return Constants.CALG_MD5;
571 case "SHA1":
572 return Constants.CALG_SHA1;
573 case "SHA256":
574 return Constants.CALG_SHA_256;
575 case "SHA384":
576 return Constants.CALG_SHA_384;
577 case "SHA512":
578 return Constants.CALG_SHA_512;
579 default:
580 throw new CryptographicException(Environment.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm.Name));
584 public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) {
585 if (data == null) {
586 throw new ArgumentNullException("data");
588 if (padding == null) {
589 throw new ArgumentNullException("padding");
592 if (padding == RSAEncryptionPadding.Pkcs1) {
593 return Encrypt(data, fOAEP: false);
594 } else if (padding == RSAEncryptionPadding.OaepSHA1) {
595 return Encrypt(data, fOAEP: true);
596 } else {
597 throw PaddingModeNotSupported();
601 public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) {
602 if (data == null) {
603 throw new ArgumentNullException("data");
605 if (padding == null) {
606 throw new ArgumentNullException("padding");
609 if (padding == RSAEncryptionPadding.Pkcs1) {
610 return Decrypt(data, fOAEP: false);
611 } else if (padding == RSAEncryptionPadding.OaepSHA1) {
612 return Decrypt(data, fOAEP: true);
613 } else {
614 throw PaddingModeNotSupported();
618 public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
619 if (hash == null) {
620 throw new ArgumentNullException("hash");
622 if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
623 throw HashAlgorithmNameNullOrEmpty();
625 if (padding == null) {
626 throw new ArgumentNullException("padding");
628 if (padding != RSASignaturePadding.Pkcs1) {
629 throw PaddingModeNotSupported();
632 return SignHash(hash, GetAlgorithmId(hashAlgorithm));
635 public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) {
636 if (hash == null) {
637 throw new ArgumentNullException("hash");
639 if (signature == null) {
640 throw new ArgumentNullException("signature");
642 if (String.IsNullOrEmpty(hashAlgorithm.Name)) {
643 throw HashAlgorithmNameNullOrEmpty();
645 if (padding == null) {
646 throw new ArgumentNullException("padding");
648 if (padding != RSASignaturePadding.Pkcs1) {
649 throw PaddingModeNotSupported();
652 return VerifyHash(hash, GetAlgorithmId(hashAlgorithm), signature);
655 private static Exception PaddingModeNotSupported() {
656 return new CryptographicException(Environment.GetResourceString("Cryptography_InvalidPaddingMode"));