-
Notifications
You must be signed in to change notification settings - Fork 329
Expand file tree
/
Copy pathCoreCryptoTests.cs
More file actions
148 lines (124 loc) · 7.52 KB
/
CoreCryptoTests.cs
File metadata and controls
148 lines (124 loc) · 7.52 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
147
148
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup;
using Xunit;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
{
public class CoreCryptoTests
{
[Fact]
public void TestAeadCryptoWithNativeBaseline()
{
// Initialize the reader for resource text file which has the native code generated baseline.
CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader();
// Read and initialized the crypto vectors from the resource text file.
cryptoNativeBaselineReader.InitializeCryptoVectors();
IList<CryptoVector> cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors;
Assert.True(cryptoParametersListForTest.Count >= 1, @"Invalid number of AEAD test vectors. Expected at least 1.");
// For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code.
foreach (CryptoVector cryptoParameter in cryptoParametersListForTest)
{
// For Deterministic encryption, compare the result of encrypting the cell data (or plain text).
if (cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic)
{
TestEncryptionResultUsingAead(cryptoParameter.PlainText,
cryptoParameter.RootKey,
cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized,
cryptoParameter.FinalCell);
}
// For Randomized and Deterministic encryption, try the decryption of final cell value and compare against the native code baseline's plain text.
TestDecryptionResultUsingAead(cryptoParameter.FinalCell,
cryptoParameter.RootKey,
cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized,
cryptoParameter.PlainText);
}
}
[Fact]
public void TestRsaCryptoWithNativeBaseline()
{
SqlColumnEncryptionCertificateStoreProvider rsaProvider = new();
// Initialize the reader for resource text file which has the native code generated baseline.
CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader();
// Read and initialized the crypto vectors from the resource text file.
cryptoNativeBaselineReader.InitializeCryptoVectors(CryptNativeTestVectorType.Rsa);
IList<CryptoVector> cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors;
Assert.True(cryptoParametersListForTest.Count >= 3, @"Invalid number of RSA test vectors. Expected at least 3 (RSA Keypair + PFX + test vectors).");
Assert.True(cryptoParametersListForTest[0].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaKeyPair, @"First entry must be an RSA key pair.");
Assert.True(cryptoParametersListForTest[1].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaPfx, @"2nd entry must be a PFX.");
byte[] rsaKeyPair = cryptoParametersListForTest[0].RsaKeyPair;
byte[] rsaPfx = cryptoParametersListForTest[1].RsaKeyPair;
// Convert the PFX into a certificate and install it into the local user's certificate store.
// We can only do this cross-platform on the CurrentUser store, which matches the baseline data we have.
Assert.NotNull(rsaPfx);
Assert.NotEmpty(rsaPfx);
X509Store store = null;
bool addedToStore = false;
#if NET9_0_OR_GREATER
using X509Certificate2 x509 = X509CertificateLoader.LoadPkcs12(rsaPfx, @"P@zzw0rD!SqlvN3x+");
#else
using X509Certificate2 x509 = new(rsaPfx, @"P@zzw0rD!SqlvN3x+");
#endif
Assert.True(x509.HasPrivateKey);
try
{
store = new(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(x509);
addedToStore = true;
// For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code.
foreach (CryptoVector cryptoParameter in cryptoParametersListForTest)
{
if (cryptoParameter.CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.Rsa)
{
Assert.NotNull(cryptoParameter.PathCek);
Assert.StartsWith("CurrentUser/My", cryptoParameter.PathCek);
// Decrypt the supplied final cell CEK, and ensure that the plaintext CEK value matches the native code baseline.
byte[] plaintext = rsaProvider.DecryptColumnEncryptionKey(cryptoParameter.PathCek, "RSA_OAEP", cryptoParameter.FinalcellCek);
Assert.Equal(cryptoParameter.PlaintextCek, plaintext);
}
}
}
finally
{
if (addedToStore)
{
store.Remove(x509);
}
store?.Dispose();
}
}
/// <summary>
/// Helper function to test the result of encryption using Aead.
/// </summary>
/// <param name="plainText"></param>
/// <param name="rootKey"></param>
/// <param name="encryptionType"></param>
/// <param name="expectedFinalCellValue"></param>
private void TestEncryptionResultUsingAead(byte[] plainText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedFinalCellValue)
{
// Encrypt.
byte[] encryptedCellData = CertificateUtility.EncryptDataUsingAED(plainText, rootKey, encryptionType);
Debug.Assert(encryptedCellData != null && encryptedCellData.Length > 0);
Assert.True(encryptedCellData.SequenceEqual(expectedFinalCellValue), "Final Cell Value does not match with the native code baseline.");
}
/// <summary>
/// Helper function to test the result of decryption using Aead.
/// </summary>
/// <param name="cipherText"></param>
/// <param name="rootKey"></param>
/// <param name="encryptionType"></param>
/// <param name="expectedPlainText"></param>
private void TestDecryptionResultUsingAead(byte[] cipherText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedPlainText)
{
// Decrypt.
byte[] decryptedCellData = CertificateUtility.DecryptDataUsingAED(cipherText, rootKey, encryptionType);
Debug.Assert(decryptedCellData != null);
Assert.True(decryptedCellData.SequenceEqual(expectedPlainText), "Decrypted cell data does not match with the native code baseline.");
}
}
}