Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / rsapkcs1signatureformatter.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 //
10 // RSAPKCS1SignatureFormatter.cs
11 //
12
13 using System;
14 using System.Diagnostics.Contracts;
15 using System.Security.Cryptography.X509Certificates;
16
17 namespace System.Security.Cryptography {
18     [System.Runtime.InteropServices.ComVisible(true)]
19     public class RSAPKCS1SignatureFormatter : AsymmetricSignatureFormatter {
20         private RSA    _rsaKey;
21         private String _strOID;
22         private bool?  _rsaOverridesSignHash;
23
24         //
25         // public constructors
26         //
27
28         public RSAPKCS1SignatureFormatter() {}
29
30         public RSAPKCS1SignatureFormatter(AsymmetricAlgorithm key) {
31             if (key == null) 
32                 throw new ArgumentNullException("key");
33             Contract.EndContractBlock();
34             _rsaKey = (RSA) key;
35         }
36
37         //
38         // public methods
39         //
40
41         public override void SetKey(AsymmetricAlgorithm key) {
42             if (key == null) 
43                 throw new ArgumentNullException("key");
44             Contract.EndContractBlock();
45             _rsaKey = (RSA) key;
46             _rsaOverridesSignHash = default(bool?);
47         }
48
49         public override void SetHashAlgorithm(String strName) {
50             _strOID = CryptoConfig.MapNameToOID(strName, OidGroup.HashAlgorithm);
51         }
52
53         [System.Security.SecuritySafeCritical]  // auto-generated
54         public override byte[] CreateSignature(byte[] rgbHash) {
55             if (rgbHash == null)
56                 throw new ArgumentNullException("rgbHash");
57             Contract.EndContractBlock();
58
59             if (_strOID == null)
60                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingOID"));
61             if (_rsaKey == null)
62                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
63
64             // Two cases here -- if we are talking to the CSP version or if we are talking to some other RSA provider.
65             if (_rsaKey is RSACryptoServiceProvider) {
66                 // This path is kept around for desktop compat: in case someone is using this with a hash algorithm that's known to GetAlgIdFromOid but
67                 // not from OidToHashAlgorithmName.
68                 int calgHash = X509Utils.GetAlgIdFromOid(_strOID, OidGroup.HashAlgorithm);
69                 return ((RSACryptoServiceProvider)_rsaKey).SignHash(rgbHash, calgHash);
70             }
71             else if (OverridesSignHash) {
72                 HashAlgorithmName hashAlgorithmName = Utils.OidToHashAlgorithmName(_strOID);
73                 return _rsaKey.SignHash(rgbHash, hashAlgorithmName, RSASignaturePadding.Pkcs1);
74             }
75             else {
76                 // Fallback compat path for 3rd-party RSA classes that don't override SignHash()
77
78                 byte[] pad = Utils.RsaPkcs1Padding(_rsaKey, CryptoConfig.EncodeOID(_strOID), rgbHash);
79                 // Create the signature by applying the private key to the padded buffer we just created.
80                 return _rsaKey.DecryptValue(pad);
81             }
82         }
83
84         private bool OverridesSignHash {
85             get {
86                 if (!_rsaOverridesSignHash.HasValue) {
87                     _rsaOverridesSignHash = Utils.DoesRsaKeyOverride(_rsaKey, "SignHash", new Type[] { typeof(byte[]), typeof(HashAlgorithmName), typeof(RSASignaturePadding) });
88                 }
89                 return _rsaOverridesSignHash.Value;
90             }
91         }
92     }
93 }