Merge pull request #3213 from henricm/fix-for-win-securestring-to-bstr
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / rsapkcs1keyexchangedeformatter.cs
1 using System.Diagnostics.Contracts;
2 // ==++==
3 // 
4 //   Copyright (c) Microsoft Corporation.  All rights reserved.
5 // 
6 // ==--==
7 // <OWNER>[....]</OWNER>
8 // 
9
10 namespace System.Security.Cryptography {
11     [System.Runtime.InteropServices.ComVisible(true)]
12     public class RSAPKCS1KeyExchangeDeformatter : AsymmetricKeyExchangeDeformatter {
13         RSA _rsaKey;
14         bool?  _rsaOverridesDecrypt;
15         RandomNumberGenerator RngValue;
16
17         // Constructors
18
19         public RSAPKCS1KeyExchangeDeformatter() {}
20
21         public RSAPKCS1KeyExchangeDeformatter(AsymmetricAlgorithm key) {
22             if (key == null) 
23                 throw new ArgumentNullException("key");
24             Contract.EndContractBlock();
25             _rsaKey = (RSA) key;
26         }
27
28         //
29         // public properties
30         //
31
32         public RandomNumberGenerator RNG {
33             get { return RngValue; }
34             set { RngValue = value; }
35         }
36         
37         public override String Parameters {
38             get { return null; }
39             set { ;}
40         }
41
42         //
43         // public methods
44         //
45
46         public override byte[] DecryptKeyExchange(byte[] rgbIn) {
47             if (_rsaKey == null)
48                 throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_MissingKey"));
49
50             byte[] rgbOut;
51             if (OverridesDecrypt) {
52                 rgbOut = _rsaKey.Decrypt(rgbIn, RSAEncryptionPadding.Pkcs1);
53             }
54             else {
55                 int i;
56                 byte[] rgb;
57                 rgb = _rsaKey.DecryptValue(rgbIn);
58
59                 //
60                 //  Expected format is:
61                 //      00 || 02 || PS || 00 || D
62                 //      where PS does not contain any zeros.
63                 //
64
65                 for (i = 2; i<rgb.Length; i++) {
66                     if (rgb[i] == 0) {
67                         break;
68                     }
69                 }
70
71                 if (i >= rgb.Length)
72                     throw new CryptographicUnexpectedOperationException(Environment.GetResourceString("Cryptography_PKCS1Decoding"));
73
74                 i++;            // Skip over the zero
75
76                 rgbOut = new byte[rgb.Length - i];
77                 Buffer.InternalBlockCopy(rgb, i, rgbOut, 0, rgbOut.Length);
78             }
79             return rgbOut;
80         }
81
82         public override void SetKey(AsymmetricAlgorithm key) {
83             if (key == null) 
84                 throw new ArgumentNullException("key");
85             Contract.EndContractBlock();
86             _rsaKey = (RSA) key;
87             _rsaOverridesDecrypt = default(bool?);
88         }
89
90         private bool OverridesDecrypt {
91             get {
92                 if (!_rsaOverridesDecrypt.HasValue) {
93                     _rsaOverridesDecrypt = Utils.DoesRsaKeyOverride(_rsaKey, "Decrypt", new Type[] { typeof(byte[]), typeof(RSAEncryptionPadding) });
94                 }
95                 return _rsaOverridesDecrypt.Value;
96             }
97         }
98     }
99 }