3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
10 // RSACryptoServiceProvider.cs
12 // CSP-based implementation of RSA
15 namespace System
.Security
.Cryptography
{
17 using System
.Globalization
;
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
;
28 // Object layout of the RSAParameters structure
29 internal class RSACspObject
{
30 internal byte[] Exponent
;
31 internal byte[] Modulus
;
36 internal byte[] InverseQ
;
41 [System
.Runtime
.InteropServices
.ComVisible(true)]
42 public sealed partial class RSACryptoServiceProvider
: RSA
43 , ICspAsymmetricAlgorithm
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
;
54 private static volatile CspProviderFlags s_UseMachineKeyStore
= 0;
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
,
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
,
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) {
112 [System
.Security
.SecurityCritical
] // auto-generated
113 private RSACryptoServiceProvider(int dwKeySize
, CspParameters parameters
, bool useDefaultKeySize
) {
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
127 || Environment
.GetCompatibilityFlag(CompatibilityFlag
.EagerlyGenerateRandomAsymmKeys
)
128 #endif //!FEATURE_CORECLR
133 [System
.Security
.SecurityCritical
] // auto-generated
134 private void GetKeyPair () {
135 if (_safeKeyHandle
== null) {
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();
164 [System
.Runtime
.InteropServices
.ComVisible(false)]
165 public bool PublicOnly
{
166 [System
.Security
.SecuritySafeCritical
] // auto-generated
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
179 return new CspKeyContainerInfo(_parameters
, _randomKeyContainer
);
183 public override int KeySize
{
184 [System
.Security
.SecuritySafeCritical
] // auto-generated
187 byte[] keySize
= (byte[]) Utils
._GetKeyParameter(_safeKeyHandle
, Constants
.CLR_KEYLEN
);
188 _dwKeySize
= (keySize
[0] | (keySize
[1] << 8) | (keySize
[2] << 16) | (keySize
[3] << 24));
193 public override string KeyExchangeAlgorithm
{
195 if (_parameters
.KeyNumber
== Constants
.AT_KEYEXCHANGE
)
196 return "RSA-PKCS1-KeyEx";
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); }
210 public bool PersistKeyInCsp
{
211 [System
.Security
.SecuritySafeCritical
] // auto-generated
213 if (_safeProvHandle
== null) {
215 if (_safeProvHandle
== null)
216 _safeProvHandle
= Utils
.CreateProvHandle(_parameters
, _randomKeyContainer
);
219 return Utils
.GetPersistKeyInCsp(_safeProvHandle
);
221 [System
.Security
.SecuritySafeCritical
] // auto-generated
223 bool oldPersistKeyInCsp
= this.PersistKeyInCsp
;
224 if (value == oldPersistKeyInCsp
)
227 if (!CompatibilitySwitches
.IsAppEarlierThanWindowsPhone8
) {
228 KeyContainerPermission kp
= new KeyContainerPermission(KeyContainerPermissionFlags
.NoFlags
);
230 KeyContainerPermissionAccessEntry entry
= new KeyContainerPermissionAccessEntry(_parameters
, KeyContainerPermissionFlags
.Delete
);
231 kp
.AccessEntries
.Add(entry
);
233 KeyContainerPermissionAccessEntry entry
= new KeyContainerPermissionAccessEntry(_parameters
, KeyContainerPermissionFlags
.Create
);
234 kp
.AccessEntries
.Add(entry
);
239 Utils
.SetPersistKeyInCsp(_safeProvHandle
, value);
247 [System
.Security
.SecuritySafeCritical
] // auto-generated
248 public override RSAParameters
ExportParameters (bool includePrivateParameters
) {
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
);
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
]
268 [System
.Security
.SecuritySafeCritical
] // auto-generated
270 [System
.Runtime
.InteropServices
.ComVisible(false)]
271 public byte[] ExportCspBlob (bool includePrivateParameters
) {
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
);
291 if (!CompatibilitySwitches
.IsAppEarlierThanWindowsPhone8
) {
292 KeyContainerPermission kp
= new KeyContainerPermission(KeyContainerPermissionFlags
.NoFlags
);
293 KeyContainerPermissionAccessEntry entry
= new KeyContainerPermissionAccessEntry(_parameters
, KeyContainerPermissionFlags
.Import
);
294 kp
.AccessEntries
.Add(entry
);
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
]
307 [System
.Security
.SecuritySafeCritical
] // auto-generated
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
) {
344 throw new ArgumentNullException("rgbHash");
345 Contract
.EndContractBlock();
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);
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
);
366 return Utils
.SignValue(_safeKeyHandle
, _parameters
.KeyNumber
, Constants
.CALG_RSA_SIGN
, calgHash
, rgbHash
);
369 public bool VerifyHash(byte[] rgbHash
, string str
, byte[] rgbSignature
) {
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);
387 return Utils
.VerifySign(_safeKeyHandle
, Constants
.CALG_RSA_SIGN
, calgHash
, rgbHash
, rgbSignature
);
391 /// Encrypt raw data, generally used for encrypting symmetric key material.
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.
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
) {
404 throw new ArgumentNullException("rgb");
405 Contract
.EndContractBlock();
409 byte[] encryptedKey
= null;
410 EncryptKey(_safeKeyHandle
, rgb
, rgb
.Length
, fOAEP
, JitHelpers
.GetObjectHandleOnStack(ref encryptedKey
));
415 /// Decrypt raw data, generally used for decrypting symmetric key material
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
) {
423 throw new ArgumentNullException("rgb");
424 Contract
.EndContractBlock();
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
);
441 byte[] decryptedKey
= null;
442 DecryptKey(_safeKeyHandle
, rgb
, rgb
.Length
, fOAEP
, JitHelpers
.GetObjectHandleOnStack(ref 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
;
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
;
484 // find whether an RSA key blob is public.
485 private static bool IsPublic (byte[] keyBlob
) {
487 throw new ArgumentNullException("keyBlob");
488 Contract
.EndContractBlock();
490 // The CAPI RSA public key representation consists of the following sequence:
494 // The first should be PUBLICKEYBLOB and magic should be RSA_PUB_MAGIC "RSA1"
495 if (keyBlob
[0] != Constants
.PUBLICKEYBLOB
)
498 if (keyBlob
[11] != 0x31 || keyBlob
[10] != 0x41 || keyBlob
[9] != 0x53 || keyBlob
[8] != 0x52)
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);
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.
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
));
531 var hash
= HashAlgorithm
.Create (hashAlgorithm
.Name
);
532 return hash
.ComputeHash (data
, offset
, count
);
534 using (SafeHashHandle hashHandle
= Utils
.CreateHash(Utils
.StaticProvHandle
, GetAlgorithmId(hashAlgorithm
))) {
535 Utils
.HashData(hashHandle
, data
, offset
, count
);
536 return Utils
.EndHash(hashHandle
);
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
));
548 var hash
= HashAlgorithm
.Create (hashAlgorithm
.Name
);
549 return hash
.ComputeHash (data
);
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];
556 bytesRead
= data
.Read(buffer
, 0, buffer
.Length
);
558 Utils
.HashData(hashHandle
, buffer
, 0, bytesRead
);
560 } while (bytesRead
> 0);
562 return Utils
.EndHash(hashHandle
);
567 private static int GetAlgorithmId(HashAlgorithmName hashAlgorithm
) {
568 switch (hashAlgorithm
.Name
) {
570 return Constants
.CALG_MD5
;
572 return Constants
.CALG_SHA1
;
574 return Constants
.CALG_SHA_256
;
576 return Constants
.CALG_SHA_384
;
578 return Constants
.CALG_SHA_512
;
580 throw new CryptographicException(Environment
.GetResourceString("Cryptography_UnknownHashAlgorithm", hashAlgorithm
.Name
));
584 public override byte[] Encrypt(byte[] data
, RSAEncryptionPadding padding
) {
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);
597 throw PaddingModeNotSupported();
601 public override byte[] Decrypt(byte[] data
, RSAEncryptionPadding padding
) {
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);
614 throw PaddingModeNotSupported();
618 public override byte[] SignHash(byte[] hash
, HashAlgorithmName hashAlgorithm
, RSASignaturePadding padding
) {
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
) {
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"));