@@ -70,13 +70,16 @@ public static void Encrypt(this Stream inputStream, Stream outputStream, X509Cer
70
70
if ( null == cert ) throw new ArgumentNullException ( nameof ( cert ) ) ;
71
71
if ( null == algName ) throw new ArgumentNullException ( nameof ( algName ) ) ;
72
72
73
- // DO NOT Dispose this; Doing so will render the X509Certificate in cache use-less.
73
+ // Encrypt using Public key.
74
+ // DO NOT Dispose this; Doing so will render the X509Certificate in the cache use-less.
75
+ // Did endurance test of 1 mil cycles, found NO HANDLE leak.
74
76
var keyEncryption = cert . GetRsaPublicKeyAsymmetricAlgorithm ( ) ;
75
77
76
78
using ( var dataEncryption = SymmetricAlgorithm . Create ( algName ) )
77
79
{
78
80
if ( null == dataEncryption ) throw new Exception ( $ "SymmetricAlgorithm.Create() returned null. Check algName: '{ algName } '") ;
79
81
82
+ // Select suggested keySize/blockSize.
80
83
dataEncryption . KeySize = keySize ;
81
84
dataEncryption . BlockSize = blockSize ;
82
85
Encrypt ( inputStream , outputStream , keyEncryption , dataEncryption ) ;
@@ -95,17 +98,24 @@ public static void Decrypt(this Stream inputStream, Stream outputStream, X509Cer
95
98
if ( null == cert ) throw new ArgumentNullException ( nameof ( cert ) ) ;
96
99
if ( null == algName ) throw new ArgumentNullException ( nameof ( algName ) ) ;
97
100
101
+ // Decrypt using Private key.
98
102
// DO NOT Dispose this; Doing so will render the X509Certificate in cache use-less.
103
+ // Did endurance test of 1 mil cycles, found NO HANDLE leak.
99
104
var keyEncryption = cert . GetRsaPrivateKeyAsymmetricAlgorithm ( ) ;
100
105
101
106
using ( var dataEncryption = SymmetricAlgorithm . Create ( algName ) )
102
107
{
103
108
if ( null == dataEncryption ) throw new Exception ( $ "SymmetricAlgorithm.Create() returned null. Check algName: '{ algName } '") ;
104
109
110
+ // KeySize/blockSize will be selected when we assign key/IV later.
105
111
Decrypt ( inputStream , outputStream , keyEncryption , dataEncryption ) ;
106
112
}
107
113
}
108
114
115
+ //...............................................................................
116
+ #region Encrypt/Decrypt the Key (Asymmetric) and the Data (Symmetric)
117
+ //...............................................................................
118
+
109
119
static void Encrypt ( Stream inputStream , Stream outputStream , AsymmetricAlgorithm keyEncryption , SymmetricAlgorithm dataEncryption )
110
120
{
111
121
if ( null == inputStream ) throw new ArgumentNullException ( nameof ( inputStream ) ) ;
@@ -131,6 +141,7 @@ static void Encrypt(Stream inputStream, Stream outputStream, AsymmetricAlgorithm
131
141
outputStream . WriteLengthAndBytes ( encryptedIV ) ;
132
142
133
143
// Write the encrypted data.
144
+ // Note: Disposing the CryptoStream also disposes the outputStream. There is no keepOpen option.
134
145
using ( var transform = dataEncryption . CreateEncryptor ( ) )
135
146
using ( var cryptoStream = new CryptoStream ( outputStream , transform , CryptoStreamMode . Write ) )
136
147
{
@@ -156,13 +167,17 @@ static void Decrypt(Stream inputStream, Stream outputStream, AsymmetricAlgorithm
156
167
// Trace.WriteLine($"Decrypting. KEK: {keyEncryption.GetType().Name} / {keyEncryption.KeySize} bits");
157
168
// Trace.WriteLine($"Decrypting. DEK: {dataEncryption.GetType().Name} / {dataEncryption.KeySize} bits / BlockSize: {dataEncryption.BlockSize} bits");
158
169
170
+ // Read the encrypted data.
171
+ // Note: Disposing the CryptoStream also disposes the inputStream. There is no keepOpen option.
159
172
using ( var transform = dataEncryption . CreateDecryptor ( ) )
160
173
using ( var cryptoStream = new CryptoStream ( inputStream , transform , CryptoStreamMode . Read ) )
161
174
{
162
175
cryptoStream . CopyTo ( outputStream , bufferSize : dataEncryption . BlockSize * 4 ) ;
163
176
}
164
177
}
165
178
179
+ #endregion
180
+
166
181
//...............................................................................
167
182
#region Utils: WriteLengthAndBytes(), ReadLengthAndBytes()
168
183
//...............................................................................
@@ -171,8 +186,10 @@ static void WriteLengthAndBytes(this Stream outputStream, byte[] bytes)
171
186
if ( null == outputStream ) throw new ArgumentNullException ( nameof ( outputStream ) ) ;
172
187
if ( null == bytes ) throw new ArgumentNullException ( nameof ( bytes ) ) ;
173
188
189
+ // Int32 length to exactly-four-bytes array.
174
190
var length = BitConverter . GetBytes ( ( Int32 ) bytes . Length ) ;
175
191
192
+ // Write the four-byte-length followed by the data.
176
193
outputStream . Write ( length , 0 , length . Length ) ;
177
194
outputStream . Write ( bytes , 0 , bytes . Length ) ;
178
195
}
@@ -188,7 +205,7 @@ static byte[] ReadLengthAndBytes(this Stream inputStream, int maxBytes)
188
205
189
206
// Length of data to read.
190
207
var length = BitConverter . ToInt32 ( arrLength , 0 ) ;
191
- if ( length > maxBytes ) throw new Exception ( $ "Unexpected data size { length : #,0} bytes. Expecting not more than { maxBytes : #,0} bytes.") ;
208
+ if ( length > maxBytes ) throw new Exception ( $ "Unexpected data size { length : #,0} bytes. Expecting NOT more than { maxBytes : #,0} bytes.") ;
192
209
193
210
// Read suggested no of bytes...
194
211
var bytes = new byte [ length ] ;
@@ -201,8 +218,9 @@ static byte[] ReadLengthAndBytes(this Stream inputStream, int maxBytes)
201
218
#endregion
202
219
203
220
//...............................................................................
204
- #region Obtain private/ public key AsymmetricAlgorithm
221
+ #region Obtain public/private key AsymmetricAlgorithm
205
222
//...............................................................................
223
+
206
224
static AsymmetricAlgorithm GetRsaPublicKeyAsymmetricAlgorithm ( this X509Certificate2 cert )
207
225
{
208
226
if ( null == cert ) throw new ArgumentNullException ( nameof ( cert ) ) ;
0 commit comments