-
Notifications
You must be signed in to change notification settings - Fork 329
Expand file tree
/
Copy pathCspProviderExt.cs
More file actions
146 lines (126 loc) · 6.73 KB
/
CspProviderExt.cs
File metadata and controls
146 lines (126 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Data.SqlClient.Tests.Common.Fixtures;
using Microsoft.Win32;
using Xunit;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
{
/// <summary>
/// Always Encrypted public CspProvider Manual tests.
/// </summary>
// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault.
[Trait("Set", "AE")]
[PlatformSpecific(TestPlatforms.Windows)]
public class CspProviderExt
{
// [Fact(Skip="Run this in non-parallel mode")] or [ConditionalFact()]
[Fact(Skip = "Failing in TCE")]
public void TestRoundTripWithCspAndCertStoreProvider()
{
using CspCertificateFixture cspCertificateFixture = new CspCertificateFixture();
X509Certificate2 cert = cspCertificateFixture.CspCertificate;
string cspPath = cspCertificateFixture.CspKeyPath;
string certificatePath = cspCertificateFixture.CspCertificatePath;
SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider();
SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider();
byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32);
byte[] encryptedColumnEncryptionKeyUsingCert = certProvider.EncryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", columnEncryptionKey);
byte[] columnEncryptionKeyReturnedCert2CSP = cspProvider.DecryptColumnEncryptionKey(cspPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert);
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2CSP));
byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey);
byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP);
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert));
}
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
[MemberData(nameof(TestEncryptDecryptWithCsp_Data))]
public void TestEncryptDecryptWithCsp(string connectionString, string providerName, int providerType)
{
string keyIdentifier = DataTestUtility.GetLongName("CSP");
CspParameters namedCspParameters = new CspParameters(providerType, providerName, keyIdentifier);
using SQLSetupStrategyCspProvider sqlSetupStrategyCsp = new SQLSetupStrategyCspProvider(namedCspParameters);
using SqlConnection sqlConn = new(connectionString);
sqlConn.Open();
// Test INPUT parameter on an encrypted parameter
string commandText = @$"SELECT CustomerId, FirstName, LastName " +
@$"FROM [{sqlSetupStrategyCsp.ApiTestTable.Name}] " +
@$"WHERE FirstName = @firstName";
using SqlCommand sqlCommand = new(commandText, sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled);
SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft");
customerFirstParam.Direction = System.Data.ParameterDirection.Input;
using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
ValidateResultSet(sqlDataReader);
}
public static IEnumerable<object[]> TestEncryptDecryptWithCsp_Data
{
get
{
// xUnit evaluates MemberData during discovery, before [PlatformSpecific]
// can skip execution. Guard here to prevent Registry access on non-Windows.
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
yield break;
}
const string providerRegistryKeyPath = @"SOFTWARE\Microsoft\Cryptography\Defaults\Provider";
using RegistryKey defaultProviderRegistryKey = Registry.LocalMachine.OpenSubKey(providerRegistryKeyPath);
if (defaultProviderRegistryKey is null)
{
// No test cases can be generated if the registry key doesn't exist.
yield break;
}
foreach (string subKeyName in defaultProviderRegistryKey.GetSubKeyNames())
{
// Skip inappropriate providers
if (!subKeyName.Contains(@"RSA and AES"))
{
continue;
}
// Open the provider
using RegistryKey providerKey = defaultProviderRegistryKey.OpenSubKey(subKeyName);
if (providerKey is null)
{
continue;
}
// Read provider name
string providerName = Path.GetFileName(providerKey.Name);
// Read provider type
object providerTypeValue = providerKey.GetValue(@"Type");
if (providerTypeValue is not int providerType)
{
continue;
}
// Combine with AE connection strings
foreach (string aeConnectionString in DataTestUtility.AEConnStrings)
{
yield return new object[] { aeConnectionString, providerName, providerType };
}
}
}
}
/// <summary>
/// Validates that the results are the ones expected.
/// </summary>
/// <param name="sqlDataReader"></param>
private void ValidateResultSet(SqlDataReader sqlDataReader)
{
int rowsFound = 0;
while (sqlDataReader.Read())
{
if (sqlDataReader.FieldCount == 3)
{
Assert.Equal(45, sqlDataReader.GetInt32(0));
Assert.Equal(@"Microsoft", sqlDataReader.GetString(1));
Assert.Equal(@"Corporation", sqlDataReader.GetString(2));
}
rowsFound++;
}
Assert.Equal(1, rowsFound);
}
}
}