7
7
using System . Reflection ;
8
8
using System . Security . Cryptography . X509Certificates ;
9
9
using System . Text ;
10
+ using Microsoft . Data . SqlClient . TestUtilities . Fixtures ;
10
11
using Xunit ;
11
12
using static Microsoft . Data . SqlClient . Tests . AlwaysEncryptedTests . Utility ;
12
13
13
14
namespace Microsoft . Data . SqlClient . Tests . AlwaysEncryptedTests
14
15
{
15
- public class ExceptionsAlgorithmErrors : IClassFixture < CertFixture >
16
+ public class ExceptionsAlgorithmErrors : IClassFixture < ColumnEncryptionCertificateFixture >
16
17
{
17
18
// Reflection
18
19
public static Assembly systemData = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
19
20
public static Type sqlClientSymmetricKey = systemData . GetType ( "Microsoft.Data.SqlClient.SqlClientSymmetricKey" ) ;
20
21
public static ConstructorInfo sqlColumnEncryptionKeyConstructor = sqlClientSymmetricKey . GetConstructor ( BindingFlags . NonPublic | BindingFlags . Instance , null , new Type [ ] { typeof ( byte [ ] ) } , null ) ;
21
22
23
+ private readonly ColumnEncryptionCertificateFixture _fixture ;
24
+ private readonly byte [ ] _cek ;
25
+ private readonly byte [ ] _encryptedCek ;
26
+ private readonly string _certificatePath ;
27
+
28
+ public ExceptionsAlgorithmErrors ( ColumnEncryptionCertificateFixture fixture )
29
+ {
30
+ // Disable the cache to avoid false failures.
31
+ SqlConnection . ColumnEncryptionQueryMetadataCacheEnabled = false ;
32
+
33
+ SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider ( ) ;
34
+ X509Certificate2 currUserCertificate = fixture . GetCertificate ( StoreLocation . CurrentUser ) ;
35
+
36
+ _cek = GenerateRandomBytes ( 32 ) ;
37
+ _fixture = fixture ;
38
+ _certificatePath = string . Format ( "CurrentUser/My/{0}" , currUserCertificate . Thumbprint ) ;
39
+ _encryptedCek = provider . EncryptColumnEncryptionKey ( _certificatePath , "RSA_OAEP" , _cek ) ;
40
+ }
41
+
22
42
[ Fact ]
23
43
[ PlatformSpecific ( TestPlatforms . Windows ) ]
24
44
public void TestNullCEK ( )
@@ -52,9 +72,9 @@ public void TestInvalidEncryptionType()
52
72
{
53
73
const byte invalidEncryptionType = 3 ;
54
74
Object cipherMD = GetSqlCipherMetadata ( 0 , 2 , null , invalidEncryptionType , 0x01 ) ;
55
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
75
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
56
76
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
57
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
77
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
58
78
59
79
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidEncryptionType ,
60
80
"AEAD_AES_256_CBC_HMAC_SHA256" , invalidEncryptionType , "'Deterministic', 'Randomized'" ) ;
@@ -74,7 +94,7 @@ public void TestInvalidCipherText()
74
94
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidCipherTextSize ,
75
95
invalidCiphertextLength , 65 ) ;
76
96
byte [ ] cipherText = GenerateRandomBytes ( invalidCiphertextLength ) ; // minimum length is 65
77
- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
97
+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
78
98
Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
79
99
}
80
100
@@ -85,10 +105,10 @@ public void TestInvalidAlgorithmVersion()
85
105
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidAlgorithmVersion ,
86
106
40 , "01" ) ;
87
107
byte [ ] plainText = Encoding . Unicode . GetBytes ( "Hello World" ) ;
88
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
108
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
89
109
// Put a version number of 0x10
90
110
cipherText [ 0 ] = 0x40 ;
91
- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
111
+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
92
112
Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
93
113
}
94
114
@@ -98,13 +118,13 @@ public void TestInvalidAuthenticationTag()
98
118
{
99
119
string expectedMessage = SystemDataResourceManager . Instance . TCE_InvalidAuthenticationTag ;
100
120
byte [ ] plainText = Encoding . Unicode . GetBytes ( "Hello World" ) ;
101
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
121
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
102
122
// Zero out 4 bytes of authentication tag
103
123
for ( int i = 0 ; i < 4 ; i ++ )
104
124
{
105
125
cipherText [ i + 1 ] = 0x00 ;
106
126
}
107
- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
127
+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
108
128
Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
109
129
}
110
130
@@ -115,9 +135,9 @@ public void TestNullColumnEncryptionAlgorithm()
115
135
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_NullColumnEncryptionAlgorithm ,
116
136
"'AEAD_AES_256_CBC_HMAC_SHA256'" ) ;
117
137
Object cipherMD = GetSqlCipherMetadata ( 0 , 0 , null , 1 , 0x01 ) ;
118
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
138
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
119
139
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
120
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
140
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
121
141
122
142
TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
123
143
Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
@@ -133,9 +153,9 @@ public void TestUnknownEncryptionAlgorithmId()
133
153
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnknownColumnEncryptionAlgorithmId ,
134
154
unknownEncryptionAlgoId , "'1', '2'" ) ;
135
155
Object cipherMD = GetSqlCipherMetadata ( 0 , unknownEncryptionAlgoId , null , 1 , 0x01 ) ;
136
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
156
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
137
157
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
138
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
158
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
139
159
140
160
Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( plainText , cipherMD ) ) ;
141
161
Assert . Matches ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -157,9 +177,9 @@ public void TestUnknownCustomKeyStoreProvider()
157
177
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnrecognizedKeyStoreProviderName ,
158
178
invalidProviderName , "'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'" , "" ) ;
159
179
Object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x03 ) ;
160
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , invalidProviderName , "RSA_OAEP" ) ;
180
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , invalidProviderName , "RSA_OAEP" ) ;
161
181
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
162
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
182
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
163
183
164
184
Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( plainText , cipherMD ) ) ;
165
185
Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -179,9 +199,9 @@ public void TestTceUnknownEncryptionAlgorithm()
179
199
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnknownColumnEncryptionAlgorithm ,
180
200
unknownEncryptionAlgorithm , "'AEAD_AES_256_CBC_HMAC_SHA256'" ) ;
181
201
Object cipherMD = GetSqlCipherMetadata ( 0 , 0 , "Dummy" , 1 , 0x01 ) ;
182
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
202
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
183
203
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
184
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
204
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
185
205
186
206
Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
187
207
Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -194,15 +214,15 @@ public void TestTceUnknownEncryptionAlgorithm()
194
214
[ PlatformSpecific ( TestPlatforms . Windows ) ]
195
215
public void TestExceptionsFromCertStore ( )
196
216
{
197
- byte [ ] corruptedCek = GenerateInvalidEncryptedCek ( CertFixture . cek , ECEKCorruption . SIGNATURE ) ;
217
+ byte [ ] corruptedCek = GenerateInvalidEncryptedCek ( _cek , ECEKCorruption . SIGNATURE ) ;
198
218
199
219
string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_KeyDecryptionFailedCertStore ,
200
220
"MSSQL_CERTIFICATE_STORE" , BitConverter . ToString ( corruptedCek , corruptedCek . Length - 10 , 10 ) ) ;
201
221
202
222
Object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x01 ) ;
203
- AddEncryptionKeyToCipherMD ( cipherMD , corruptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
223
+ AddEncryptionKeyToCipherMD ( cipherMD , corruptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
204
224
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
205
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
225
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
206
226
207
227
Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
208
228
Assert . Matches ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -224,9 +244,9 @@ public void TestExceptionsFromCustomKeyStore()
224
244
SqlConnection . RegisterColumnEncryptionKeyStoreProviders ( customProviders ) ;
225
245
226
246
object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x01 ) ;
227
- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "DummyProvider" , "DummyAlgo" ) ;
247
+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "DummyProvider" , "DummyAlgo" ) ;
228
248
byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
229
- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
249
+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
230
250
231
251
Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
232
252
Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -238,35 +258,4 @@ public void TestExceptionsFromCustomKeyStore()
238
258
}
239
259
}
240
260
}
241
-
242
- public class CertFixture : IDisposable
243
- {
244
- private readonly SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider ( ) ;
245
-
246
- public static X509Certificate2 certificate ;
247
- public static string thumbprint ;
248
- public static string certificatePath ;
249
- public static byte [ ] cek ;
250
- public static byte [ ] encryptedCek ;
251
-
252
- public CertFixture ( )
253
- {
254
- if ( certificate == null )
255
- {
256
- certificate = Utility . CreateCertificate ( ) ;
257
- }
258
- thumbprint = certificate . Thumbprint ;
259
- certificatePath = string . Format ( "CurrentUser/My/{0}" , thumbprint ) ;
260
- cek = GenerateRandomBytes ( 32 ) ;
261
- encryptedCek = provider . EncryptColumnEncryptionKey ( certificatePath , "RSA_OAEP" , cek ) ;
262
-
263
- // Disable the cache to avoid false failures.
264
- SqlConnection . ColumnEncryptionQueryMetadataCacheEnabled = false ;
265
- }
266
-
267
- public void Dispose ( )
268
- {
269
- // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well.
270
- }
271
- }
272
261
}
0 commit comments