From ce431e79fd9800940079dba9909df5d02bad2a38 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:37:07 +0000 Subject: [PATCH 1/9] Remove default .pfx file from TDS.Servers Clients requiring a server certificate will need to generate their own. --- .../ManualTests/TracingTests/TestTdsServer.cs | 6 +----- .../tests/tools/TDS/TDS.EndPoint/TDSParser.cs | 6 ++++++ .../tools/TDS/TDS.Servers/TDS.Servers.csproj | 3 --- .../tools/TDS/TDS.Servers/TDSServerArguments.cs | 2 +- .../TDS/TDS.Servers/TdsServerCertificate.pfx | Bin 1854 -> 0 bytes 5 files changed, 8 insertions(+), 9 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TdsServerCertificate.pfx diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/TestTdsServer.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/TestTdsServer.cs index a4557d72b6..2e6e3d0dc6 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/TestTdsServer.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/TestTdsServer.cs @@ -43,11 +43,7 @@ public static TestTdsServer StartServerWithQueryEngine(QueryEngine engine, bool args.FedAuthRequiredPreLoginOption = SqlServer.TDS.PreLogin.TdsPreLoginFedAuthRequiredOption.FedAuthRequired; } - if (encryptionCertificate != null) - { - args.EncryptionCertificate = encryptionCertificate; - } - + args.EncryptionCertificate = encryptionCertificate; args.Encryption = encryptionType; TestTdsServer server = engine == null ? new TestTdsServer(args) : new TestTdsServer(engine, args); diff --git a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDSParser.cs b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDSParser.cs index 2027c7bd7f..eceed95d60 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDSParser.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.EndPoint/TDSParser.cs @@ -113,6 +113,12 @@ protected void EnableServerTransportEncryption(X509Certificate certificate) return; } + // The SSL certificate is required for the server to handle transport encryption + if (certificate == null) + { + throw new AuthenticationException("Server is unable to authenticate transport encryption without a valid SSL certificate."); + } + Log("Enabling server transport encryption..."); // Wrap TDS stream with auto TDS stream diff --git a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDS.Servers.csproj b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDS.Servers.csproj index cb89f362ea..b7757b257b 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDS.Servers.csproj +++ b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDS.Servers.csproj @@ -26,9 +26,6 @@ - - Always - diff --git a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs index 1543ebde63..1ff553bed0 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs @@ -87,7 +87,7 @@ public TDSServerArguments() // By Default SQL authentication will be used. FedAuthRequiredPreLoginOption = TdsPreLoginFedAuthRequiredOption.FedAuthNotRequired; - EncryptionCertificate = new X509Certificate2("TdsServerCertificate.pfx", "SecretPassword123456"); + EncryptionCertificate = null; ServerPrincipalName = AzureADServicePrincipalName; StsUrl = AzureADProductionTokenEndpoint; diff --git a/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TdsServerCertificate.pfx b/src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TdsServerCertificate.pfx deleted file mode 100644 index a5c48e2aee1f100c63aa698345667d6a3672e97f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1854 zcmY*YcUY767XC8)!iLBQBTBHhV6@_w7-qGg0-`cyU&=*B2xt&w6_gpm62!>xf-(z; zY*PiK%8-N&Wr=_wOGrRKj37~p(9b^iwojkmbIx<#_q^wve||5-!000pD2M@Wf})4w zP2+`<2n?ct0rJrd@C{5)Lkv{QKUyd@nt`f<=`uJpt)>z* zMaig81n7Tf_bum!PEhvL6}8~D&(~w}ek>eF4{RQcM=-5N=SnbjlLrvV1xeMj4Z&{dUf9PRL& zQ#oZ*^h0s7cvoG^8rQ)O{BA9aIv2LTwyAK7PRH|=+I$a03kfG^_6}k)quaI~qgBl< zs}hWYWCv2!y|Q7SV&ukxEl2WD>yQ#wq@a~pTY%LbJ$PFz`IUO7YWDF=PbEfgr0>w3 z3Kl!@!&guJ$dG?e2ZX_pFWnt+PjO%)*RHY#q=%p!x z5#1WD*pkXyGoCI}d^)Sc@d4Sqop`gQ?yiqiV}8JIs+LaGin0!hQsMN^R#=unx7u#? zcuj@0%G+3Hd9LpUFKn~1IlX{gW*P0Ke$Da2!8wH`U3U*^P+w7^h;?RB^O|JT>H|{D z1SI>{Hy4#BfoL=W0077Z6g>supk7u4A=s`@Q^+% z@c?uHJ-{6}22cPJa0JkTYZ4qsV5|+V_JAv0n4!Yx2mrx-2q43c3irscMhnhvuu*Y; z9m0SG43r2=p^*pxcI%hFJBWW67yN2mHA2136IpnGkYfc27A?H!4Ry zgE;js8Js=v(@g2P@`u|w>HS{yitda9%+-s*cQ=`D`hwZIW}y3=Yre>AAoEt1oD-xIFccSe|ow*y6wqEFUqna}#WG#T?|^ScVH z0#tZ}lpTG;mwi_<2ghZXf^|oA#qCY;q#nolqSv^zG|tu9PLy%(OwB-oxvja|qidy4 z<0NP&z3>w^9He}#Fo((kcwSNZl^XgQ@jA|?QLml(M-B- zgJxd;r`Z;-`(bV_!Dsl4a;5?`D@D!sSct+<>MUQqA;o9mT+#S-cU|Ru_Rfy@#D$mx zK1-8Nu^ls>mWrtd@p5T*x)R?;-gJ!Xd)d#`P_q%TZ}<3tO*OPjijp?7oCb*)3;h?e zd3z`Prbi?EotNxMC&lc3FqfXu*zCNtY~X!-x9jyYg_vPSg!5casVTAb6jHvzF=jhI zFi@0eUB2nAsQRf88rZY{mFgH< zS4t;hEcjMg?ZkbO==2K8F%wQ`IbfbUbK#<2HAU9wX~lmuG43P#$|<2t3)Gaph3EE<$>?RP_hgkFi|I#?*6QO?0=?zXh|3?%c=Y12H9OkbFI9%p~;IC&8TakZJmP6$ttsQiU+!p2Jcoq%vC0KPfX@FkZ>t o!*E%YHj&r!WPX!~mNWW@t668IJ&=o1TUT#dU>6Bv^S&D54}-)jG5`Po From b130460e254f1cb968ef3797882a6819c85d438e Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:18:25 +0000 Subject: [PATCH 2/9] Infrastructure work - base class, project targets * TestUtilities no longer targets netstandard2.0, so is now able to use CertificateRequest. * Added a reference from Tests to TestUtilities. * Added a base CertificateFixtureBase class. This provides basic infrastructure to generate a certificate and add it to a store (with cleanup on disposal.) --- .../Microsoft.Data.SqlClient.Tests.csproj | 1 + .../Fixtures/CertificateFixtureBase.cs | 229 ++++++++++++++++++ ...rosoft.Data.SqlClient.TestUtilities.csproj | 8 +- 3 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 1186c3ebdd..38f719b1a5 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -116,6 +116,7 @@ TDS + diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs new file mode 100644 index 0000000000..b05ea370e3 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs @@ -0,0 +1,229 @@ +// 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace Microsoft.Data.SqlClient.TestUtilities.Fixtures +{ + public abstract class CertificateFixtureBase : IDisposable + { + private sealed class CertificateStoreContext + { + public List Certificates { get; } + + public StoreLocation Location { get; } + + public StoreName Name { get; } + + public CertificateStoreContext(StoreLocation location, StoreName name) + { + Certificates = new List(); + Location = location; + Name = name; + } + } + + private readonly List _certificateStoreModifications = new List(); + + protected static X509Certificate CreateCertificate(string subjectName, IEnumerable dnsNames, IEnumerable ipAddresses) + { + // This will always generate a certificate with: + // * Start date: 24hrs ago + // * End date: 24hrs in the future + // * Subject: {subjectName} + // * Subject alternative names: {dnsNames}, {ipAddresses} + // * Public key: 4096-bit RSA + // * Hash algorithm: SHA256 + // * Key usage: digital signature, key encipherment + // * Enhanced key usage: server authentication, client authentication + DateTimeOffset notBefore = DateTimeOffset.UtcNow.AddDays(-1); + DateTimeOffset notAfter = DateTimeOffset.UtcNow.AddDays(1); +#if NET + X500DistinguishedNameBuilder subjectBuilder = new X500DistinguishedNameBuilder(); + SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); + RSA rsaKey = RSA.Create(4096); + bool hasSans = false; + + subjectBuilder.AddCommonName(subjectName); + foreach (string dnsName in dnsNames) + { + sanBuilder.AddDnsName(dnsName); + hasSans = true; + } + foreach (string ipAddress in ipAddresses) + { + sanBuilder.AddIpAddress(System.Net.IPAddress.Parse(ipAddress)); + hasSans = true; + } + + CertificateRequest request = new CertificateRequest(subjectBuilder.Build(), rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + + request.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(request.PublicKey, false)); + request.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, false)); + request.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection() { new Oid("1.3.6.1.5.5.7.3.1"), new Oid("1.3.6.1.5.5.7.3.2") }, true)); + + if (hasSans) + { + request.CertificateExtensions.Add(sanBuilder.Build()); + } + + return request.CreateSelfSigned(notBefore, notAfter); +#else + // The CertificateRequest API is available in .NET Core, but was only added to .NET Framework 4.7.2; it thus can't be used in the test projects. + // Instead, fall back to running a PowerShell script which calls New-SelfSignedCertificate. This cmdlet also adds the certificate to a specific, + // certificate store, so remove it from there. + // Normally, the PowerShell script will return zero and print the base64-encoded certificate to stdout. If there's an exception, it'll return 1 and + // print the message instead. + const string PowerShellCommandTemplate = @"$notBefore = [DateTime]::ParseExact(""{0}"", ""O"", $null) +$notAfter = [DateTime]::ParseExact(""{1}"", ""O"", $null) +$subject = ""CN={2}"" +$sAN = @({3}) + +try +{{ + $x509 = New-SelfSignedCertificate -Subject $subject -TextExtension $sAN -KeyLength 4096 -KeyAlgorithm RSA ` + -CertStoreLocation ""Cert:\CurrentUser\My"" -NotBefore $notBefore -NotAfter $notAfter ` + -KeyExportPolicy Exportable -HashAlgorithm SHA256 + + if ($x509 -eq $null) + {{ throw ""Certificate was null!"" }} + + $exportedArray = $x509.Export(""Pkcs12"", ""{4}"") + Write-Output $([Convert]::ToBase64String($exportedArray)) + + Remove-Item ""Cert:\CurrentUser\My\$($x509.Thumbprint)"" + + exit 0 +}} +catch [Exception] +{{ + Write-Output $_.Exception.Message + exit 1 +}}"; + const int PowerShellCommandTimeout = 15_000; + + string sanString = string.Empty; + bool hasSans = false; + string formattedCommand = null; + byte[] passwordBytes = new byte[32]; + string password = null; + Random rnd = new Random(); + string commandOutput = null; + + foreach (string dnsName in dnsNames) + { + sanString += string.Format("DNS={0}&", dnsName); + hasSans = true; + } + foreach (string ipAddress in ipAddresses) + { + sanString += string.Format("IPAddress={0}&", ipAddress); + hasSans = true; + } + + sanString = hasSans ? "\"2.5.29.17={text}" + sanString.Substring(0, sanString.Length - 1) + "\"" : string.Empty; + + rnd.NextBytes(passwordBytes); + password = Convert.ToBase64String(passwordBytes); + formattedCommand = string.Format(PowerShellCommandTemplate, notBefore.ToString("O"), notAfter.ToString("O"), subjectName, sanString, password); + + using (Process psProcess = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = "powershell.exe", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true, + // Pass the Base64-encoded command to remove the need to escape quote marks + Arguments = "-EncodedCommand " + Convert.ToBase64String(Encoding.Unicode.GetBytes(formattedCommand)) + } + }) + { + psProcess.Start(); + commandOutput = psProcess.StandardOutput.ReadToEnd(); + + if (!psProcess.WaitForExit(PowerShellCommandTimeout)) + { + psProcess.Kill(); + throw new Exception("Process did not complete in time, exiting."); + } + + // Process completed successfully if it had an exit code of zero, the command output will be the base64-encoded certificate + if (psProcess.ExitCode == 0) + { + return new X509Certificate2(Convert.FromBase64String(commandOutput), password); + } + else + { + throw new Exception($"PowerShell command raised exception: {commandOutput}"); + } + } +#endif + } + + protected void AddToStore(X509Certificate2 cert, StoreLocation storeLocation, StoreName storeName) + { + CertificateStoreContext storeContext = _certificateStoreModifications.Find(csc => csc.Location == storeLocation && csc.Name == storeName); + + if (storeContext == null) + { + storeContext = new(storeLocation, storeName); + _certificateStoreModifications.Add(storeContext); + } + + using X509Store store = new X509Store(storeContext.Name, storeContext.Location); + + store.Open(OpenFlags.ReadWrite); + if (store.Certificates.Contains(cert)) + { + store.Remove(cert); + } + store.Add(cert); + + storeContext.Certificates.Add(cert); + } + + public virtual void Dispose() + { + foreach (CertificateStoreContext storeContext in _certificateStoreModifications) + { + using X509Store store = new X509Store(storeContext.Name, storeContext.Location); + + try + { + store.Open(OpenFlags.ReadWrite); + } + catch(Exception) + { + continue; + } + + foreach (X509Certificate2 cert in storeContext.Certificates) + { + try + { + if (store.Certificates.Contains(cert)) + { + store.Remove(cert); + } + } + catch (Exception) + { + continue; + } + + cert.Dispose(); + } + + storeContext.Certificates.Clear(); + } + } + } +} diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj index 3bd48830cc..2895ef3a6a 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj @@ -1,6 +1,10 @@ - + - netstandard2.0 + netfx + netcoreapp + win + win-$(Platform) + $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName) $(BinFolder)$(Configuration).$(Platform)\$(AssemblyName) From 455903142c7d4ea3c2ecc63da75db88aa13e93b0 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:19:06 +0000 Subject: [PATCH 3/9] Reworked SqlColumnEncryptionCertificateStoreProviderShould Removed multiple hardcoded references to three certificates. Also removed references to TestCertificate12. --- ...ncryptionCertificateStoreProviderShould.cs | 195 ++++++------------ .../AlwaysEncryptedTests/Utility.cs | 49 ----- .../Fixtures/CertificateFixtureBase.cs | 27 ++- .../ColumnEncryptionCertificateFixture.cs | 51 +++++ 4 files changed, 135 insertions(+), 187 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs index ecbd4c5da9..b7ff289a19 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.Data.SqlClient.TestUtilities.Fixtures; using System; using System.Collections.Generic; using System.Linq; @@ -16,9 +17,11 @@ namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests { - public class SqlColumnEncryptionCertificateStoreProviderWindowsShould : IClassFixture + [Collection(nameof(SqlColumnEncryptionCertificateStoreProviderCollection))] + public class SqlColumnEncryptionCertificateStoreProviderWindowsShould { - private const string MASTER_KEY_PATH = "CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946"; + private const string PRIMARY_CERTIFICATE_PATH = "CurrentUser/My/{primary_thumbprint}"; + private const string SECONDARY_CERTIFICATE_PATH = "CurrentUser/My/{secondary_thumbprint}"; private const string ENCRYPTION_ALGORITHM = "RSA_OAEP"; /// @@ -93,14 +96,22 @@ public class SqlColumnEncryptionCertificateStoreProviderWindowsShould : IClassFi /// private const int CipherTextStartIndex = IVStartIndex + IVLengthInBytes; + private readonly ColumnEncryptionCertificateFixture _certFixture; + + public SqlColumnEncryptionCertificateStoreProviderWindowsShould(ColumnEncryptionCertificateFixture certFixture) + { + _certFixture = certFixture; + } + [Theory] [InvalidDecryptionParameters] [PlatformSpecific(TestPlatforms.Windows)] public void ThrowExceptionWithInvalidParameterWhileDecryptingColumnEncryptionKey(string errorMsg, Type exceptionType, string masterKeyPath, string encryptionAlgorithm, byte[] bytes) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - Exception ex = Assert.Throws(exceptionType, () => provider.DecryptColumnEncryptionKey(masterKeyPath, encryptionAlgorithm, bytes)); - Assert.Matches(errorMsg, ex.Message); + Exception ex = Assert.Throws(exceptionType, + () => provider.DecryptColumnEncryptionKey(ReplaceKeyTokens(masterKeyPath), encryptionAlgorithm, bytes)); + Assert.Matches(ReplaceKeyTokens(errorMsg), ex.Message); } [Theory] @@ -109,7 +120,7 @@ public void ThrowExceptionWithInvalidParameterWhileDecryptingColumnEncryptionKey public void ThrowExceptionWithInvalidParameterWhileEncryptingColumnEncryptionKey(string errorMsg, Type exceptionType, string masterKeyPath, string encryptionAlgorithm, byte[] bytes) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - Exception ex = Assert.Throws(exceptionType, () => provider.EncryptColumnEncryptionKey(masterKeyPath, encryptionAlgorithm, bytes)); + Exception ex = Assert.Throws(exceptionType, () => provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(masterKeyPath), encryptionAlgorithm, bytes)); Assert.Matches(errorMsg, ex.Message); } @@ -124,26 +135,26 @@ public void ThrowExceptionWithInvalidParameterWhileSigningColumnMasterKeyMetadat } [Theory] - [InlineData("CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] - [InlineData("CURRENTUSER/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] - [InlineData("currentuser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] + [InlineData("CurrentUser/My/{primary_thumbprint}")] + [InlineData("CURRENTUSER/My/{primary_thumbprint}")] + [InlineData("currentuser/My/{primary_thumbprint}")] [PlatformSpecific(TestPlatforms.Windows)] - public void SetStoreLocationApproperiatelyFromMasterKeyPathRegardlessOfCase(string masterKeyPath) + public void SetStoreLocationAppropriatelyFromMasterKeyPathRegardlessOfCase(string masterKeyPath) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] ciphertext = provider.EncryptColumnEncryptionKey(masterKeyPath, ENCRYPTION_ALGORITHM, new byte[] { 1, 2, 3, 4, 5 }); + byte[] ciphertext = provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(masterKeyPath), ENCRYPTION_ALGORITHM, new byte[] { 1, 2, 3, 4, 5 }); Assert.NotNull(ciphertext); } [Theory] - [InlineData("CurrentUser/my/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] - [InlineData("CurrentUser/MY/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] - [InlineData("CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946")] + [InlineData("CurrentUser/my/{primary_thumbprint}")] + [InlineData("CurrentUser/MY/{primary_thumbprint}")] + [InlineData("CurrentUser/My/{primary_thumbprint}")] [PlatformSpecific(TestPlatforms.Windows)] - public void SetStoreNameApproperiatelyFromMasterKeyPathRegardlessOfCase(string masterKeyPath) + public void SetStoreNameAppropriatelyFromMasterKeyPathRegardlessOfCase(string masterKeyPath) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] ciphertext = provider.EncryptColumnEncryptionKey(masterKeyPath, ENCRYPTION_ALGORITHM, new byte[] { 1, 2, 3, 4, 5 }); + byte[] ciphertext = provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(masterKeyPath), ENCRYPTION_ALGORITHM, new byte[] { 1, 2, 3, 4, 5 }); Assert.NotNull(ciphertext); } @@ -155,7 +166,7 @@ public void SetStoreNameApproperiatelyFromMasterKeyPathRegardlessOfCase(string m public void AcceptEncryptionAlgorithmRegardlessOfCase(string algorithm) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] ciphertext = provider.EncryptColumnEncryptionKey(MASTER_KEY_PATH, algorithm, new byte[] { 1, 2, 3, 4, 5 }); + byte[] ciphertext = provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), algorithm, new byte[] { 1, 2, 3, 4, 5 }); Assert.NotNull(ciphertext); } @@ -171,8 +182,8 @@ public void EncryptKeyAndThenDecryptItSuccessfully(int dataSize) var randomNumberGenerator = new Random(); randomNumberGenerator.NextBytes(columnEncryptionKey); - byte[] encryptedData = provider.EncryptColumnEncryptionKey(MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, columnEncryptionKey); - byte[] decryptedData = provider.DecryptColumnEncryptionKey(MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, encryptedData); + byte[] encryptedData = provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), ENCRYPTION_ALGORITHM, columnEncryptionKey); + byte[] decryptedData = provider.DecryptColumnEncryptionKey(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), ENCRYPTION_ALGORITHM, encryptedData); Assert.Equal(columnEncryptionKey, decryptedData); } @@ -183,10 +194,10 @@ public void EncryptKeyAndThenDecryptItSuccessfully(int dataSize) public void SignAndVerifyColumnMasterKeyMetadataSuccessfully(bool allowEnclaveComputations) { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] signature = provider.SignColumnMasterKeyMetadata(MASTER_KEY_PATH, allowEnclaveComputations); + byte[] signature = provider.SignColumnMasterKeyMetadata(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), allowEnclaveComputations); Assert.NotNull(signature); - Assert.True(provider.VerifyColumnMasterKeyMetadata(MASTER_KEY_PATH, allowEnclaveComputations, signature)); - Assert.False(provider.VerifyColumnMasterKeyMetadata(MASTER_KEY_PATH, !allowEnclaveComputations, signature)); + Assert.True(provider.VerifyColumnMasterKeyMetadata(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), allowEnclaveComputations, signature)); + Assert.False(provider.VerifyColumnMasterKeyMetadata(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), !allowEnclaveComputations, signature)); } [Theory] @@ -197,10 +208,10 @@ public void FailToVerifyColumnMasterKeyMetadataWithWrongCertificate(bool allowEn { var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] signature = provider.SignColumnMasterKeyMetadata(MASTER_KEY_PATH, allowEnclaveComputations); + byte[] signature = provider.SignColumnMasterKeyMetadata(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), allowEnclaveComputations); Assert.NotNull(signature); Assert.False( - provider.VerifyColumnMasterKeyMetadata("CurrentUser/My/4281446463C6F7F5B8EDFFA4BD6E345E46857CAD", allowEnclaveComputations, signature)); + provider.VerifyColumnMasterKeyMetadata(ReplaceKeyTokens(SECONDARY_CERTIFICATE_PATH), allowEnclaveComputations, signature)); } [Fact] @@ -209,10 +220,10 @@ public void EncryptAndDecryptDataSuccessfully() { var input = new byte[] { 1, 2, 3, 4, 5 }; var provider = new SqlColumnEncryptionCertificateStoreProvider(); - byte[] ciphertext = provider.EncryptColumnEncryptionKey(MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, + byte[] ciphertext = provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), ENCRYPTION_ALGORITHM, new byte[] { 1, 2, 3, 4, 5 }); byte[] output = - provider.DecryptColumnEncryptionKey(MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, ciphertext); + provider.DecryptColumnEncryptionKey(ReplaceKeyTokens(PRIMARY_CERTIFICATE_PATH), ENCRYPTION_ALGORITHM, ciphertext); Assert.Equal(input, output); } @@ -222,11 +233,9 @@ public void EncryptAndDecryptDataSuccessfully() public void TestCEKEncryptionReversal(StoreLocation certificateStoreLocation, String certificateStoreNameAndLocation) { Assert.True(!string.IsNullOrWhiteSpace(certificateStoreNameAndLocation)); - string certificateName = @"TestCertificate12"; // Fetch the newly created cert. - X509Certificate2 masterKeyCertificate = Utility.GetCertificate(certificateName, - certificateStoreLocation); + X509Certificate2 masterKeyCertificate = _certFixture.GetCertificate(certificateStoreLocation); Assert.True(masterKeyCertificate != null); @@ -389,11 +398,8 @@ public void TestValidCertificatePaths(string certificateStoreNameAndLocation, ob certificateStoreLocation = StoreLocation.CurrentUser; } - string certificateName = @"TestCertificate12"; - // Fetch the newly created cert. - X509Certificate2 masterKeyCertificate = Utility.GetCertificate(certificateName, - certificateStoreLocation); + X509Certificate2 masterKeyCertificate = _certFixture.GetCertificate(certificateStoreLocation); Assert.True(masterKeyCertificate != null); @@ -459,6 +465,12 @@ public void TestEncryptedCellValueTampering(string parameterToTamper, Utility.CC Assert.Matches(expectedErrorMessage, e.InnerException.Message); } + private string ReplaceKeyTokens(string keyPath) + { + return keyPath?.Replace("{primary_thumbprint}", _certFixture.PrimaryColumnEncryptionCertificate.Thumbprint) + ?.Replace("{secondary_thumbprint}", _certFixture.SecondaryColumnEncryptionCertificate.Thumbprint); + } + public class AeadEncryptionParameters : DataAttribute { /// @@ -496,7 +508,7 @@ public override IEnumerable GetData(MethodInfo testMethod) { yield return new object[2] { StoreLocation.CurrentUser, CurrentUserMyPathPrefix }; // use localmachine cert path only when current user is Admin. - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && CertificateFixture.IsAdmin) + if (ColumnEncryptionCertificateFixture.IsAdmin) { yield return new object[2] { StoreLocation.LocalMachine, LocalMachineMyPathPrefix }; } @@ -510,11 +522,11 @@ public class ValidCertificatePathsParameters : DataAttribute public override IEnumerable GetData(MethodInfo testMethod) { yield return new object[2] { CurrentUserMyPathPrefix, StoreLocation.CurrentUser }; - yield return new object[2] { MyPathPrefix, null }; - yield return new object[2] { @"", null }; - // use localmachine cert path only when current user is Admin. - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && CertificateFixture.IsAdmin) + // use localmachine cert path (or an incomplete path, which defaults to localmachine) only when current user is Admin. + if (ColumnEncryptionCertificateFixture.IsAdmin) { + yield return new object[2] { MyPathPrefix, StoreLocation.LocalMachine }; + yield return new object[2] { @"", StoreLocation.LocalMachine }; yield return new object[2] { LocalMachineMyPathPrefix, StoreLocation.LocalMachine }; } } @@ -534,28 +546,28 @@ public class InvalidDecryptionParameters : DataAttribute private const string TCE_InvalidCertificateStore = @"Internal error. Invalid certificate store 'Invalid' specified in certificate path 'CurrentUser/Invalid/Thumbprint'. Expected value: 'My'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateSignature = @"Internal error. Empty certificate thumbprint specified in certificate path 'CurrentUser/My/'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidAlgorithmVersion = @"Specified encrypted column encryption key contains an invalid encryption algorithm version '02'. Expected version is '01'.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - private const string TCE_InvalidCiphertextLengthInEncryptedCEK = @"The specified encrypted column encryption key's ciphertext length: 128 does not match the ciphertext length: 256 when using column master key \(certificate\) in 'CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - private const string TCE_InvalidSignatureInEncryptedCEK = @"The specified encrypted column encryption key's signature length: 128 does not match the signature length: 256 when using column master key \(certificate\) in 'CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - private const string TCE_InvalidSignature = @"The specified encrypted column encryption key signature does not match the signature computed with the column master key \(certificate\) in 'CurrentUser/My/C74D53B816A971E3FF9714FE1DD2E57E1710D946'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + private const string TCE_InvalidCiphertextLengthInEncryptedCEK = @"The specified encrypted column encryption key's ciphertext length: 128 does not match the ciphertext length: 256 when using column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + private const string TCE_InvalidSignatureInEncryptedCEK = @"The specified encrypted column encryption key's signature length: 128 does not match the signature length: 256 when using column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + private const string TCE_InvalidSignature = @"The specified encrypted column encryption key signature does not match the signature computed with the column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; public override IEnumerable GetData(MethodInfo testMethod) { yield return new Object[] { TCE_NullCertificatePath, typeof(ArgumentNullException), null, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_EmptyCertificatePath, typeof(ArgumentException), "", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; - yield return new Object[] { TCE_NullEncryptedColumnEncryptionKey, typeof(ArgumentNullException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, null }; - yield return new Object[] { TCE_EmptyEncryptedColumnEncryptionKey, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, new byte[] { } }; - yield return new Object[] { TCE_NullKeyEncryptionAlgorithm, typeof(ArgumentNullException), MASTER_KEY_PATH, null, GenerateTestEncryptedBytes(1, 0, 256, 256) }; - yield return new Object[] { TCE_InvalidKeyEncryptionAlgorithm, typeof(ArgumentException), MASTER_KEY_PATH, "", GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_NullEncryptedColumnEncryptionKey, typeof(ArgumentNullException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, null }; + yield return new Object[] { TCE_EmptyEncryptedColumnEncryptionKey, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, new byte[] { } }; + yield return new Object[] { TCE_NullKeyEncryptionAlgorithm, typeof(ArgumentNullException), PRIMARY_CERTIFICATE_PATH, null, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_InvalidKeyEncryptionAlgorithm, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, "", GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_LargeCertificatePathLength, typeof(ArgumentException), GenerateString(Int16.MaxValue + 1), ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificatePath, typeof(ArgumentException), "CurrentUser/My/Thumbprint/extra", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateLocation, typeof(ArgumentException), "Invalid/My/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateStore, typeof(ArgumentException), "CurrentUser/Invalid/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateSignature, typeof(ArgumentException), "CurrentUser/My/", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; - yield return new Object[] { TCE_InvalidAlgorithmVersion, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(2, 0, 256, 256) }; - yield return new Object[] { TCE_InvalidCiphertextLengthInEncryptedCEK, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 128, 256) }; - yield return new Object[] { TCE_InvalidSignatureInEncryptedCEK, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 128) }; - yield return new Object[] { TCE_InvalidSignature, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_InvalidAlgorithmVersion, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(2, 0, 256, 256) }; + yield return new Object[] { TCE_InvalidCiphertextLengthInEncryptedCEK, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 128, 256) }; + yield return new Object[] { TCE_InvalidSignatureInEncryptedCEK, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 128) }; + yield return new Object[] { TCE_InvalidSignature, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; } } @@ -577,10 +589,10 @@ public override IEnumerable GetData(MethodInfo testMethod) { yield return new Object[] { TCE_NullCertificatePath, typeof(ArgumentNullException), null, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_EmptyCertificatePath, typeof(ArgumentException), "", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; - yield return new Object[] { TCE_NullEncryptedColumnEncryptionKey, typeof(ArgumentNullException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, null }; - yield return new Object[] { TCE_EmptyEncryptedColumnEncryptionKey, typeof(ArgumentException), MASTER_KEY_PATH, ENCRYPTION_ALGORITHM, new byte[] { } }; - yield return new Object[] { TCE_NullKeyEncryptionAlgorithm, typeof(ArgumentNullException), MASTER_KEY_PATH, null, GenerateTestEncryptedBytes(1, 0, 256, 256) }; - yield return new Object[] { TCE_InvalidKeyEncryptionAlgorithm, typeof(ArgumentException), MASTER_KEY_PATH, "", GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_NullEncryptedColumnEncryptionKey, typeof(ArgumentNullException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, null }; + yield return new Object[] { TCE_EmptyEncryptedColumnEncryptionKey, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, new byte[] { } }; + yield return new Object[] { TCE_NullKeyEncryptionAlgorithm, typeof(ArgumentNullException), PRIMARY_CERTIFICATE_PATH, null, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_InvalidKeyEncryptionAlgorithm, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, "", GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_LargeCertificatePathLength, typeof(ArgumentException), GenerateString(Int16.MaxValue + 1), ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificatePath, typeof(ArgumentException), "CurrentUser/My/Thumbprint/extra", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateLocation, typeof(ArgumentException), "Invalid/My/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; @@ -631,82 +643,9 @@ public void ThrowPlatformNotSupportedExceptionInUnix() } } - public class CertificateFixture : IDisposable + [CollectionDefinition(nameof(SqlColumnEncryptionCertificateStoreProviderCollection))] + public class SqlColumnEncryptionCertificateStoreProviderCollection + : ICollectionFixture { - public static bool IsAdmin - { - get - { -#if NET - System.Diagnostics.Debug.Assert(OperatingSystem.IsWindows()); -#endif - return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); - } - } - public string certificateThumbPrint1 = "C74D53B816A971E3FF9714FE1DD2E57E1710D946"; - public static byte[] certificateRawBytes1 = new byte[] { 48, 130, 10, 36, 2, 1, 3, 48, 130, 9, 224, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 9, 209, 4, 130, 9, 205, 48, 130, 9, 201, 48, 130, 5, 250, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 235, 4, 130, 5, 231, 48, 130, 5, 227, 48, 130, 5, 223, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 4, 254, 48, 130, 4, 250, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 146, 126, 191, 6, 130, 18, 111, 71, 2, 2, 7, 208, 4, 130, 4, 216, 55, 138, 10, 135, 82, 84, 240, 82, 107, 75, 21, 156, 54, 53, 188, 62, 36, 248, 59, 17, 18, 41, 206, 171, 226, 168, 175, 59, 48, 50, 36, 26, 58, 39, 118, 231, 200, 107, 86, 144, 200, 20, 135, 22, 105, 159, 229, 116, 123, 122, 194, 69, 172, 171, 128, 251, 129, 222, 113, 27, 253, 48, 164, 116, 72, 194, 123, 12, 247, 186, 162, 40, 39, 114, 22, 118, 91, 192, 73, 122, 235, 247, 40, 89, 3, 222, 64, 214, 184, 67, 204, 188, 197, 188, 107, 126, 225, 194, 161, 110, 156, 45, 70, 26, 86, 69, 63, 120, 153, 164, 136, 15, 220, 153, 104, 50, 121, 87, 10, 180, 149, 98, 220, 73, 175, 50, 146, 231, 112, 230, 204, 132, 76, 43, 142, 7, 104, 142, 146, 92, 21, 52, 38, 59, 154, 108, 159, 192, 93, 174, 39, 134, 96, 189, 150, 77, 90, 160, 43, 127, 173, 199, 189, 4, 69, 44, 104, 148, 225, 44, 149, 167, 149, 121, 220, 232, 98, 131, 212, 130, 35, 79, 10, 173, 177, 150, 161, 91, 26, 12, 221, 136, 230, 124, 73, 96, 126, 12, 241, 99, 60, 140, 126, 140, 0, 166, 47, 16, 87, 102, 138, 45, 97, 21, 31, 224, 126, 231, 102, 99, 35, 207, 75, 22, 249, 115, 51, 106, 79, 208, 21, 108, 124, 143, 108, 130, 6, 61, 215, 227, 7, 224, 174, 193, 97, 211, 241, 224, 90, 37, 101, 147, 149, 173, 239, 113, 214, 1, 41, 69, 158, 203, 3, 63, 101, 196, 134, 7, 127, 58, 113, 243, 228, 162, 99, 75, 207, 153, 19, 193, 187, 52, 124, 85, 234, 7, 249, 75, 65, 230, 107, 247, 145, 64, 94, 106, 50, 117, 83, 138, 49, 10, 22, 211, 115, 183, 20, 119, 18, 117, 166, 153, 30, 210, 248, 118, 200, 21, 180, 118, 208, 53, 90, 243, 74, 76, 109, 106, 46, 103, 112, 197, 89, 92, 178, 83, 48, 97, 162, 73, 78, 105, 145, 213, 230, 17, 211, 121, 200, 101, 179, 158, 85, 99, 211, 68, 122, 234, 176, 4, 33, 225, 120, 139, 163, 110, 35, 199, 23, 45, 126, 199, 80, 145, 14, 74, 217, 200, 172, 216, 159, 237, 241, 157, 85, 210, 141, 180, 150, 187, 82, 48, 245, 154, 125, 60, 223, 244, 21, 20, 39, 88, 8, 153, 185, 227, 76, 78, 137, 99, 98, 81, 141, 27, 197, 41, 39, 251, 80, 27, 85, 78, 65, 15, 216, 106, 106, 113, 33, 253, 210, 46, 214, 47, 49, 89, 170, 215, 207, 62, 182, 88, 25, 186, 166, 214, 172, 63, 94, 17, 123, 235, 226, 72, 73, 204, 18, 173, 134, 92, 66, 2, 213, 151, 251, 95, 175, 38, 56, 156, 138, 96, 123, 190, 107, 59, 230, 24, 210, 224, 206, 169, 159, 95, 180, 237, 34, 194, 62, 4, 213, 228, 85, 216, 138, 157, 50, 20, 101, 160, 195, 138, 207, 18, 17, 232, 6, 73, 82, 247, 173, 50, 180, 53, 58, 156, 97, 230, 112, 211, 251, 204, 120, 188, 34, 41, 67, 83, 197, 131, 251, 176, 20, 70, 169, 116, 237, 43, 117, 45, 31, 66, 74, 152, 216, 3, 108, 102, 99, 5, 127, 76, 129, 57, 180, 90, 218, 157, 108, 85, 4, 240, 101, 149, 154, 221, 208, 70, 152, 34, 128, 57, 135, 38, 17, 139, 142, 167, 109, 73, 129, 181, 105, 45, 151, 106, 171, 166, 0, 113, 147, 141, 19, 228, 196, 88, 175, 219, 18, 213, 54, 105, 179, 8, 249, 250, 164, 86, 28, 185, 19, 60, 50, 140, 73, 237, 148, 201, 33, 204, 189, 43, 83, 163, 138, 1, 10, 13, 240, 196, 211, 221, 169, 207, 100, 167, 203, 146, 115, 70, 118, 230, 4, 224, 192, 209, 242, 144, 150, 72, 170, 149, 255, 196, 7, 91, 55, 251, 57, 127, 103, 98, 113, 83, 224, 97, 118, 132, 81, 119, 8, 105, 250, 155, 107, 149, 28, 127, 66, 127, 224, 79, 96, 9, 168, 73, 84, 228, 123, 161, 222, 179, 115, 73, 184, 62, 24, 228, 44, 156, 42, 124, 209, 29, 81, 19, 169, 24, 212, 6, 238, 239, 221, 68, 220, 106, 0, 45, 201, 129, 3, 50, 150, 244, 32, 220, 237, 20, 39, 175, 249, 80, 189, 166, 68, 251, 102, 60, 137, 93, 209, 86, 194, 55, 164, 100, 76, 220, 249, 30, 233, 101, 177, 150, 71, 28, 227, 180, 44, 115, 83, 201, 129, 44, 128, 247, 68, 175, 97, 36, 170, 76, 236, 57, 119, 240, 0, 129, 185, 35, 160, 231, 183, 56, 162, 197, 237, 186, 109, 118, 232, 84, 108, 125, 93, 92, 101, 193, 180, 210, 192, 244, 47, 55, 56, 217, 178, 200, 168, 232, 80, 223, 209, 255, 234, 146, 46, 215, 170, 197, 94, 84, 213, 233, 140, 247, 69, 185, 103, 183, 91, 23, 232, 32, 246, 244, 30, 41, 156, 28, 72, 109, 90, 127, 135, 132, 19, 136, 233, 168, 29, 98, 17, 111, 5, 185, 234, 86, 234, 114, 47, 227, 81, 77, 108, 179, 184, 91, 31, 74, 23, 29, 248, 41, 207, 8, 23, 181, 33, 99, 217, 48, 145, 97, 126, 139, 133, 11, 100, 69, 151, 146, 38, 79, 231, 155, 92, 134, 139, 189, 237, 132, 196, 95, 45, 141, 15, 26, 37, 58, 219, 10, 0, 36, 221, 240, 82, 117, 163, 121, 141, 206, 21, 180, 195, 58, 109, 56, 123, 152, 206, 116, 161, 221, 125, 248, 23, 31, 240, 227, 186, 52, 171, 147, 51, 39, 203, 92, 205, 182, 146, 149, 111, 27, 59, 219, 234, 216, 52, 89, 22, 224, 76, 62, 94, 76, 131, 48, 162, 134, 161, 177, 44, 205, 101, 253, 13, 237, 40, 29, 72, 224, 121, 74, 189, 57, 81, 58, 169, 178, 173, 157, 182, 143, 205, 64, 225, 137, 188, 235, 43, 195, 3, 187, 105, 113, 72, 82, 153, 58, 97, 38, 251, 212, 149, 191, 11, 153, 157, 106, 16, 236, 237, 209, 210, 208, 19, 68, 92, 176, 65, 24, 115, 181, 94, 24, 126, 2, 216, 63, 200, 136, 178, 92, 248, 11, 128, 68, 122, 14, 46, 234, 48, 142, 219, 92, 29, 136, 70, 200, 52, 78, 70, 160, 215, 113, 102, 190, 66, 16, 69, 120, 25, 201, 23, 209, 41, 79, 25, 151, 38, 38, 82, 244, 143, 121, 216, 111, 91, 167, 232, 32, 234, 243, 195, 168, 240, 135, 188, 1, 92, 145, 77, 240, 107, 20, 82, 147, 168, 132, 78, 115, 206, 95, 47, 8, 80, 91, 255, 28, 38, 161, 52, 168, 211, 236, 143, 238, 146, 172, 104, 2, 254, 240, 229, 210, 225, 47, 41, 76, 134, 5, 20, 203, 188, 48, 195, 120, 103, 234, 94, 217, 142, 238, 254, 131, 146, 214, 106, 212, 229, 201, 79, 151, 198, 100, 132, 99, 228, 82, 182, 94, 216, 226, 163, 42, 113, 110, 201, 70, 221, 127, 242, 7, 176, 60, 121, 158, 37, 56, 6, 156, 191, 75, 94, 222, 10, 155, 39, 64, 172, 216, 106, 210, 202, 246, 66, 83, 107, 250, 17, 134, 222, 212, 71, 200, 215, 103, 35, 82, 225, 106, 17, 106, 74, 18, 130, 236, 175, 45, 145, 155, 169, 88, 72, 244, 3, 38, 245, 208, 49, 129, 205, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 74, 30, 72, 0, 100, 0, 99, 0, 99, 0, 52, 0, 51, 0, 48, 0, 56, 0, 56, 0, 45, 0, 50, 0, 57, 0, 54, 0, 53, 0, 45, 0, 52, 0, 57, 0, 97, 0, 48, 0, 45, 0, 56, 0, 51, 0, 54, 0, 53, 0, 45, 0, 50, 0, 52, 0, 101, 0, 52, 0, 97, 0, 52, 0, 49, 0, 100, 0, 55, 0, 50, 0, 52, 0, 48, 48, 93, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 80, 30, 78, 0, 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 83, 0, 116, 0, 114, 0, 111, 0, 110, 0, 103, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 3, 199, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 3, 184, 48, 130, 3, 180, 2, 1, 0, 48, 130, 3, 173, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 206, 244, 28, 93, 203, 68, 165, 233, 2, 2, 7, 208, 128, 130, 3, 128, 74, 136, 80, 43, 195, 182, 181, 122, 132, 229, 10, 181, 229, 1, 78, 122, 145, 95, 16, 236, 242, 107, 9, 141, 186, 205, 32, 139, 154, 132, 184, 180, 80, 26, 3, 85, 196, 10, 33, 216, 101, 105, 172, 196, 77, 222, 232, 229, 37, 199, 6, 189, 152, 8, 203, 15, 231, 164, 140, 163, 120, 23, 137, 34, 16, 241, 186, 64, 11, 241, 210, 160, 186, 90, 55, 39, 21, 210, 145, 74, 151, 40, 122, 221, 240, 191, 185, 115, 85, 208, 125, 136, 51, 210, 137, 124, 155, 65, 135, 50, 35, 233, 223, 157, 131, 108, 11, 142, 152, 217, 162, 163, 218, 47, 89, 255, 229, 21, 224, 139, 187, 4, 175, 251, 248, 8, 18, 16, 112, 134, 75, 17, 90, 246, 62, 150, 31, 207, 95, 172, 5, 220, 135, 201, 179, 247, 193, 177, 23, 5, 170, 207, 66, 219, 145, 117, 99, 167, 238, 100, 158, 169, 44, 22, 199, 132, 38, 67, 203, 66, 187, 53, 216, 98, 113, 76, 142, 153, 36, 238, 110, 152, 251, 68, 6, 154, 255, 51, 65, 75, 91, 9, 121, 86, 116, 35, 224, 47, 220, 194, 17, 136, 175, 76, 165, 210, 153, 89, 104, 197, 133, 200, 49, 173, 1, 167, 5, 88, 183, 58, 193, 146, 30, 60, 129, 195, 3, 16, 78, 87, 167, 135, 182, 182, 150, 68, 116, 161, 116, 125, 180, 155, 103, 63, 0, 98, 27, 179, 142, 64, 73, 31, 35, 63, 138, 137, 30, 169, 149, 221, 104, 21, 182, 23, 67, 246, 2, 162, 217, 165, 238, 124, 229, 149, 84, 5, 203, 174, 149, 79, 153, 25, 153, 233, 213, 86, 250, 10, 42, 6, 226, 113, 123, 90, 76, 153, 39, 203, 237, 124, 36, 191, 232, 132, 127, 82, 163, 109, 100, 121, 54, 254, 116, 155, 26, 255, 50, 150, 140, 172, 240, 208, 245, 65, 72, 49, 183, 149, 220, 244, 120, 193, 37, 222, 144, 137, 82, 168, 233, 13, 179, 2, 217, 29, 177, 4, 136, 69, 192, 133, 249, 180, 9, 62, 162, 216, 251, 164, 188, 173, 143, 149, 32, 204, 255, 246, 249, 33, 216, 75, 23, 127, 215, 134, 69, 79, 112, 213, 198, 89, 44, 51, 19, 226, 16, 210, 125, 212, 232, 18, 252, 178, 93, 245, 33, 62, 81, 207, 78, 167, 144, 238, 251, 27, 194, 21, 53, 44, 63, 58, 26, 176, 75, 79, 164, 67, 59, 80, 17, 54, 209, 58, 184, 2, 36, 202, 135, 91, 35, 78, 55, 203, 134, 238, 79, 178, 84, 242, 46, 223, 131, 227, 87, 255, 182, 244, 117, 162, 60, 134, 161, 49, 59, 95, 64, 190, 30, 195, 100, 106, 7, 120, 181, 202, 122, 174, 234, 30, 11, 88, 65, 238, 53, 64, 243, 233, 185, 168, 34, 8, 58, 233, 171, 210, 104, 105, 93, 49, 206, 11, 40, 172, 248, 204, 80, 128, 53, 143, 54, 95, 92, 70, 152, 209, 193, 116, 252, 138, 19, 50, 249, 43, 14, 225, 167, 8, 205, 112, 103, 79, 223, 14, 141, 147, 70, 197, 91, 11, 117, 202, 19, 180, 240, 21, 118, 108, 25, 63, 54, 94, 156, 112, 109, 16, 216, 113, 192, 246, 207, 156, 203, 65, 75, 143, 157, 125, 158, 151, 167, 207, 96, 6, 162, 97, 66, 114, 95, 227, 52, 44, 98, 121, 139, 181, 240, 89, 27, 59, 156, 189, 93, 28, 48, 165, 11, 245, 102, 198, 29, 5, 6, 180, 147, 58, 130, 65, 201, 10, 164, 193, 93, 168, 96, 156, 89, 225, 139, 70, 245, 74, 128, 3, 141, 133, 137, 21, 163, 77, 3, 19, 226, 35, 248, 156, 56, 56, 37, 221, 69, 67, 214, 3, 152, 149, 224, 92, 72, 173, 39, 196, 229, 153, 67, 151, 190, 115, 20, 70, 126, 210, 140, 109, 186, 46, 82, 88, 185, 96, 1, 254, 161, 217, 130, 226, 133, 18, 103, 175, 132, 249, 102, 51, 229, 192, 94, 44, 10, 25, 197, 237, 77, 196, 1, 253, 153, 78, 237, 151, 136, 89, 203, 113, 244, 217, 235, 252, 31, 116, 139, 233, 40, 197, 22, 176, 157, 130, 109, 149, 215, 11, 20, 3, 156, 239, 29, 250, 95, 188, 241, 184, 117, 108, 216, 74, 91, 169, 186, 122, 175, 214, 36, 62, 240, 142, 107, 172, 7, 250, 31, 101, 75, 83, 255, 56, 8, 231, 200, 194, 154, 105, 202, 170, 207, 252, 128, 10, 249, 53, 41, 168, 94, 225, 163, 10, 251, 149, 64, 10, 144, 252, 44, 136, 149, 119, 183, 7, 230, 87, 160, 46, 62, 185, 82, 218, 213, 125, 62, 70, 43, 27, 5, 181, 50, 193, 11, 30, 0, 8, 81, 94, 169, 171, 143, 113, 235, 171, 38, 129, 116, 11, 191, 75, 235, 185, 184, 178, 36, 193, 174, 177, 51, 87, 163, 142, 52, 62, 161, 237, 139, 50, 51, 227, 188, 164, 106, 233, 209, 8, 237, 241, 92, 145, 51, 6, 36, 197, 24, 255, 143, 5, 144, 43, 87, 242, 208, 251, 79, 171, 90, 103, 219, 73, 242, 95, 36, 48, 95, 127, 40, 128, 201, 80, 79, 74, 226, 25, 43, 50, 56, 180, 59, 84, 148, 110, 151, 9, 45, 4, 212, 172, 31, 189, 44, 115, 59, 169, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 238, 91, 24, 104, 64, 45, 237, 63, 114, 36, 111, 106, 82, 43, 251, 110, 60, 159, 42, 178, 4, 20, 20, 49, 70, 55, 115, 247, 221, 156, 47, 189, 197, 19, 116, 77, 161, 163, 216, 77, 166, 144, 2, 2, 7, 208 }; - public string certificateThumbPrint2 = "4281446463C6F7F5B8EDFFA4BD6E345E46857CAD"; - public static byte[] certificateRawBytes2 = new byte[] { 48, 130, 10, 36, 2, 1, 3, 48, 130, 9, 224, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 9, 209, 4, 130, 9, 205, 48, 130, 9, 201, 48, 130, 5, 250, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 235, 4, 130, 5, 231, 48, 130, 5, 227, 48, 130, 5, 223, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 4, 254, 48, 130, 4, 250, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 95, 228, 98, 55, 21, 153, 43, 16, 2, 2, 7, 208, 4, 130, 4, 216, 210, 4, 83, 193, 62, 47, 171, 147, 165, 139, 74, 78, 118, 172, 54, 56, 118, 81, 203, 190, 58, 5, 220, 181, 64, 1, 213, 5, 156, 164, 86, 59, 63, 230, 250, 57, 26, 236, 10, 195, 200, 80, 217, 38, 214, 116, 250, 224, 236, 54, 59, 208, 206, 128, 167, 122, 89, 0, 195, 145, 41, 63, 122, 160, 157, 21, 226, 205, 179, 166, 243, 92, 94, 71, 61, 208, 183, 153, 105, 24, 232, 255, 139, 188, 32, 109, 120, 41, 18, 218, 212, 71, 219, 139, 182, 59, 78, 46, 97, 176, 67, 125, 239, 234, 107, 47, 202, 71, 81, 100, 243, 136, 162, 39, 197, 207, 4, 224, 52, 62, 104, 88, 44, 42, 234, 18, 70, 55, 248, 251, 121, 215, 162, 77, 109, 189, 135, 86, 219, 69, 208, 92, 147, 163, 21, 50, 0, 87, 166, 8, 39, 21, 72, 107, 75, 214, 165, 238, 50, 145, 2, 65, 138, 179, 21, 87, 149, 218, 163, 51, 214, 17, 93, 252, 224, 6, 245, 242, 132, 63, 100, 223, 136, 166, 89, 253, 171, 204, 215, 191, 170, 25, 40, 44, 14, 32, 25, 22, 149, 161, 62, 145, 61, 162, 32, 116, 7, 201, 33, 159, 128, 248, 172, 42, 33, 51, 248, 187, 135, 58, 107, 23, 7, 39, 21, 114, 186, 222, 132, 117, 193, 132, 94, 57, 213, 80, 9, 86, 186, 62, 201, 40, 12, 196, 207, 23, 182, 127, 245, 139, 18, 62, 107, 82, 58, 156, 156, 17, 29, 173, 60, 227, 180, 73, 245, 165, 16, 186, 246, 64, 178, 40, 66, 2, 119, 61, 78, 246, 214, 226, 89, 225, 85, 183, 163, 108, 82, 36, 109, 216, 195, 141, 174, 123, 162, 91, 128, 169, 37, 68, 121, 170, 80, 236, 27, 109, 173, 223, 6, 37, 37, 249, 166, 219, 226, 116, 236, 184, 212, 47, 70, 249, 89, 195, 216, 157, 227, 137, 247, 179, 148, 16, 40, 217, 220, 247, 97, 42, 120, 63, 3, 14, 104, 79, 111, 160, 245, 210, 33, 50, 6, 36, 90, 225, 206, 104, 70, 4, 191, 79, 16, 237, 200, 125, 92, 215, 175, 196, 143, 134, 95, 112, 251, 58, 68, 165, 157, 80, 82, 78, 203, 34, 131, 163, 136, 200, 4, 117, 174, 197, 159, 175, 14, 5, 110, 99, 70, 235, 91, 214, 136, 218, 14, 203, 28, 153, 48, 34, 60, 10, 202, 129, 212, 146, 83, 104, 236, 228, 248, 125, 120, 98, 174, 173, 216, 146, 254, 128, 0, 206, 64, 119, 56, 71, 153, 81, 155, 40, 195, 114, 41, 73, 108, 77, 229, 98, 15, 216, 164, 13, 139, 81, 9, 143, 137, 164, 122, 35, 192, 93, 87, 85, 88, 230, 168, 148, 233, 5, 76, 244, 116, 121, 157, 27, 174, 231, 58, 84, 159, 102, 149, 163, 142, 128, 195, 10, 214, 11, 164, 197, 182, 189, 33, 177, 232, 39, 44, 225, 74, 237, 197, 52, 82, 76, 105, 9, 221, 110, 251, 62, 255, 194, 24, 93, 184, 19, 220, 119, 127, 76, 198, 181, 14, 136, 106, 49, 241, 164, 18, 62, 80, 18, 88, 114, 167, 138, 183, 72, 160, 64, 27, 140, 160, 74, 113, 40, 212, 223, 128, 23, 113, 192, 162, 184, 234, 141, 207, 3, 246, 40, 2, 89, 184, 191, 67, 121, 16, 187, 117, 141, 163, 187, 170, 124, 169, 67, 148, 226, 202, 132, 61, 95, 7, 242, 116, 252, 228, 17, 102, 201, 178, 77, 215, 164, 204, 210, 31, 100, 243, 242, 190, 151, 96, 173, 74, 195, 214, 233, 78, 187, 73, 124, 183, 38, 124, 33, 108, 226, 113, 120, 25, 87, 201, 49, 134, 106, 127, 206, 234, 40, 37, 199, 56, 112, 0, 172, 136, 68, 8, 145, 225, 78, 186, 170, 121, 218, 37, 186, 80, 207, 29, 180, 129, 159, 178, 162, 152, 107, 39, 229, 192, 237, 226, 172, 88, 117, 144, 229, 124, 67, 74, 156, 81, 211, 118, 93, 188, 93, 209, 170, 240, 136, 37, 18, 181, 20, 48, 70, 79, 37, 169, 184, 240, 101, 153, 230, 10, 212, 36, 29, 201, 27, 39, 107, 221, 179, 226, 19, 199, 108, 158, 78, 217, 49, 255, 131, 36, 194, 37, 133, 47, 36, 207, 13, 16, 115, 179, 220, 57, 248, 194, 101, 181, 222, 170, 240, 120, 37, 50, 87, 198, 14, 251, 138, 115, 33, 231, 29, 240, 172, 130, 199, 77, 53, 245, 43, 178, 61, 103, 28, 33, 175, 247, 67, 232, 3, 139, 198, 115, 93, 146, 71, 154, 206, 118, 163, 99, 213, 241, 174, 20, 247, 181, 12, 112, 165, 116, 179, 220, 52, 200, 206, 162, 105, 12, 30, 212, 199, 179, 243, 176, 156, 113, 51, 142, 138, 70, 179, 130, 28, 118, 98, 7, 46, 26, 100, 200, 215, 16, 80, 138, 113, 160, 107, 209, 18, 85, 2, 69, 235, 2, 217, 80, 238, 212, 108, 18, 68, 63, 24, 174, 60, 253, 127, 94, 255, 249, 181, 98, 243, 240, 172, 109, 242, 155, 42, 70, 155, 38, 214, 231, 206, 60, 205, 46, 68, 77, 128, 192, 141, 4, 73, 54, 137, 32, 71, 20, 68, 11, 204, 124, 97, 205, 246, 80, 209, 175, 165, 121, 60, 195, 104, 104, 60, 2, 99, 142, 82, 121, 136, 118, 226, 178, 158, 80, 0, 159, 131, 208, 232, 46, 150, 196, 154, 196, 50, 183, 85, 170, 242, 218, 232, 236, 225, 52, 46, 109, 237, 127, 68, 251, 25, 105, 239, 32, 59, 205, 174, 131, 95, 75, 93, 218, 168, 173, 6, 152, 111, 251, 201, 146, 19, 230, 2, 32, 73, 32, 64, 101, 124, 96, 155, 101, 211, 232, 249, 143, 177, 147, 17, 187, 246, 46, 202, 155, 113, 236, 181, 70, 118, 220, 87, 20, 27, 17, 255, 223, 65, 217, 126, 5, 246, 161, 95, 186, 194, 77, 46, 26, 128, 253, 108, 178, 246, 121, 133, 172, 172, 75, 59, 12, 118, 7, 146, 154, 51, 94, 243, 112, 232, 103, 239, 159, 64, 183, 187, 79, 22, 43, 7, 250, 205, 183, 201, 178, 235, 80, 154, 233, 232, 125, 78, 62, 203, 132, 33, 4, 185, 234, 59, 190, 116, 133, 240, 41, 172, 207, 36, 177, 206, 49, 18, 40, 23, 177, 250, 36, 243, 59, 160, 24, 245, 218, 53, 234, 79, 17, 68, 19, 165, 156, 16, 250, 18, 111, 60, 179, 142, 168, 4, 67, 212, 11, 230, 113, 46, 105, 234, 98, 60, 36, 218, 202, 93, 54, 53, 160, 247, 144, 244, 225, 219, 101, 143, 239, 183, 75, 6, 144, 68, 10, 96, 98, 191, 251, 230, 243, 154, 236, 113, 164, 139, 155, 250, 133, 104, 45, 21, 106, 221, 20, 139, 191, 33, 38, 103, 135, 95, 5, 237, 173, 185, 173, 2, 40, 196, 114, 3, 174, 13, 201, 219, 150, 100, 30, 212, 38, 60, 106, 112, 244, 229, 34, 155, 169, 51, 62, 96, 154, 90, 225, 221, 103, 8, 201, 235, 189, 170, 42, 44, 255, 210, 69, 155, 119, 153, 8, 164, 171, 97, 173, 166, 68, 207, 170, 50, 92, 17, 2, 32, 182, 46, 136, 189, 187, 148, 206, 205, 127, 179, 32, 31, 77, 12, 141, 19, 126, 5, 82, 221, 47, 87, 206, 198, 146, 226, 128, 144, 64, 124, 49, 129, 205, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 74, 30, 72, 0, 98, 0, 53, 0, 55, 0, 56, 0, 48, 0, 53, 0, 52, 0, 52, 0, 45, 0, 52, 0, 56, 0, 99, 0, 48, 0, 45, 0, 52, 0, 55, 0, 56, 0, 52, 0, 45, 0, 57, 0, 50, 0, 98, 0, 52, 0, 45, 0, 56, 0, 99, 0, 49, 0, 101, 0, 102, 0, 56, 0, 54, 0, 101, 0, 54, 0, 100, 0, 54, 0, 54, 48, 93, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 80, 30, 78, 0, 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 83, 0, 116, 0, 114, 0, 111, 0, 110, 0, 103, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 3, 199, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 3, 184, 48, 130, 3, 180, 2, 1, 0, 48, 130, 3, 173, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 109, 84, 234, 217, 158, 100, 175, 217, 2, 2, 7, 208, 128, 130, 3, 128, 90, 89, 57, 156, 113, 214, 108, 227, 208, 52, 188, 14, 47, 164, 163, 155, 102, 18, 248, 55, 200, 122, 232, 224, 246, 212, 57, 2, 121, 60, 244, 110, 223, 203, 184, 67, 115, 179, 191, 220, 45, 209, 143, 220, 17, 53, 61, 179, 105, 25, 150, 102, 108, 168, 140, 67, 141, 86, 165, 159, 139, 29, 23, 173, 40, 81, 79, 245, 12, 154, 11, 154, 208, 199, 34, 25, 46, 112, 30, 175, 71, 124, 20, 64, 128, 150, 156, 241, 198, 55, 103, 242, 169, 160, 232, 138, 160, 189, 30, 66, 73, 134, 28, 1, 32, 19, 151, 249, 75, 179, 252, 0, 244, 116, 209, 35, 116, 199, 171, 120, 18, 234, 17, 47, 70, 115, 154, 76, 170, 36, 166, 140, 190, 168, 99, 169, 130, 200, 220, 55, 38, 56, 145, 4, 119, 149, 184, 242, 214, 46, 181, 101, 25, 97, 102, 39, 240, 123, 83, 87, 69, 107, 159, 69, 136, 101, 88, 45, 2, 254, 111, 255, 202, 184, 213, 237, 98, 120, 235, 247, 134, 85, 155, 103, 232, 99, 218, 169, 219, 55, 232, 126, 133, 172, 179, 210, 82, 40, 42, 101, 157, 213, 42, 217, 88, 111, 101, 88, 202, 30, 212, 117, 225, 169, 164, 105, 225, 128, 251, 66, 148, 38, 7, 166, 125, 120, 135, 158, 139, 222, 245, 170, 5, 8, 102, 51, 193, 173, 136, 141, 183, 233, 168, 185, 208, 198, 238, 176, 63, 6, 167, 53, 27, 15, 226, 47, 37, 154, 1, 126, 252, 77, 83, 5, 21, 221, 166, 171, 9, 177, 181, 85, 83, 6, 154, 164, 24, 206, 48, 88, 243, 82, 103, 80, 9, 1, 169, 225, 255, 75, 10, 150, 17, 242, 49, 110, 194, 114, 9, 69, 15, 183, 20, 33, 43, 113, 79, 131, 115, 102, 230, 138, 139, 191, 29, 249, 175, 222, 231, 87, 98, 213, 108, 107, 30, 10, 126, 114, 3, 81, 67, 192, 26, 125, 31, 87, 83, 75, 113, 254, 122, 143, 227, 104, 67, 58, 155, 93, 177, 158, 84, 50, 50, 197, 125, 17, 252, 87, 194, 176, 160, 140, 220, 47, 209, 188, 158, 89, 167, 166, 241, 212, 44, 108, 208, 52, 39, 128, 198, 157, 93, 56, 154, 184, 136, 9, 48, 93, 239, 244, 140, 204, 139, 91, 181, 160, 117, 230, 142, 233, 205, 18, 178, 212, 103, 148, 188, 201, 106, 70, 172, 212, 215, 145, 62, 166, 139, 165, 241, 178, 100, 150, 119, 234, 44, 107, 123, 73, 105, 82, 222, 254, 40, 49, 198, 167, 88, 165, 176, 187, 124, 161, 97, 133, 188, 159, 234, 90, 110, 99, 121, 191, 123, 254, 86, 108, 164, 231, 225, 227, 209, 237, 155, 26, 148, 241, 91, 253, 18, 68, 137, 175, 184, 4, 160, 176, 109, 72, 177, 84, 229, 115, 95, 98, 155, 117, 96, 54, 226, 141, 163, 109, 58, 189, 67, 15, 246, 151, 136, 169, 88, 46, 160, 102, 113, 226, 92, 122, 209, 140, 52, 105, 235, 254, 127, 131, 235, 246, 146, 67, 24, 97, 196, 193, 248, 246, 214, 55, 52, 254, 214, 193, 77, 192, 91, 45, 17, 204, 77, 193, 211, 166, 152, 214, 79, 173, 167, 11, 49, 253, 9, 167, 249, 168, 228, 198, 164, 61, 209, 118, 5, 170, 128, 128, 217, 130, 90, 64, 13, 79, 191, 142, 29, 211, 101, 225, 173, 190, 124, 132, 149, 107, 178, 129, 102, 135, 23, 109, 5, 75, 207, 185, 21, 227, 184, 41, 92, 83, 180, 164, 77, 140, 184, 216, 66, 25, 104, 165, 158, 95, 234, 78, 153, 215, 26, 253, 100, 115, 101, 149, 58, 5, 49, 204, 213, 35, 188, 200, 201, 74, 248, 94, 143, 231, 215, 59, 145, 54, 28, 197, 156, 197, 131, 80, 114, 212, 236, 133, 25, 178, 57, 28, 241, 237, 56, 220, 195, 19, 234, 13, 122, 109, 81, 205, 163, 204, 122, 82, 10, 166, 44, 44, 74, 229, 251, 200, 42, 128, 223, 29, 182, 95, 180, 3, 100, 235, 56, 34, 157, 84, 23, 142, 6, 147, 187, 145, 97, 185, 6, 254, 48, 110, 125, 41, 239, 163, 169, 196, 145, 120, 115, 213, 57, 85, 118, 121, 211, 14, 56, 54, 34, 171, 101, 37, 190, 232, 55, 64, 238, 119, 150, 67, 136, 116, 193, 175, 100, 38, 2, 163, 28, 27, 250, 88, 46, 56, 18, 20, 68, 115, 111, 172, 112, 239, 55, 213, 5, 2, 91, 134, 98, 53, 99, 90, 6, 18, 199, 74, 241, 162, 85, 182, 134, 42, 233, 38, 192, 248, 200, 165, 194, 85, 232, 129, 170, 36, 155, 44, 14, 31, 234, 191, 172, 204, 146, 151, 24, 214, 14, 174, 163, 88, 15, 198, 119, 104, 198, 20, 139, 7, 199, 232, 144, 30, 129, 243, 234, 148, 231, 227, 87, 76, 81, 160, 149, 26, 233, 108, 133, 127, 193, 82, 233, 19, 179, 62, 210, 244, 118, 249, 202, 245, 5, 71, 37, 53, 249, 30, 0, 43, 190, 110, 96, 184, 239, 176, 52, 55, 109, 110, 111, 53, 193, 192, 200, 180, 5, 88, 32, 174, 106, 17, 23, 127, 190, 166, 34, 57, 161, 146, 255, 197, 222, 2, 107, 227, 61, 215, 36, 253, 1, 122, 234, 234, 156, 79, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 207, 75, 252, 75, 27, 80, 128, 157, 13, 40, 231, 80, 100, 232, 103, 176, 94, 95, 145, 147, 4, 20, 48, 158, 42, 31, 56, 126, 217, 230, 42, 16, 115, 84, 206, 98, 189, 26, 78, 38, 171, 12, 2, 2, 7, 208 }; - public static byte[] certificateRawBytes3 = new byte[] { 48, 130, 10, 44, 2, 1, 3, 48, 130, 9, 232, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 9, 217, 4, 130, 9, 213, 48, 130, 9, 209, 48, 130, 5, 250, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 235, 4, 130, 5, 231, 48, 130, 5, 227, 48, 130, 5, 223, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 4, 254, 48, 130, 4, 250, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 201, 182, 155, 228, 101, 5, 93, 99, 2, 2, 7, 208, 4, 130, 4, 216, 10, 49, 25, 129, 251, 253, 104, 241, 120, 23, 72, 166, 23, 144, 117, 109, 170, 226, 13, 202, 202, 135, 74, 114, 79, 208, 250, 193, 195, 26, 118, 85, 45, 17, 43, 75, 29, 44, 52, 18, 255, 66, 137, 221, 33, 65, 186, 142, 90, 33, 2, 4, 177, 170, 58, 244, 60, 82, 40, 77, 64, 168, 77, 2, 29, 36, 210, 107, 213, 47, 160, 181, 82, 202, 221, 5, 202, 46, 222, 27, 228, 181, 14, 128, 2, 65, 57, 13, 128, 211, 53, 168, 207, 150, 76, 135, 1, 84, 243, 72, 151, 205, 184, 164, 221, 138, 107, 162, 163, 248, 8, 107, 102, 223, 173, 12, 192, 119, 77, 154, 224, 213, 198, 90, 183, 161, 188, 4, 221, 191, 76, 179, 87, 158, 140, 179, 198, 253, 87, 148, 162, 94, 186, 171, 36, 251, 214, 44, 164, 240, 131, 52, 204, 192, 163, 166, 108, 150, 108, 85, 138, 181, 45, 159, 7, 106, 47, 1, 189, 81, 104, 80, 66, 21, 133, 111, 226, 238, 73, 126, 191, 61, 169, 123, 210, 37, 228, 121, 231, 118, 134, 176, 15, 206, 137, 99, 253, 172, 21, 14, 249, 32, 226, 122, 101, 41, 98, 23, 35, 183, 23, 66, 102, 249, 175, 41, 103, 161, 211, 57, 208, 146, 182, 229, 55, 1, 251, 212, 253, 83, 119, 224, 153, 22, 198, 147, 9, 99, 101, 214, 142, 202, 197, 187, 197, 21, 199, 186, 231, 143, 116, 4, 253, 70, 238, 220, 98, 236, 110, 20, 153, 134, 52, 40, 245, 167, 76, 28, 24, 242, 40, 57, 97, 227, 223, 239, 249, 14, 34, 40, 53, 145, 35, 248, 37, 251, 84, 65, 255, 0, 143, 54, 73, 38, 8, 99, 160, 70, 49, 7, 238, 31, 238, 62, 180, 125, 71, 166, 96, 52, 37, 134, 229, 198, 150, 206, 102, 241, 51, 240, 186, 120, 74, 55, 114, 46, 190, 85, 15, 89, 4, 126, 89, 247, 120, 241, 119, 110, 225, 126, 99, 143, 179, 7, 117, 242, 225, 197, 247, 130, 105, 59, 129, 127, 222, 207, 20, 108, 241, 149, 124, 156, 175, 187, 105, 79, 23, 245, 131, 106, 12, 111, 228, 124, 128, 147, 204, 21, 122, 93, 52, 251, 197, 119, 204, 195, 111, 8, 43, 226, 50, 39, 66, 179, 84, 108, 71, 35, 10, 35, 129, 96, 0, 110, 5, 92, 223, 77, 49, 237, 184, 153, 163, 111, 29, 241, 52, 62, 190, 157, 22, 40, 26, 6, 231, 156, 90, 210, 16, 183, 154, 208, 244, 113, 213, 110, 121, 56, 131, 240, 136, 77, 171, 87, 215, 87, 134, 188, 14, 104, 217, 35, 218, 215, 36, 50, 5, 72, 137, 63, 242, 29, 0, 28, 127, 172, 190, 166, 239, 100, 172, 172, 23, 131, 237, 32, 73, 92, 157, 178, 82, 87, 0, 131, 53, 226, 176, 125, 221, 33, 75, 201, 164, 24, 253, 23, 130, 41, 129, 13, 223, 10, 22, 231, 99, 220, 171, 0, 205, 239, 89, 47, 224, 139, 181, 201, 54, 125, 105, 206, 168, 62, 145, 182, 114, 209, 134, 48, 0, 90, 143, 163, 161, 117, 167, 74, 6, 229, 92, 10, 163, 27, 49, 25, 139, 44, 140, 35, 107, 46, 74, 124, 180, 88, 92, 49, 27, 53, 93, 20, 105, 35, 8, 242, 28, 106, 106, 80, 220, 138, 169, 89, 154, 9, 57, 173, 83, 67, 136, 119, 200, 78, 152, 47, 100, 166, 119, 23, 208, 46, 57, 213, 6, 18, 21, 29, 185, 174, 154, 245, 154, 122, 53, 155, 28, 110, 139, 20, 236, 97, 97, 155, 65, 128, 45, 27, 95, 117, 126, 150, 87, 70, 37, 209, 65, 178, 27, 17, 59, 180, 176, 172, 104, 184, 144, 2, 238, 219, 210, 250, 168, 125, 24, 113, 36, 28, 105, 107, 34, 241, 175, 251, 71, 110, 72, 64, 15, 194, 39, 105, 18, 168, 60, 13, 50, 62, 191, 196, 255, 5, 106, 100, 158, 3, 45, 148, 238, 239, 64, 3, 21, 198, 50, 165, 107, 245, 195, 103, 138, 108, 153, 48, 105, 193, 106, 31, 82, 126, 202, 144, 215, 64, 138, 23, 160, 13, 233, 88, 199, 77, 46, 231, 124, 237, 26, 24, 206, 53, 162, 53, 224, 41, 178, 17, 44, 148, 22, 151, 192, 140, 121, 12, 68, 31, 238, 82, 24, 21, 116, 219, 172, 138, 179, 91, 10, 54, 235, 19, 49, 145, 67, 5, 55, 171, 23, 196, 237, 252, 107, 197, 18, 207, 48, 75, 229, 197, 152, 60, 33, 246, 97, 231, 28, 163, 222, 213, 8, 169, 178, 54, 217, 174, 208, 181, 173, 59, 174, 100, 65, 137, 130, 47, 42, 59, 176, 209, 225, 254, 59, 193, 40, 110, 195, 139, 166, 11, 44, 134, 251, 243, 46, 200, 174, 96, 21, 244, 10, 226, 244, 40, 115, 30, 241, 143, 100, 247, 0, 227, 248, 239, 78, 249, 80, 0, 35, 73, 107, 250, 156, 21, 36, 138, 203, 235, 84, 154, 46, 184, 12, 139, 246, 255, 89, 162, 249, 107, 237, 55, 148, 123, 197, 148, 254, 90, 201, 255, 249, 219, 170, 138, 212, 179, 175, 93, 42, 44, 195, 71, 108, 77, 187, 145, 147, 82, 154, 29, 166, 90, 35, 124, 157, 68, 102, 136, 235, 143, 100, 41, 248, 103, 139, 50, 56, 108, 233, 65, 228, 42, 152, 157, 102, 176, 56, 249, 86, 198, 236, 75, 61, 206, 240, 255, 55, 20, 222, 105, 19, 221, 7, 66, 194, 20, 186, 152, 120, 90, 68, 231, 17, 37, 248, 172, 75, 172, 129, 209, 220, 180, 123, 65, 32, 215, 146, 245, 5, 28, 255, 213, 35, 10, 59, 141, 15, 111, 5, 176, 189, 54, 209, 38, 234, 89, 52, 203, 128, 17, 147, 202, 171, 186, 8, 10, 89, 223, 83, 119, 28, 102, 11, 108, 70, 235, 43, 6, 146, 152, 132, 106, 192, 10, 80, 242, 88, 117, 8, 80, 13, 224, 120, 56, 19, 165, 190, 45, 124, 193, 38, 185, 40, 115, 222, 149, 243, 106, 169, 170, 55, 79, 87, 59, 203, 110, 62, 3, 100, 130, 147, 171, 79, 9, 227, 36, 39, 134, 231, 253, 179, 7, 23, 19, 206, 64, 56, 32, 175, 127, 46, 234, 192, 238, 190, 122, 35, 52, 162, 176, 223, 174, 205, 233, 88, 60, 32, 77, 154, 144, 15, 148, 126, 78, 53, 37, 247, 129, 104, 215, 9, 0, 43, 198, 64, 47, 115, 102, 232, 31, 49, 70, 219, 23, 54, 242, 73, 110, 145, 16, 206, 59, 91, 179, 172, 134, 143, 20, 22, 78, 167, 102, 59, 91, 29, 206, 197, 73, 245, 245, 219, 59, 42, 198, 105, 195, 50, 23, 196, 133, 185, 8, 30, 197, 92, 213, 48, 194, 217, 133, 65, 229, 16, 70, 231, 232, 230, 167, 77, 127, 233, 148, 87, 181, 62, 1, 159, 32, 27, 110, 167, 31, 111, 1, 196, 242, 7, 123, 241, 89, 221, 132, 252, 185, 175, 112, 51, 108, 228, 189, 207, 189, 89, 23, 65, 205, 7, 53, 171, 220, 245, 242, 85, 187, 55, 153, 8, 255, 1, 171, 160, 187, 109, 130, 245, 4, 26, 1, 83, 223, 10, 221, 61, 65, 101, 0, 94, 136, 47, 2, 209, 7, 143, 65, 216, 32, 71, 168, 155, 198, 236, 170, 205, 64, 49, 129, 205, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 74, 30, 72, 0, 49, 0, 99, 0, 57, 0, 48, 0, 53, 0, 48, 0, 51, 0, 97, 0, 45, 0, 55, 0, 56, 0, 52, 0, 57, 0, 45, 0, 52, 0, 51, 0, 54, 0, 99, 0, 45, 0, 56, 0, 54, 0, 97, 0, 52, 0, 45, 0, 49, 0, 51, 0, 50, 0, 97, 0, 54, 0, 53, 0, 100, 0, 52, 0, 97, 0, 48, 0, 48, 0, 55, 48, 93, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 80, 30, 78, 0, 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 83, 0, 116, 0, 114, 0, 111, 0, 110, 0, 103, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 3, 207, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 3, 192, 48, 130, 3, 188, 2, 1, 0, 48, 130, 3, 181, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 200, 59, 127, 243, 171, 147, 157, 127, 2, 2, 7, 208, 128, 130, 3, 136, 99, 75, 113, 248, 97, 190, 186, 177, 98, 176, 186, 91, 120, 170, 132, 193, 62, 121, 23, 129, 255, 220, 247, 43, 159, 29, 163, 114, 13, 93, 143, 171, 102, 66, 252, 74, 99, 253, 38, 53, 56, 73, 69, 51, 98, 128, 200, 232, 11, 162, 4, 170, 137, 109, 228, 185, 27, 6, 195, 120, 253, 174, 180, 67, 183, 248, 105, 101, 6, 173, 66, 251, 129, 249, 90, 140, 192, 43, 14, 201, 78, 111, 140, 115, 138, 216, 199, 45, 66, 89, 55, 144, 91, 37, 72, 194, 78, 193, 34, 16, 13, 88, 91, 183, 96, 143, 202, 15, 164, 215, 97, 222, 124, 248, 92, 221, 184, 103, 54, 132, 64, 114, 209, 116, 102, 168, 236, 8, 132, 143, 98, 218, 86, 110, 79, 45, 73, 156, 55, 35, 162, 83, 219, 200, 223, 144, 56, 64, 170, 137, 193, 157, 107, 47, 58, 38, 128, 142, 18, 184, 44, 80, 182, 80, 26, 8, 203, 161, 224, 254, 247, 223, 56, 124, 23, 187, 123, 63, 254, 147, 193, 77, 209, 101, 76, 46, 70, 118, 57, 172, 177, 35, 15, 49, 189, 115, 28, 117, 133, 166, 225, 246, 19, 133, 195, 70, 30, 237, 25, 215, 141, 19, 115, 48, 104, 39, 41, 140, 104, 38, 32, 215, 222, 153, 232, 74, 16, 23, 233, 21, 237, 145, 161, 62, 225, 143, 30, 219, 183, 12, 62, 24, 141, 28, 73, 49, 203, 92, 39, 133, 152, 143, 176, 197, 87, 47, 128, 228, 128, 169, 5, 121, 168, 15, 141, 217, 179, 79, 128, 150, 131, 78, 224, 238, 184, 141, 249, 123, 211, 241, 236, 103, 45, 7, 211, 163, 108, 216, 104, 200, 208, 134, 78, 196, 96, 118, 184, 78, 62, 88, 221, 5, 155, 249, 176, 207, 238, 2, 147, 229, 18, 77, 69, 189, 13, 237, 212, 224, 12, 61, 45, 254, 130, 135, 234, 41, 51, 142, 94, 24, 174, 55, 247, 56, 115, 206, 214, 161, 85, 51, 74, 248, 16, 219, 70, 91, 82, 26, 150, 59, 215, 39, 41, 85, 211, 77, 49, 23, 52, 59, 127, 20, 22, 130, 40, 253, 112, 123, 6, 15, 253, 98, 212, 24, 154, 126, 134, 216, 76, 76, 110, 212, 70, 62, 213, 115, 53, 158, 209, 152, 92, 178, 254, 24, 224, 121, 208, 19, 114, 250, 255, 80, 163, 61, 237, 48, 108, 51, 36, 41, 84, 97, 175, 131, 106, 150, 73, 176, 67, 114, 173, 244, 158, 235, 127, 19, 85, 179, 74, 144, 206, 126, 50, 39, 173, 112, 232, 108, 43, 9, 193, 167, 162, 63, 242, 218, 47, 26, 121, 237, 13, 240, 7, 107, 193, 202, 117, 224, 208, 128, 174, 137, 242, 221, 209, 37, 88, 184, 254, 69, 10, 39, 163, 158, 55, 249, 111, 238, 9, 78, 154, 184, 139, 227, 198, 39, 127, 222, 220, 77, 101, 128, 31, 210, 138, 48, 36, 26, 80, 160, 167, 181, 185, 196, 195, 208, 129, 23, 17, 157, 101, 157, 45, 173, 249, 158, 173, 245, 103, 88, 24, 170, 174, 203, 92, 69, 211, 167, 1, 221, 73, 99, 16, 148, 44, 97, 190, 28, 144, 252, 87, 10, 13, 95, 83, 211, 86, 14, 176, 27, 77, 236, 68, 10, 245, 185, 82, 154, 22, 207, 1, 163, 21, 214, 183, 201, 254, 91, 176, 171, 176, 223, 193, 128, 33, 100, 34, 32, 146, 156, 207, 247, 97, 250, 244, 41, 140, 253, 230, 56, 62, 90, 190, 41, 225, 50, 221, 134, 219, 63, 4, 81, 210, 106, 154, 6, 186, 97, 227, 13, 79, 111, 18, 204, 184, 246, 107, 194, 105, 65, 30, 179, 125, 196, 248, 96, 216, 77, 160, 27, 93, 42, 23, 6, 246, 13, 178, 22, 46, 67, 83, 224, 116, 91, 136, 223, 246, 213, 250, 207, 252, 197, 217, 139, 118, 245, 91, 236, 66, 208, 138, 154, 75, 107, 109, 151, 202, 68, 240, 212, 67, 20, 99, 109, 248, 139, 224, 206, 84, 152, 224, 170, 51, 137, 117, 64, 222, 91, 239, 71, 72, 162, 247, 243, 187, 164, 53, 123, 99, 186, 208, 39, 12, 160, 61, 78, 19, 205, 15, 250, 185, 238, 102, 144, 146, 127, 94, 250, 121, 240, 122, 240, 156, 182, 119, 143, 16, 120, 138, 161, 170, 79, 93, 169, 100, 149, 168, 76, 173, 8, 163, 172, 89, 153, 86, 73, 117, 100, 123, 115, 69, 135, 50, 29, 33, 66, 82, 71, 118, 231, 185, 151, 133, 179, 56, 251, 225, 76, 36, 189, 43, 39, 202, 168, 46, 25, 181, 127, 109, 78, 121, 80, 82, 137, 32, 196, 116, 100, 197, 0, 222, 88, 92, 165, 89, 146, 146, 239, 137, 28, 164, 44, 27, 162, 74, 37, 195, 54, 78, 18, 210, 106, 39, 162, 157, 145, 228, 70, 101, 195, 128, 222, 235, 117, 238, 29, 11, 180, 80, 104, 240, 118, 44, 231, 98, 239, 211, 64, 167, 59, 209, 26, 103, 168, 95, 187, 243, 178, 55, 31, 26, 230, 135, 67, 205, 232, 23, 89, 177, 223, 32, 105, 80, 186, 195, 82, 86, 144, 216, 110, 222, 223, 91, 20, 100, 73, 139, 128, 153, 150, 210, 140, 18, 197, 42, 121, 160, 77, 194, 37, 252, 68, 94, 32, 28, 245, 145, 29, 232, 182, 213, 246, 68, 175, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 121, 31, 55, 196, 109, 33, 122, 128, 32, 212, 84, 89, 7, 193, 97, 193, 144, 148, 24, 59, 4, 20, 161, 35, 154, 3, 112, 148, 126, 41, 44, 75, 51, 43, 182, 209, 49, 49, 210, 122, 30, 103, 2, 2, 7, 208 }; - public X509Certificate2 certificate1 = new X509Certificate2(certificateRawBytes1, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet); - public X509Certificate2 certificate2 = new X509Certificate2(certificateRawBytes2, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet); - public X509Certificate2 certificate3 = new X509Certificate2(certificateRawBytes3, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet); - public CertificateFixture() - { - AddCertificateToStore(certificate1, StoreLocation.CurrentUser); - AddCertificateToStore(certificate2, StoreLocation.CurrentUser); - AddCertificateToStore(certificate3, StoreLocation.CurrentUser); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsAdmin) - { - AddCertificateToStore(certificate3, StoreLocation.LocalMachine); - } - } - - public void Dispose() - { - // Do Not remove Certificates to provide concurrency support - // RemoveCertificate(certificate1, StoreLocation.CurrentUser); - // RemoveCertificate(certificate2, StoreLocation.CurrentUser); - } - - public static void AddCertificateToStore(X509Certificate2 certificate, StoreLocation certificateStoreLocation) - { - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, certificateStoreLocation); - certStore.Open(OpenFlags.ReadWrite); - if (!certStore.Certificates.Contains(certificate)) - { - certStore.Add(certificate); - } - - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - } - - public static void RemoveCertificate(X509Certificate2 certificate, StoreLocation certificateStoreLocation) - { - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, certificateStoreLocation); - certStore.Open(OpenFlags.ReadWrite); - certStore.Remove(certificate); - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - } } } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs index ae7d860a42..eb37d9e4e5 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs @@ -203,55 +203,6 @@ internal static X509Certificate2 CreateCertificate() return certificate; } - /// - /// Gets the certificate. - /// - /// - /// - /// - internal static X509Certificate2 GetCertificate(string certificateName, StoreLocation certificateStoreLocation) - { - Assert.True(!string.IsNullOrWhiteSpace(certificateName)); - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, certificateStoreLocation); - certStore.Open(OpenFlags.ReadOnly); - X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindBySubjectName, certificateName, validOnly: false); - Assert.True(certCollection != null && certCollection.Count > 0); - - return certCollection[0]; - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - } - - /// - /// Removes a certificate from the local certificate store (useful for test cleanup). - /// - internal static void RemoveCertificate(X509Certificate2 certificate) - { - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); - certStore.Open(OpenFlags.ReadWrite); - certStore.Remove(certificate); - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - } - /// /// Encrypt Data using AED /// diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs index b05ea370e3..4c0f3599a2 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs @@ -31,23 +31,29 @@ public CertificateStoreContext(StoreLocation location, StoreName name) private readonly List _certificateStoreModifications = new List(); - protected static X509Certificate CreateCertificate(string subjectName, IEnumerable dnsNames, IEnumerable ipAddresses) + protected static X509Certificate2 CreateCertificate(string subjectName, IEnumerable dnsNames, IEnumerable ipAddresses) { // This will always generate a certificate with: // * Start date: 24hrs ago // * End date: 24hrs in the future // * Subject: {subjectName} // * Subject alternative names: {dnsNames}, {ipAddresses} - // * Public key: 4096-bit RSA + // * Public key: 2048-bit RSA // * Hash algorithm: SHA256 // * Key usage: digital signature, key encipherment // * Enhanced key usage: server authentication, client authentication DateTimeOffset notBefore = DateTimeOffset.UtcNow.AddDays(-1); DateTimeOffset notAfter = DateTimeOffset.UtcNow.AddDays(1); + byte[] passwordBytes = new byte[32]; + string password = null; + Random rnd = new Random(); + + rnd.NextBytes(passwordBytes); + password = Convert.ToBase64String(passwordBytes); #if NET X500DistinguishedNameBuilder subjectBuilder = new X500DistinguishedNameBuilder(); SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); - RSA rsaKey = RSA.Create(4096); + RSA rsaKey = RSA.Create(2048); bool hasSans = false; subjectBuilder.AddCommonName(subjectName); @@ -73,7 +79,13 @@ protected static X509Certificate CreateCertificate(string subjectName, IEnumerab request.CertificateExtensions.Add(sanBuilder.Build()); } - return request.CreateSelfSigned(notBefore, notAfter); + // Generate an ephemeral certificate, then export it and return it as a new certificate with the correct key storage flags set. + // This is to ensure that it's imported into the certificate stores with its private key. + using (X509Certificate2 ephemeral = request.CreateSelfSigned(notBefore, notAfter)) + { + return new X509Certificate2(ephemeral.Export(X509ContentType.Pkcs12, password), password, + X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + } #else // The CertificateRequest API is available in .NET Core, but was only added to .NET Framework 4.7.2; it thus can't be used in the test projects. // Instead, fall back to running a PowerShell script which calls New-SelfSignedCertificate. This cmdlet also adds the certificate to a specific, @@ -87,7 +99,7 @@ protected static X509Certificate CreateCertificate(string subjectName, IEnumerab try {{ - $x509 = New-SelfSignedCertificate -Subject $subject -TextExtension $sAN -KeyLength 4096 -KeyAlgorithm RSA ` + $x509 = New-SelfSignedCertificate -Subject $subject -TextExtension $sAN -KeyLength 2048 -KeyAlgorithm RSA ` -CertStoreLocation ""Cert:\CurrentUser\My"" -NotBefore $notBefore -NotAfter $notAfter ` -KeyExportPolicy Exportable -HashAlgorithm SHA256 @@ -111,9 +123,6 @@ exit 1 string sanString = string.Empty; bool hasSans = false; string formattedCommand = null; - byte[] passwordBytes = new byte[32]; - string password = null; - Random rnd = new Random(); string commandOutput = null; foreach (string dnsName in dnsNames) @@ -129,8 +138,6 @@ exit 1 sanString = hasSans ? "\"2.5.29.17={text}" + sanString.Substring(0, sanString.Length - 1) + "\"" : string.Empty; - rnd.NextBytes(passwordBytes); - password = Convert.ToBase64String(passwordBytes); formattedCommand = string.Format(PowerShellCommandTemplate, notBefore.ToString("O"), notAfter.ToString("O"), subjectName, sanString, password); using (Process psProcess = new Process() diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs new file mode 100644 index 0000000000..b0511b1d09 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs @@ -0,0 +1,51 @@ +// 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; +using System.Security.Cryptography.X509Certificates; +using System.Security.Principal; + +namespace Microsoft.Data.SqlClient.TestUtilities.Fixtures +{ + public sealed class ColumnEncryptionCertificateFixture : CertificateFixtureBase + { + public X509Certificate2 PrimaryColumnEncryptionCertificate { get; } + + public X509Certificate2 SecondaryColumnEncryptionCertificate { get; } + + private readonly X509Certificate2 _currentUserCertificate; + private readonly X509Certificate2 _localMachineCertificate; + + public ColumnEncryptionCertificateFixture() + { + PrimaryColumnEncryptionCertificate = CreateCertificate(nameof(PrimaryColumnEncryptionCertificate), Array.Empty(), Array.Empty()); + SecondaryColumnEncryptionCertificate = CreateCertificate(nameof(SecondaryColumnEncryptionCertificate), Array.Empty(), Array.Empty()); + _currentUserCertificate = CreateCertificate(nameof(_currentUserCertificate), Array.Empty(), Array.Empty()); + + AddToStore(PrimaryColumnEncryptionCertificate, StoreLocation.CurrentUser, StoreName.My); + AddToStore(SecondaryColumnEncryptionCertificate, StoreLocation.CurrentUser, StoreName.My); + AddToStore(_currentUserCertificate, StoreLocation.CurrentUser, StoreName.My); + + if (IsAdmin) + { + _localMachineCertificate = CreateCertificate(nameof(_localMachineCertificate), Array.Empty(), Array.Empty()); + + AddToStore(_localMachineCertificate, StoreLocation.LocalMachine, StoreName.My); + } + } + + public X509Certificate2 GetCertificate(StoreLocation storeLocation) + { + return storeLocation == StoreLocation.CurrentUser + ? _currentUserCertificate + : storeLocation == StoreLocation.LocalMachine && IsAdmin + ? _localMachineCertificate + : throw new InvalidOperationException("Attempted to retrieve the certificate added to the local machine store; this requires administrator rights."); + } + + public static bool IsAdmin + => Environment.OSVersion.Platform == PlatformID.Win32NT + && new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); + } +} From 6ac9c53da754db3fa4363ae057805567c04630ca Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:18:22 +0000 Subject: [PATCH 4/9] Cleanup: ExceptionsCertStore This test class covered similar ground to the existing SqlColumnEncryptionCertificateStoreProviderShould test class. --- .../ExceptionsCertStore.cs | 104 ------------------ ...ncryptionCertificateStoreProviderShould.cs | 17 ++- .../AlwaysEncryptedTests/Utility.cs | 31 ------ .../Microsoft.Data.SqlClient.Tests.csproj | 1 - .../ColumnEncryptionCertificateFixture.cs | 9 ++ 5 files changed, 23 insertions(+), 139 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs deleted file mode 100644 index 30f4528d23..0000000000 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs +++ /dev/null @@ -1,104 +0,0 @@ -// 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; -using System.Security.Cryptography.X509Certificates; -using Xunit; - -namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests -{ - public class ExceptionsCertStore : IClassFixture - { - private readonly string masterKeyEncAlgo = "RSA_OAEP"; - - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public void EmptyCertificateThumbprint() - { - string dummyPath = string.Format("CurrentUser/My/"); - string expectedMessage = string.Format(@"Empty certificate thumbprint specified in certificate path '{0}'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", dummyPath); - - ArgumentException e = Assert.Throws(() => ExceptionCertFixture.certStoreProvider.EncryptColumnEncryptionKey(dummyPath, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Matches(expectedMessage, e.Message); - - expectedMessage = string.Format(@"Internal error. Empty certificate thumbprint specified in certificate path '{0}'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", dummyPath); - e = Assert.Throws(() => ExceptionCertFixture.certStoreProvider.DecryptColumnEncryptionKey(dummyPath, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Matches(expectedMessage, e.Message); - } - - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public void CertificateNotFound() - { - string dummyPath = string.Format("CurrentUser/My/JunkThumbprint"); - string expectedMessage = string.Format(@"Certificate with thumbprint 'JunkThumbprint' not found in certificate store 'My' in certificate location 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"); - ArgumentException e = Assert.Throws(() => ExceptionCertFixture.certStoreProvider.EncryptColumnEncryptionKey(dummyPath, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Matches(expectedMessage, e.Message); - - expectedMessage = string.Format(@"Certificate with thumbprint 'JunkThumbprint' not found in certificate store 'My' in certificate location 'CurrentUser'. Verify the certificate path in the column master key definition in the database is correct, and the certificate has been imported correctly into the certificate location/store.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"); - e = Assert.Throws(() => ExceptionCertFixture.certStoreProvider.DecryptColumnEncryptionKey(dummyPath, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Matches(expectedMessage, e.Message); - } - -#if NETFRAMEWORK - [Fact] - [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp)] - public void CertificateWithNoPrivateKey() - { - string expectedMessage = string.Format("Certificate specified in key path '{0}' does not have a private key to encrypt a column encryption key. Verify the certificate is imported correctly.\r\nParameter name: masterKeyPath", ExceptionCertFixture.masterKeyPathNPK); - ArgumentException e = Assert.Throws(() => - ExceptionCertFixture.certStoreProvider.EncryptColumnEncryptionKey( - ExceptionCertFixture.masterKeyPathNPK, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Contains(expectedMessage, e.Message); - - expectedMessage = string.Format("Certificate specified in key path '{0}' does not have a private key to decrypt a column encryption key. Verify the certificate is imported correctly.\r\nParameter name: masterKeyPath", ExceptionCertFixture.masterKeyPathNPK); - e = Assert.Throws(() => - ExceptionCertFixture.certStoreProvider.DecryptColumnEncryptionKey( - ExceptionCertFixture.masterKeyPathNPK, masterKeyEncAlgo, ExceptionCertFixture.encryptedCek)); - Assert.Contains(expectedMessage, e.Message); - } -#endif - } - public class ExceptionCertFixture : IDisposable - { - public static readonly SqlColumnEncryptionCertificateStoreProvider certStoreProvider = new SqlColumnEncryptionCertificateStoreProvider(); - public static X509Certificate2 certificate; - public static string certificatePath; - public static string thumbprint; - public static byte[] cek; - public static byte[] encryptedCek; -#if NETFRAMEWORK - public static X509Certificate2 masterKeyCertificateNPK; // no private key - public static string thumbprintNPK; // No private key - public static string masterKeyPathNPK; -#endif - - public ExceptionCertFixture() - { - if(certificate == null) - { - certificate = Utility.CreateCertificate(); - } - thumbprint = certificate.Thumbprint; - certificatePath = string.Format("CurrentUser/My/{0}", thumbprint); - cek = Utility.GenerateRandomBytes(32); - encryptedCek = certStoreProvider.EncryptColumnEncryptionKey(certificatePath, "RSA_OAEP", cek); -#if NETFRAMEWORK - if (masterKeyCertificateNPK == null) - { - masterKeyCertificateNPK = Utility.CreateCertificateWithNoPrivateKey(); - } - thumbprintNPK = masterKeyCertificateNPK.Thumbprint; - masterKeyPathNPK = "CurrentUser/My/" + thumbprintNPK; -#endif - // Disable the cache to avoid false failures. - SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; - } - - public void Dispose() - { - // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well. - } - } -} diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs index b7ff289a19..8500a1c536 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs @@ -101,6 +101,9 @@ public class SqlColumnEncryptionCertificateStoreProviderWindowsShould public SqlColumnEncryptionCertificateStoreProviderWindowsShould(ColumnEncryptionCertificateFixture certFixture) { _certFixture = certFixture; + + // Disable the cache to avoid false failures. + SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; } [Theory] @@ -121,7 +124,7 @@ public void ThrowExceptionWithInvalidParameterWhileEncryptingColumnEncryptionKey { var provider = new SqlColumnEncryptionCertificateStoreProvider(); Exception ex = Assert.Throws(exceptionType, () => provider.EncryptColumnEncryptionKey(ReplaceKeyTokens(masterKeyPath), encryptionAlgorithm, bytes)); - Assert.Matches(errorMsg, ex.Message); + Assert.Matches(ReplaceKeyTokens(errorMsg), ex.Message); } [Theory] @@ -468,7 +471,8 @@ public void TestEncryptedCellValueTampering(string parameterToTamper, Utility.CC private string ReplaceKeyTokens(string keyPath) { return keyPath?.Replace("{primary_thumbprint}", _certFixture.PrimaryColumnEncryptionCertificate.Thumbprint) - ?.Replace("{secondary_thumbprint}", _certFixture.SecondaryColumnEncryptionCertificate.Thumbprint); + ?.Replace("{secondary_thumbprint}", _certFixture.SecondaryColumnEncryptionCertificate.Thumbprint) + ?.Replace("{npk_thumbprint}", _certFixture.CertificateWithoutPrivateKey.Thumbprint); } public class AeadEncryptionParameters : DataAttribute @@ -544,13 +548,14 @@ public class InvalidDecryptionParameters : DataAttribute private const string TCE_InvalidCertificatePath = @"Internal error. Invalid certificate path: 'CurrentUser/My/Thumbprint/extra'. Use the following format: //, where is either 'LocalMachine' or 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateLocation = @"Internal error. Invalid certificate location 'Invalid' in certificate path 'Invalid/My/Thumbprint'. Use the following format: //, where is either 'LocalMachine' or 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateStore = @"Internal error. Invalid certificate store 'Invalid' specified in certificate path 'CurrentUser/Invalid/Thumbprint'. Expected value: 'My'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + private const string TCE_CertificateNotFound = @"Certificate with thumbprint 'JunkThumbprint' not found in certificate store 'My' in certificate location 'CurrentUser'. Verify the certificate path in the column master key definition in the database is correct, and the certificate has been imported correctly into the certificate location/store.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + private const string TCE_CertificateWithNoPrivateKey = @"Certificate specified in key path 'CurrentUser/My/{npk_thumbprint}' does not have a private key to decrypt a column encryption key. Verify the certificate is imported correctly.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateSignature = @"Internal error. Empty certificate thumbprint specified in certificate path 'CurrentUser/My/'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidAlgorithmVersion = @"Specified encrypted column encryption key contains an invalid encryption algorithm version '02'. Expected version is '01'.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; private const string TCE_InvalidCiphertextLengthInEncryptedCEK = @"The specified encrypted column encryption key's ciphertext length: 128 does not match the ciphertext length: 256 when using column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; private const string TCE_InvalidSignatureInEncryptedCEK = @"The specified encrypted column encryption key's signature length: 128 does not match the signature length: 256 when using column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified certificate path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; private const string TCE_InvalidSignature = @"The specified encrypted column encryption key signature does not match the signature computed with the column master key \(certificate\) in 'CurrentUser/My/{primary_thumbprint}'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - public override IEnumerable GetData(MethodInfo testMethod) { yield return new Object[] { TCE_NullCertificatePath, typeof(ArgumentNullException), null, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; @@ -563,6 +568,8 @@ public override IEnumerable GetData(MethodInfo testMethod) yield return new Object[] { TCE_InvalidCertificatePath, typeof(ArgumentException), "CurrentUser/My/Thumbprint/extra", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateLocation, typeof(ArgumentException), "Invalid/My/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateStore, typeof(ArgumentException), "CurrentUser/Invalid/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_CertificateNotFound, typeof(ArgumentException), "CurrentUser/My/JunkThumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_CertificateWithNoPrivateKey, typeof(ArgumentException), "CurrentUser/My/{npk_thumbprint}", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateSignature, typeof(ArgumentException), "CurrentUser/My/", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidAlgorithmVersion, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(2, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCiphertextLengthInEncryptedCEK, typeof(ArgumentException), PRIMARY_CERTIFICATE_PATH, ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 128, 256) }; @@ -583,6 +590,8 @@ public class InvalidEncryptionParameters : DataAttribute private const string TCE_InvalidCertificatePath = @"Invalid certificate path: 'CurrentUser/My/Thumbprint/extra'. Use the following format: //, where is either 'LocalMachine' or 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateLocation = @"Invalid certificate location 'Invalid' in certificate path 'Invalid/My/Thumbprint'. Use the following format: //, where is either 'LocalMachine' or 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateStore = @"Invalid certificate store 'Invalid' specified in certificate path 'CurrentUser/Invalid/Thumbprint'. Expected value: 'My'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + private const string TCE_CertificateNotFound = @"Certificate with thumbprint 'JunkThumbprint' not found in certificate store 'My' in certificate location 'CurrentUser'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + private const string TCE_CertificateWithNoPrivateKey = @"Certificate specified in key path 'CurrentUser/My/{npk_thumbprint}' does not have a private key to encrypt a column encryption key. Verify the certificate is imported correctly.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; private const string TCE_InvalidCertificateSignature = @"Empty certificate thumbprint specified in certificate path 'CurrentUser/My/'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; public override IEnumerable GetData(MethodInfo testMethod) @@ -597,6 +606,8 @@ public override IEnumerable GetData(MethodInfo testMethod) yield return new Object[] { TCE_InvalidCertificatePath, typeof(ArgumentException), "CurrentUser/My/Thumbprint/extra", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateLocation, typeof(ArgumentException), "Invalid/My/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateStore, typeof(ArgumentException), "CurrentUser/Invalid/Thumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_CertificateNotFound, typeof(ArgumentException), "CurrentUser/My/JunkThumbprint", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; + yield return new Object[] { TCE_CertificateWithNoPrivateKey, typeof(ArgumentException), "CurrentUser/My/{npk_thumbprint}", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; yield return new Object[] { TCE_InvalidCertificateSignature, typeof(ArgumentException), "CurrentUser/My/", ENCRYPTION_ALGORITHM, GenerateTestEncryptedBytes(1, 0, 256, 256) }; } } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs index eb37d9e4e5..7b307248a6 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs @@ -301,37 +301,6 @@ internal static byte[] DecryptDataUsingAED(byte[] encryptedCellBlob, byte[] key, return decryptedData; } -#if NETFRAMEWORK - /// - /// Create a self-signed certificate without private key. - /// - internal static X509Certificate2 CreateCertificateWithNoPrivateKey() - { - byte[] certificateRawBytes = new byte[] { 48, 130, 10, 44, 2, 1, 3, 48, 130, 9, 232, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 9, 217, 4, 130, 9, 213, 48, 130, 9, 209, 48, 130, 5, 250, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 235, 4, 130, 5, 231, 48, 130, 5, 227, 48, 130, 5, 223, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 4, 254, 48, 130, 4, 250, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 235, 104, 8, 192, 48, 172, 84, 29, 2, 2, 7, 208, 4, 130, 4, 216, 223, 187, 54, 199, 219, 97, 167, 152, 236, 137, 175, 54, 77, 8, 247, 205, 172, 76, 84, 103, 8, 28, 176, 175, 188, 108, 135, 239, 218, 134, 129, 181, 251, 107, 39, 184, 253, 101, 94, 26, 232, 8, 233, 161, 112, 129, 228, 7, 130, 121, 197, 85, 170, 39, 8, 195, 112, 127, 125, 148, 97, 162, 52, 74, 56, 187, 228, 232, 17, 145, 186, 138, 140, 245, 76, 203, 154, 41, 148, 15, 86, 152, 239, 221, 3, 64, 158, 137, 250, 33, 11, 23, 49, 250, 50, 116, 183, 138, 223, 230, 8, 210, 52, 95, 6, 238, 167, 153, 107, 99, 214, 58, 56, 70, 135, 6, 173, 190, 175, 116, 23, 53, 250, 166, 192, 128, 93, 243, 109, 60, 55, 10, 246, 188, 43, 56, 157, 116, 22, 105, 215, 194, 58, 229, 28, 93, 175, 65, 64, 162, 237, 182, 40, 159, 140, 24, 3, 226, 63, 246, 201, 144, 40, 128, 122, 15, 188, 130, 195, 120, 65, 191, 10, 164, 29, 119, 17, 60, 231, 63, 26, 172, 87, 191, 110, 233, 107, 44, 206, 197, 170, 176, 12, 6, 44, 181, 219, 56, 45, 10, 75, 145, 154, 148, 162, 169, 240, 109, 254, 115, 33, 81, 206, 88, 33, 91, 251, 235, 56, 56, 41, 75, 145, 36, 177, 104, 68, 7, 76, 150, 230, 182, 136, 239, 10, 21, 3, 10, 23, 217, 103, 148, 160, 114, 55, 122, 22, 165, 91, 37, 230, 23, 28, 182, 107, 31, 53, 78, 226, 125, 17, 81, 223, 48, 36, 51, 101, 19, 79, 202, 221, 197, 11, 152, 253, 155, 142, 63, 107, 51, 11, 197, 55, 18, 8, 109, 173, 83, 125, 201, 167, 170, 152, 152, 26, 142, 29, 77, 174, 189, 241, 185, 239, 56, 207, 128, 203, 136, 203, 226, 29, 88, 97, 230, 119, 161, 6, 15, 231, 9, 250, 96, 129, 40, 35, 201, 28, 220, 237, 24, 88, 88, 222, 239, 108, 39, 35, 147, 76, 242, 209, 122, 4, 165, 91, 18, 78, 74, 40, 131, 194, 1, 105, 104, 103, 207, 198, 222, 100, 2, 188, 130, 224, 187, 243, 170, 192, 0, 169, 69, 155, 32, 48, 159, 164, 254, 29, 255, 197, 250, 118, 69, 2, 11, 47, 232, 157, 151, 17, 106, 211, 82, 15, 246, 22, 117, 90, 220, 129, 228, 91, 249, 18, 147, 125, 13, 51, 98, 235, 213, 145, 81, 77, 139, 23, 50, 35, 165, 13, 117, 71, 82, 166, 120, 103, 121, 72, 229, 3, 116, 65, 90, 125, 224, 121, 19, 136, 215, 57, 73, 247, 249, 174, 197, 234, 13, 58, 182, 24, 46, 21, 122, 193, 111, 47, 40, 207, 75, 224, 155, 163, 138, 130, 38, 204, 211, 149, 132, 249, 37, 66, 194, 83, 147, 6, 187, 113, 60, 129, 139, 197, 84, 60, 179, 253, 192, 124, 67, 60, 29, 149, 244, 114, 238, 71, 144, 139, 0, 104, 29, 100, 90, 137, 151, 31, 138, 3, 35, 96, 243, 130, 203, 200, 191, 212, 247, 137, 194, 183, 150, 53, 213, 108, 9, 30, 18, 204, 248, 30, 60, 132, 25, 12, 186, 64, 179, 130, 165, 141, 77, 4, 244, 166, 0, 197, 145, 66, 51, 17, 198, 181, 54, 63, 112, 195, 70, 11, 93, 122, 175, 136, 8, 156, 136, 165, 228, 22, 105, 107, 87, 160, 1, 140, 134, 166, 151, 91, 76, 15, 187, 197, 131, 67, 5, 51, 191, 23, 4, 105, 219, 167, 45, 167, 3, 118, 161, 54, 187, 250, 136, 201, 233, 148, 234, 228, 65, 18, 105, 92, 201, 5, 100, 213, 59, 97, 29, 163, 42, 50, 5, 59, 178, 122, 190, 159, 218, 10, 239, 183, 20, 226, 197, 187, 190, 160, 5, 122, 45, 70, 111, 205, 232, 160, 115, 145, 173, 255, 60, 105, 204, 253, 18, 212, 167, 23, 95, 10, 146, 175, 0, 137, 166, 220, 51, 203, 244, 13, 27, 51, 121, 159, 178, 20, 178, 43, 133, 182, 169, 234, 56, 205, 153, 170, 26, 138, 48, 84, 2, 20, 11, 141, 41, 76, 178, 76, 10, 30, 9, 242, 158, 59, 9, 109, 240, 185, 30, 199, 136, 167, 146, 202, 239, 253, 95, 61, 56, 16, 166, 163, 78, 75, 241, 228, 98, 198, 59, 113, 214, 77, 58, 177, 251, 132, 167, 137, 82, 119, 216, 157, 8, 37, 95, 43, 106, 140, 117, 166, 0, 111, 84, 45, 43, 22, 220, 109, 219, 30, 165, 252, 91, 3, 203, 165, 91, 22, 202, 91, 223, 194, 122, 238, 159, 25, 1, 254, 183, 4, 7, 96, 150, 253, 199, 92, 250, 143, 107, 77, 112, 133, 202, 126, 117, 128, 59, 124, 111, 174, 41, 92, 184, 247, 248, 44, 43, 148, 37, 193, 30, 110, 34, 190, 210, 37, 230, 182, 113, 130, 3, 65, 85, 90, 60, 0, 177, 78, 95, 251, 111, 91, 12, 27, 111, 119, 74, 117, 81, 162, 174, 33, 110, 63, 242, 31, 24, 11, 186, 174, 80, 52, 76, 184, 42, 199, 203, 245, 75, 97, 104, 12, 206, 133, 206, 36, 30, 105, 254, 233, 145, 29, 224, 62, 139, 143, 168, 181, 142, 247, 139, 240, 2, 220, 57, 221, 62, 133, 90, 209, 106, 69, 82, 89, 172, 134, 230, 129, 154, 88, 35, 126, 16, 43, 107, 12, 76, 67, 116, 66, 181, 251, 73, 157, 31, 196, 240, 237, 184, 92, 126, 182, 46, 66, 91, 56, 37, 75, 235, 200, 90, 129, 103, 80, 73, 246, 156, 160, 169, 212, 3, 57, 238, 17, 6, 244, 219, 106, 112, 96, 80, 204, 181, 173, 82, 238, 24, 36, 232, 84, 158, 135, 211, 35, 133, 141, 46, 48, 179, 174, 127, 34, 44, 45, 193, 241, 222, 10, 175, 76, 64, 39, 191, 63, 182, 25, 39, 105, 61, 35, 162, 89, 253, 189, 59, 159, 225, 142, 174, 166, 5, 56, 253, 106, 170, 190, 136, 207, 37, 233, 54, 131, 111, 118, 198, 83, 52, 86, 102, 14, 38, 26, 181, 42, 175, 131, 116, 0, 82, 25, 96, 191, 188, 196, 158, 132, 25, 0, 160, 125, 188, 236, 71, 221, 58, 71, 247, 35, 85, 68, 183, 64, 119, 247, 159, 185, 240, 9, 230, 184, 43, 116, 163, 91, 67, 244, 33, 243, 210, 190, 86, 127, 14, 38, 60, 19, 211, 182, 96, 77, 86, 116, 159, 173, 134, 39, 217, 77, 131, 85, 126, 145, 224, 120, 94, 233, 103, 254, 14, 92, 242, 69, 17, 17, 63, 94, 251, 195, 199, 194, 175, 94, 137, 82, 25, 234, 253, 89, 225, 46, 103, 131, 109, 12, 204, 188, 141, 173, 146, 124, 221, 144, 235, 188, 165, 141, 95, 224, 56, 58, 53, 149, 94, 77, 204, 101, 195, 127, 8, 86, 122, 190, 7, 214, 60, 154, 222, 229, 101, 12, 73, 149, 216, 6, 124, 223, 165, 65, 197, 217, 61, 174, 172, 84, 179, 169, 153, 116, 47, 176, 76, 119, 232, 236, 44, 82, 146, 241, 136, 223, 251, 249, 12, 40, 216, 133, 54, 145, 43, 43, 135, 238, 2, 212, 216, 242, 118, 199, 195, 221, 16, 46, 29, 4, 95, 66, 58, 168, 47, 0, 11, 161, 15, 104, 189, 76, 245, 195, 254, 129, 123, 98, 1, 127, 230, 47, 171, 184, 87, 192, 241, 169, 219, 49, 129, 205, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 74, 30, 72, 0, 48, 0, 55, 0, 101, 0, 97, 0, 50, 0, 102, 0, 48, 0, 54, 0, 45, 0, 53, 0, 48, 0, 99, 0, 55, 0, 45, 0, 52, 0, 55, 0, 50, 0, 57, 0, 45, 0, 98, 0, 48, 0, 53, 0, 100, 0, 45, 0, 101, 0, 54, 0, 49, 0, 52, 0, 50, 0, 54, 0, 56, 0, 97, 0, 57, 0, 51, 0, 54, 0, 49, 48, 93, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 80, 30, 78, 0, 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 83, 0, 116, 0, 114, 0, 111, 0, 110, 0, 103, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 3, 207, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 3, 192, 48, 130, 3, 188, 2, 1, 0, 48, 130, 3, 181, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 37, 194, 101, 21, 13, 36, 244, 253, 2, 2, 7, 208, 128, 130, 3, 136, 10, 38, 67, 113, 151, 160, 181, 156, 252, 50, 128, 39, 35, 98, 152, 133, 235, 238, 94, 73, 70, 252, 148, 94, 227, 150, 143, 176, 164, 232, 41, 137, 239, 196, 102, 6, 78, 134, 9, 254, 13, 200, 191, 171, 47, 166, 148, 30, 196, 230, 95, 126, 29, 42, 214, 201, 165, 49, 93, 149, 12, 7, 79, 167, 112, 237, 36, 142, 123, 246, 14, 212, 16, 78, 179, 106, 60, 251, 106, 13, 232, 222, 214, 255, 212, 48, 140, 91, 26, 201, 136, 119, 148, 0, 246, 63, 252, 9, 41, 63, 147, 198, 201, 26, 134, 126, 59, 103, 212, 103, 101, 47, 138, 137, 237, 190, 83, 123, 231, 194, 213, 147, 117, 116, 148, 170, 194, 12, 62, 100, 16, 254, 76, 65, 96, 126, 45, 221, 126, 161, 233, 194, 187, 117, 13, 201, 85, 26, 223, 13, 143, 147, 250, 64, 5, 85, 232, 165, 154, 77, 255, 192, 31, 166, 154, 251, 192, 199, 100, 220, 4, 79, 242, 191, 66, 134, 203, 50, 2, 105, 98, 247, 73, 66, 41, 179, 173, 177, 217, 196, 180, 48, 219, 79, 88, 154, 40, 249, 150, 169, 231, 215, 186, 61, 129, 223, 57, 84, 48, 245, 158, 161, 89, 204, 127, 155, 134, 155, 158, 208, 159, 245, 83, 5, 63, 188, 233, 164, 60, 38, 91, 255, 221, 6, 28, 107, 85, 188, 81, 114, 23, 143, 4, 78, 17, 178, 36, 44, 209, 7, 251, 78, 13, 35, 73, 243, 151, 150, 122, 161, 86, 52, 233, 148, 241, 144, 175, 230, 22, 97, 21, 229, 143, 172, 67, 12, 130, 254, 4, 144, 136, 20, 93, 161, 177, 249, 160, 58, 18, 135, 249, 107, 142, 116, 63, 228, 37, 105, 81, 121, 43, 107, 88, 166, 7, 59, 42, 139, 76, 71, 191, 137, 102, 185, 95, 166, 229, 23, 110, 123, 49, 239, 48, 183, 246, 102, 120, 28, 25, 39, 211, 183, 1, 201, 199, 158, 143, 25, 1, 165, 163, 99, 161, 237, 235, 148, 209, 180, 152, 111, 128, 40, 102, 90, 5, 228, 15, 244, 148, 33, 110, 153, 4, 159, 28, 241, 252, 117, 69, 165, 37, 129, 227, 151, 31, 191, 105, 106, 179, 87, 41, 37, 63, 18, 59, 198, 182, 91, 21, 41, 242, 237, 63, 240, 163, 110, 219, 94, 119, 28, 234, 70, 208, 56, 141, 163, 80, 4, 223, 110, 64, 161, 81, 82, 191, 67, 13, 95, 208, 122, 152, 8, 87, 197, 31, 141, 22, 161, 23, 211, 83, 222, 116, 234, 57, 228, 203, 122, 87, 146, 161, 167, 87, 126, 181, 34, 85, 90, 190, 30, 253, 188, 207, 205, 203, 11, 248, 56, 202, 107, 28, 106, 8, 247, 65, 91, 12, 123, 2, 252, 134, 153, 88, 146, 154, 99, 116, 103, 196, 40, 212, 197, 79, 63, 1, 241, 152, 35, 34, 84, 217, 128, 56, 0, 139, 218, 77, 22, 63, 120, 204, 192, 144, 152, 127, 60, 84, 143, 30, 203, 24, 78, 44, 24, 194, 71, 139, 34, 203, 212, 4, 216, 128, 29, 158, 142, 82, 147, 165, 250, 107, 222, 76, 152, 120, 21, 236, 240, 18, 167, 99, 97, 31, 104, 3, 134, 222, 185, 129, 130, 214, 90, 200, 254, 51, 86, 225, 209, 2, 224, 32, 38, 218, 77, 156, 102, 9, 158, 232, 155, 239, 33, 76, 222, 93, 105, 50, 72, 175, 220, 219, 17, 58, 147, 86, 107, 144, 35, 191, 186, 197, 218, 74, 71, 154, 117, 192, 247, 43, 176, 141, 82, 95, 21, 245, 199, 194, 20, 204, 111, 141, 183, 50, 22, 155, 54, 47, 164, 247, 33, 110, 208, 216, 123, 141, 209, 182, 101, 100, 140, 162, 83, 12, 12, 196, 113, 61, 119, 254, 184, 94, 78, 66, 72, 239, 124, 123, 48, 101, 162, 225, 175, 235, 100, 97, 71, 192, 254, 7, 234, 235, 94, 38, 241, 159, 96, 208, 128, 93, 68, 24, 69, 62, 236, 128, 155, 9, 56, 163, 236, 112, 90, 118, 11, 97, 33, 216, 89, 24, 127, 35, 5, 33, 103, 35, 27, 182, 249, 222, 74, 44, 243, 185, 177, 97, 145, 55, 113, 57, 186, 104, 128, 158, 1, 27, 182, 134, 158, 198, 228, 122, 149, 27, 185, 181, 248, 4, 98, 35, 113, 190, 228, 37, 84, 50, 250, 197, 180, 22, 103, 231, 136, 157, 96, 109, 205, 98, 195, 5, 146, 122, 238, 143, 155, 9, 245, 188, 30, 103, 55, 77, 1, 152, 207, 166, 218, 93, 237, 66, 182, 168, 31, 61, 111, 223, 189, 129, 118, 204, 121, 213, 212, 158, 159, 146, 227, 16, 63, 15, 25, 114, 72, 243, 3, 112, 217, 85, 194, 233, 211, 154, 178, 223, 170, 210, 215, 151, 146, 76, 212, 251, 234, 136, 23, 22, 156, 135, 40, 174, 163, 211, 154, 205, 237, 225, 86, 207, 195, 154, 170, 213, 33, 227, 75, 216, 234, 208, 159, 157, 48, 193, 243, 57, 79, 40, 187, 12, 147, 134, 150, 43, 169, 156, 208, 162, 94, 28, 192, 139, 133, 6, 112, 17, 245, 56, 161, 19, 254, 220, 63, 9, 58, 90, 144, 194, 186, 220, 166, 125, 179, 149, 46, 9, 18, 62, 244, 56, 232, 171, 16, 210, 106, 149, 170, 49, 173, 44, 50, 80, 108, 61, 151, 199, 86, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 171, 133, 31, 192, 88, 19, 36, 185, 245, 48, 81, 100, 39, 120, 104, 220, 55, 66, 79, 62, 4, 20, 87, 234, 127, 133, 228, 52, 169, 111, 27, 106, 183, 211, 251, 229, 188, 99, 150, 210, 181, 175, 2, 2, 7, 208 }; - X509Certificate2 certificate = new X509Certificate2(certificateRawBytes, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet); - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); - certStore.Open(OpenFlags.ReadWrite); - certificate.PrivateKey = null; - if (!certStore.Certificates.Contains(certificate)) - { - certStore.Add(certificate); - } - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - - return certificate; - } -#endif - /// /// Gets hex representation of byte array. /// input byte array diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 38f719b1a5..b2a73ca847 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -12,7 +12,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs index b0511b1d09..b7d73ff751 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs @@ -14,6 +14,8 @@ public sealed class ColumnEncryptionCertificateFixture : CertificateFixtureBase public X509Certificate2 SecondaryColumnEncryptionCertificate { get; } + public X509Certificate2 CertificateWithoutPrivateKey { get; } + private readonly X509Certificate2 _currentUserCertificate; private readonly X509Certificate2 _localMachineCertificate; @@ -22,6 +24,13 @@ public ColumnEncryptionCertificateFixture() PrimaryColumnEncryptionCertificate = CreateCertificate(nameof(PrimaryColumnEncryptionCertificate), Array.Empty(), Array.Empty()); SecondaryColumnEncryptionCertificate = CreateCertificate(nameof(SecondaryColumnEncryptionCertificate), Array.Empty(), Array.Empty()); _currentUserCertificate = CreateCertificate(nameof(_currentUserCertificate), Array.Empty(), Array.Empty()); + using (X509Certificate2 createdCertificate = CreateCertificate(nameof(CertificateWithoutPrivateKey), Array.Empty(), Array.Empty())) + { + // This will strip the private key away from the created certificate + CertificateWithoutPrivateKey = new X509Certificate2(createdCertificate.Export(X509ContentType.Cert)); + + AddToStore(CertificateWithoutPrivateKey, StoreLocation.CurrentUser, StoreName.My); + } AddToStore(PrimaryColumnEncryptionCertificate, StoreLocation.CurrentUser, StoreName.My); AddToStore(SecondaryColumnEncryptionCertificate, StoreLocation.CurrentUser, StoreName.My); From 27300c5a7f3d171904f66a218c3402c14e6a7b58 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:45:53 +0000 Subject: [PATCH 5/9] Rework ExceptionsAlgorithmErrors Removes the last reference to Utility.CreateCertificate, replacing it with one which is generated dynamically. Accordingly, removes Utility.CreateCertificate. --- .../ExceptionsAlgorithmErrors.cs | 94 +++++++++---------- .../AlwaysEncryptedTests/Utility.cs | 26 ----- 2 files changed, 45 insertions(+), 75 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs index e2d8e02b0b..593f0f8ebd 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs @@ -7,18 +7,39 @@ using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Text; +using Microsoft.Data.SqlClient.TestUtilities.Fixtures; using Xunit; using static Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests.Utility; namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests { - public class ExceptionsAlgorithmErrors : IClassFixture + [Collection(nameof(SqlColumnEncryptionExceptionAlgorithmErrorCollection))] + public class ExceptionsAlgorithmErrors { // Reflection public static Assembly systemData = Assembly.GetAssembly(typeof(SqlConnection)); public static Type sqlClientSymmetricKey = systemData.GetType("Microsoft.Data.SqlClient.SqlClientSymmetricKey"); public static ConstructorInfo sqlColumnEncryptionKeyConstructor = sqlClientSymmetricKey.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(byte[]) }, null); + private readonly ColumnEncryptionCertificateFixture _fixture; + private readonly byte[] _cek; + private readonly byte[] _encryptedCek; + private readonly string _certificatePath; + + public ExceptionsAlgorithmErrors(ColumnEncryptionCertificateFixture fixture) + { + // Disable the cache to avoid false failures. + SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; + + SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider(); + X509Certificate2 currUserCertificate = fixture.GetCertificate(StoreLocation.CurrentUser); + + _cek = GenerateRandomBytes(32); + _fixture = fixture; + _certificatePath = string.Format("CurrentUser/My/{0}", currUserCertificate.Thumbprint); + _encryptedCek = provider.EncryptColumnEncryptionKey(_certificatePath, "RSA_OAEP", _cek); + } + [Fact] [PlatformSpecific(TestPlatforms.Windows)] public void TestNullCEK() @@ -52,9 +73,9 @@ public void TestInvalidEncryptionType() { const byte invalidEncryptionType = 3; Object cipherMD = GetSqlCipherMetadata(0, 2, null, invalidEncryptionType, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidEncryptionType, "AEAD_AES_256_CBC_HMAC_SHA256", invalidEncryptionType, "'Deterministic', 'Randomized'"); @@ -74,7 +95,7 @@ public void TestInvalidCipherText() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidCipherTextSize, invalidCiphertextLength, 65); byte[] cipherText = GenerateRandomBytes(invalidCiphertextLength); // minimum length is 65 - TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic)); Assert.Contains(expectedMessage, e.InnerException.Message); } @@ -85,10 +106,10 @@ public void TestInvalidAlgorithmVersion() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidAlgorithmVersion, 40, "01"); byte[] plainText = Encoding.Unicode.GetBytes("Hello World"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); // Put a version number of 0x10 cipherText[0] = 0x40; - TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic)); Assert.Contains(expectedMessage, e.InnerException.Message); } @@ -98,13 +119,13 @@ public void TestInvalidAuthenticationTag() { string expectedMessage = SystemDataResourceManager.Instance.TCE_InvalidAuthenticationTag; byte[] plainText = Encoding.Unicode.GetBytes("Hello World"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); // Zero out 4 bytes of authentication tag for (int i = 0; i < 4; i++) { cipherText[i + 1] = 0x00; } - TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic)); Assert.Contains(expectedMessage, e.InnerException.Message); } @@ -115,9 +136,9 @@ public void TestNullColumnEncryptionAlgorithm() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_NullColumnEncryptionAlgorithm, "'AEAD_AES_256_CBC_HMAC_SHA256'"); Object cipherMD = GetSqlCipherMetadata(0, 0, null, 1, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); TargetInvocationException e = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD)); Assert.Contains(expectedMessage, e.InnerException.Message); @@ -133,9 +154,9 @@ public void TestUnknownEncryptionAlgorithmId() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnknownColumnEncryptionAlgorithmId, unknownEncryptionAlgoId, "'1', '2'"); Object cipherMD = GetSqlCipherMetadata(0, unknownEncryptionAlgoId, null, 1, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); Exception decryptEx = Assert.Throws(() => DecryptWithKey(plainText, cipherMD)); Assert.Matches(expectedMessage, decryptEx.InnerException.Message); @@ -157,9 +178,9 @@ public void TestUnknownCustomKeyStoreProvider() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnrecognizedKeyStoreProviderName, invalidProviderName, "'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'", ""); Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x03); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, invalidProviderName, "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, invalidProviderName, "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); Exception decryptEx = Assert.Throws(() => DecryptWithKey(plainText, cipherMD)); Assert.Contains(expectedMessage, decryptEx.InnerException.Message); @@ -179,9 +200,9 @@ public void TestTceUnknownEncryptionAlgorithm() string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnknownColumnEncryptionAlgorithm, unknownEncryptionAlgorithm, "'AEAD_AES_256_CBC_HMAC_SHA256'"); Object cipherMD = GetSqlCipherMetadata(0, 0, "Dummy", 1, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD)); Assert.Contains(expectedMessage, decryptEx.InnerException.Message); @@ -194,15 +215,15 @@ public void TestTceUnknownEncryptionAlgorithm() [PlatformSpecific(TestPlatforms.Windows)] public void TestExceptionsFromCertStore() { - byte[] corruptedCek = GenerateInvalidEncryptedCek(CertFixture.cek, ECEKCorruption.SIGNATURE); + byte[] corruptedCek = GenerateInvalidEncryptedCek(_cek, ECEKCorruption.SIGNATURE); string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_KeyDecryptionFailedCertStore, "MSSQL_CERTIFICATE_STORE", BitConverter.ToString(corruptedCek, corruptedCek.Length - 10, 10)); Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD)); Assert.Matches(expectedMessage, decryptEx.InnerException.Message); @@ -224,9 +245,9 @@ public void TestExceptionsFromCustomKeyStore() SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders); object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01); - AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "DummyProvider", "DummyAlgo"); + AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "DummyProvider", "DummyAlgo"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic); Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD)); Assert.Contains(expectedMessage, decryptEx.InnerException.Message); @@ -239,34 +260,9 @@ public void TestExceptionsFromCustomKeyStore() } } - public class CertFixture : IDisposable + [CollectionDefinition(nameof(SqlColumnEncryptionExceptionAlgorithmErrorCollection))] + public class SqlColumnEncryptionExceptionAlgorithmErrorCollection + : ICollectionFixture { - private readonly SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider(); - - public static X509Certificate2 certificate; - public static string thumbprint; - public static string certificatePath; - public static byte[] cek; - public static byte[] encryptedCek; - - public CertFixture() - { - if (certificate == null) - { - certificate = Utility.CreateCertificate(); - } - thumbprint = certificate.Thumbprint; - certificatePath = string.Format("CurrentUser/My/{0}", thumbprint); - cek = GenerateRandomBytes(32); - encryptedCek = provider.EncryptColumnEncryptionKey(certificatePath, "RSA_OAEP", cek); - - // Disable the cache to avoid false failures. - SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; - } - - public void Dispose() - { - // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well. - } } } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs index 7b307248a6..bed6604fd4 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/Utility.cs @@ -177,32 +177,6 @@ internal static byte[] GenerateInvalidEncryptedCek(byte[] encryptedCek, ECEKCorr return cipherText; } - internal static X509Certificate2 CreateCertificate() - { - byte[] certificateRawBytes = new byte[] { 48, 130, 10, 44, 2, 1, 3, 48, 130, 9, 232, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 9, 217, 4, 130, 9, 213, 48, 130, 9, 209, 48, 130, 5, 250, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 160, 130, 5, 235, 4, 130, 5, 231, 48, 130, 5, 227, 48, 130, 5, 223, 6, 11, 42, 134, 72, 134, 247, 13, 1, 12, 10, 1, 2, 160, 130, 4, 254, 48, 130, 4, 250, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 16, 138, 0, 169, 73, 31, 210, 173, 2, 2, 7, 208, 4, 130, 4, 216, 188, 205, 213, 250, 205, 254, 228, 160, 194, 177, 32, 195, 5, 154, 111, 7, 166, 229, 222, 46, 194, 101, 201, 219, 151, 206, 102, 223, 17, 34, 182, 108, 227, 197, 225, 244, 226, 110, 218, 105, 148, 127, 131, 47, 1, 248, 184, 57, 233, 144, 8, 209, 163, 228, 250, 131, 33, 99, 212, 251, 175, 116, 23, 185, 105, 134, 105, 133, 247, 194, 195, 32, 176, 171, 54, 9, 212, 143, 255, 82, 12, 134, 0, 193, 144, 160, 181, 185, 12, 153, 12, 240, 134, 1, 51, 64, 97, 16, 191, 173, 179, 231, 90, 199, 88, 228, 255, 244, 197, 84, 166, 146, 212, 230, 188, 167, 44, 165, 246, 112, 252, 1, 86, 204, 221, 151, 44, 128, 17, 243, 133, 75, 190, 254, 221, 85, 236, 174, 87, 250, 164, 4, 241, 198, 35, 120, 230, 127, 215, 93, 54, 40, 149, 88, 25, 64, 13, 34, 142, 193, 43, 76, 62, 73, 233, 216, 175, 253, 30, 179, 127, 164, 246, 30, 181, 10, 96, 95, 131, 170, 112, 111, 91, 61, 184, 1, 137, 249, 236, 41, 169, 120, 107, 172, 148, 122, 118, 15, 30, 198, 41, 130, 3, 175, 253, 197, 82, 218, 171, 26, 35, 129, 95, 202, 95, 144, 148, 40, 42, 120, 94, 111, 224, 51, 149, 95, 115, 29, 19, 223, 117, 123, 17, 66, 217, 112, 121, 167, 147, 250, 169, 25, 79, 145, 251, 187, 217, 38, 200, 86, 65, 181, 138, 22, 137, 42, 11, 141, 9, 169, 213, 177, 141, 86, 44, 193, 110, 143, 0, 46, 122, 198, 168, 75, 196, 85, 231, 95, 26, 242, 180, 162, 250, 69, 184, 95, 118, 210, 201, 31, 166, 166, 92, 106, 174, 246, 179, 180, 160, 251, 94, 101, 134, 18, 204, 120, 211, 38, 217, 44, 40, 176, 207, 229, 123, 68, 11, 159, 47, 129, 193, 37, 172, 107, 166, 27, 139, 49, 196, 89, 63, 210, 197, 186, 140, 94, 70, 180, 5, 174, 28, 51, 229, 10, 150, 161, 250, 137, 64, 205, 168, 1, 228, 198, 223, 200, 37, 169, 189, 189, 84, 187, 11, 103, 30, 245, 253, 101, 62, 98, 246, 127, 234, 24, 74, 217, 163, 88, 63, 165, 220, 208, 255, 127, 174, 173, 122, 202, 7, 50, 180, 120, 32, 112, 52, 165, 76, 142, 211, 248, 80, 91, 152, 92, 208, 100, 210, 156, 148, 150, 67, 203, 43, 136, 176, 89, 139, 143, 51, 30, 29, 57, 127, 242, 193, 187, 185, 80, 189, 228, 55, 144, 214, 194, 47, 49, 107, 222, 189, 242, 24, 125, 137, 159, 212, 127, 167, 104, 47, 141, 38, 196, 191, 190, 50, 65, 14, 140, 50, 254, 188, 33, 20, 202, 13, 0, 38, 130, 1, 80, 31, 48, 30, 190, 67, 84, 147, 133, 229, 137, 43, 147, 205, 254, 6, 187, 45, 11, 114, 77, 241, 108, 109, 112, 220, 200, 128, 76, 101, 201, 238, 19, 32, 210, 196, 61, 89, 133, 236, 175, 118, 214, 171, 240, 197, 92, 29, 81, 106, 36, 200, 131, 120, 114, 103, 24, 168, 206, 70, 165, 226, 237, 115, 27, 156, 94, 95, 74, 42, 43, 61, 139, 156, 165, 30, 197, 212, 187, 122, 60, 201, 221, 201, 32, 80, 64, 105, 29, 225, 126, 218, 179, 168, 82, 177, 226, 63, 244, 130, 106, 128, 50, 229, 187, 117, 83, 90, 157, 193, 163, 13, 230, 107, 142, 243, 33, 153, 142, 161, 81, 83, 137, 220, 191, 121, 222, 85, 254, 85, 247, 212, 98, 181, 255, 175, 228, 162, 235, 92, 70, 7, 253, 210, 84, 125, 229, 220, 19, 33, 120, 156, 160, 55, 144, 196, 109, 235, 166, 206, 99, 238, 97, 251, 163, 207, 81, 125, 161, 201, 150, 91, 227, 171, 247, 225, 93, 166, 105, 157, 145, 13, 244, 8, 214, 233, 193, 27, 108, 156, 206, 211, 28, 216, 13, 28, 42, 185, 251, 55, 156, 12, 67, 172, 195, 174, 96, 70, 127, 74, 236, 170, 146, 65, 44, 79, 219, 197, 166, 227, 101, 16, 160, 72, 43, 127, 106, 108, 13, 174, 138, 111, 67, 192, 185, 36, 82, 25, 253, 40, 211, 171, 246, 219, 14, 64, 125, 91, 150, 173, 114, 100, 210, 29, 202, 39, 102, 81, 0, 90, 176, 122, 149, 121, 254, 53, 130, 202, 107, 233, 131, 47, 216, 31, 66, 96, 55, 37, 164, 195, 217, 205, 153, 74, 83, 169, 167, 241, 51, 102, 140, 102, 202, 15, 57, 193, 172, 140, 114, 115, 218, 156, 111, 238, 162, 48, 44, 141, 156, 15, 65, 29, 242, 187, 73, 19, 192, 102, 69, 192, 172, 16, 197, 17, 104, 68, 69, 224, 180, 252, 227, 80, 43, 148, 126, 85, 12, 168, 85, 18, 146, 90, 37, 215, 123, 169, 117, 87, 125, 228, 235, 11, 163, 132, 239, 31, 163, 196, 121, 19, 217, 59, 35, 52, 125, 204, 246, 142, 176, 137, 170, 76, 50, 37, 29, 250, 82, 145, 113, 138, 161, 9, 186, 227, 151, 40, 57, 217, 78, 39, 154, 237, 20, 102, 184, 78, 141, 194, 196, 22, 171, 135, 7, 62, 236, 163, 34, 222, 172, 186, 230, 175, 36, 243, 249, 13, 95, 15, 77, 227, 222, 208, 12, 140, 103, 111, 26, 160, 237, 27, 158, 162, 189, 226, 155, 76, 135, 220, 56, 152, 230, 151, 73, 120, 68, 83, 140, 238, 6, 63, 130, 182, 12, 33, 181, 201, 242, 36, 236, 9, 160, 237, 144, 22, 228, 17, 201, 45, 25, 84, 96, 127, 51, 178, 181, 173, 59, 2, 219, 37, 244, 75, 16, 135, 51, 67, 69, 240, 191, 232, 122, 200, 191, 220, 111, 18, 163, 179, 201, 101, 246, 105, 175, 241, 47, 187, 156, 251, 173, 122, 116, 51, 100, 93, 219, 166, 160, 240, 181, 161, 220, 15, 218, 215, 46, 62, 81, 79, 238, 38, 51, 115, 69, 169, 32, 252, 118, 89, 25, 208, 126, 143, 6, 135, 122, 179, 25, 4, 183, 177, 61, 62, 160, 115, 38, 184, 109, 213, 185, 14, 177, 242, 23, 228, 4, 204, 7, 199, 62, 50, 18, 5, 124, 140, 105, 149, 63, 89, 37, 117, 145, 26, 105, 83, 13, 2, 113, 211, 171, 208, 10, 25, 177, 42, 220, 4, 153, 109, 106, 99, 75, 97, 14, 42, 168, 164, 130, 88, 228, 167, 129, 198, 121, 135, 103, 231, 101, 208, 35, 108, 249, 151, 187, 74, 31, 59, 68, 127, 34, 117, 150, 179, 229, 65, 236, 169, 16, 12, 170, 67, 61, 210, 228, 72, 121, 169, 206, 63, 71, 142, 47, 16, 117, 59, 205, 159, 50, 14, 19, 111, 171, 196, 117, 113, 200, 239, 112, 175, 147, 115, 203, 37, 241, 12, 145, 111, 160, 168, 234, 240, 108, 235, 136, 143, 179, 240, 57, 74, 49, 82, 171, 35, 157, 240, 125, 116, 238, 36, 65, 225, 197, 138, 53, 32, 85, 247, 115, 154, 193, 145, 153, 176, 232, 43, 89, 96, 221, 238, 105, 42, 205, 59, 52, 97, 199, 228, 207, 23, 55, 22, 44, 27, 112, 74, 230, 228, 228, 214, 106, 91, 42, 34, 239, 156, 103, 151, 106, 30, 2, 0, 103, 16, 130, 106, 128, 117, 120, 101, 107, 206, 52, 201, 116, 168, 27, 185, 6, 181, 161, 116, 108, 49, 129, 205, 48, 19, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 21, 49, 6, 4, 4, 1, 0, 0, 0, 48, 87, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 20, 49, 74, 30, 72, 0, 53, 0, 54, 0, 102, 0, 54, 0, 54, 0, 53, 0, 97, 0, 50, 0, 45, 0, 50, 0, 54, 0, 50, 0, 98, 0, 45, 0, 52, 0, 50, 0, 52, 0, 50, 0, 45, 0, 57, 0, 57, 0, 97, 0, 56, 0, 45, 0, 57, 0, 55, 0, 55, 0, 97, 0, 97, 0, 57, 0, 56, 0, 99, 0, 101, 0, 97, 0, 97, 0, 100, 48, 93, 6, 9, 43, 6, 1, 4, 1, 130, 55, 17, 1, 49, 80, 30, 78, 0, 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 0, 102, 0, 116, 0, 32, 0, 83, 0, 116, 0, 114, 0, 111, 0, 110, 0, 103, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 0, 114, 48, 130, 3, 207, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 6, 160, 130, 3, 192, 48, 130, 3, 188, 2, 1, 0, 48, 130, 3, 181, 6, 9, 42, 134, 72, 134, 247, 13, 1, 7, 1, 48, 28, 6, 10, 42, 134, 72, 134, 247, 13, 1, 12, 1, 3, 48, 14, 4, 8, 249, 68, 23, 15, 90, 178, 55, 11, 2, 2, 7, 208, 128, 130, 3, 136, 189, 232, 130, 97, 198, 137, 5, 230, 136, 106, 215, 76, 90, 0, 66, 64, 19, 132, 179, 239, 204, 147, 171, 145, 124, 195, 15, 246, 30, 203, 38, 201, 2, 161, 7, 62, 68, 229, 251, 178, 182, 14, 196, 8, 147, 127, 74, 211, 9, 178, 219, 14, 204, 237, 59, 181, 16, 54, 199, 106, 231, 162, 42, 124, 144, 191, 249, 104, 251, 199, 30, 96, 66, 145, 83, 140, 195, 197, 220, 166, 143, 255, 193, 218, 88, 87, 135, 11, 52, 156, 122, 252, 178, 19, 207, 151, 228, 191, 226, 81, 208, 208, 101, 148, 249, 166, 242, 70, 140, 39, 180, 152, 3, 29, 150, 23, 212, 89, 209, 32, 134, 105, 128, 10, 211, 220, 4, 161, 38, 185, 202, 109, 119, 177, 29, 133, 55, 7, 126, 40, 120, 195, 36, 134, 119, 242, 130, 142, 142, 112, 212, 116, 6, 91, 150, 197, 164, 1, 53, 172, 139, 47, 230, 29, 254, 53, 106, 18, 184, 87, 117, 249, 108, 226, 61, 27, 133, 37, 250, 48, 235, 194, 115, 71, 244, 92, 165, 61, 6, 101, 153, 239, 167, 74, 230, 159, 26, 66, 132, 89, 191, 44, 73, 144, 174, 48, 219, 61, 205, 131, 107, 90, 66, 157, 148, 22, 19, 47, 182, 10, 141, 113, 225, 201, 47, 31, 244, 253, 125, 128, 244, 70, 200, 38, 123, 146, 102, 94, 247, 15, 45, 62, 176, 2, 225, 70, 17, 193, 129, 133, 121, 6, 96, 135, 138, 68, 105, 108, 186, 126, 253, 210, 80, 228, 168, 234, 202, 40, 160, 246, 117, 60, 119, 54, 126, 166, 137, 237, 94, 228, 241, 167, 170, 19, 215, 36, 154, 215, 179, 44, 35, 223, 181, 13, 55, 251, 122, 176, 132, 72, 213, 253, 103, 16, 174, 213, 35, 217, 188, 214, 113, 114, 212, 70, 106, 124, 54, 233, 93, 156, 7, 135, 253, 183, 174, 165, 29, 170, 23, 186, 148, 232, 114, 226, 82, 139, 224, 78, 239, 179, 155, 70, 117, 39, 188, 242, 198, 93, 230, 209, 169, 8, 179, 100, 136, 100, 181, 217, 240, 173, 97, 92, 176, 135, 193, 149, 89, 85, 201, 206, 191, 173, 168, 48, 47, 224, 233, 145, 47, 213, 32, 76, 94, 230, 86, 63, 85, 170, 211, 107, 94, 133, 144, 35, 102, 49, 253, 150, 120, 163, 246, 13, 105, 76, 211, 215, 244, 8, 121, 108, 225, 54, 95, 229, 239, 32, 203, 145, 0, 242, 84, 176, 22, 61, 79, 71, 84, 46, 31, 135, 71, 15, 192, 52, 250, 54, 78, 98, 45, 173, 191, 101, 161, 49, 178, 136, 67, 40, 70, 24, 148, 96, 253, 160, 1, 185, 209, 37, 159, 102, 116, 11, 252, 74, 28, 173, 218, 80, 149, 33, 189, 214, 186, 251, 97, 179, 199, 151, 48, 78, 211, 58, 241, 1, 223, 118, 99, 57, 91, 15, 142, 0, 227, 16, 18, 170, 22, 45, 230, 13, 199, 39, 143, 231, 134, 33, 117, 229, 224, 133, 130, 135, 8, 48, 170, 137, 72, 216, 34, 249, 110, 33, 25, 12, 244, 204, 66, 218, 68, 92, 144, 149, 247, 186, 92, 131, 158, 42, 9, 253, 9, 198, 27, 158, 83, 18, 151, 107, 37, 77, 251, 61, 93, 101, 60, 76, 110, 84, 167, 16, 88, 26, 119, 196, 177, 185, 172, 87, 70, 207, 167, 32, 80, 80, 9, 3, 201, 195, 48, 39, 56, 240, 184, 229, 83, 12, 80, 145, 25, 205, 226, 173, 207, 198, 206, 40, 23, 224, 74, 139, 112, 90, 17, 247, 83, 11, 18, 145, 111, 115, 250, 168, 219, 194, 96, 145, 184, 8, 22, 169, 242, 64, 166, 25, 103, 197, 186, 28, 49, 170, 10, 113, 135, 21, 220, 172, 234, 126, 39, 233, 11, 119, 235, 184, 38, 47, 44, 101, 99, 86, 210, 205, 205, 104, 98, 165, 182, 126, 124, 109, 150, 211, 79, 242, 110, 96, 74, 96, 173, 249, 63, 245, 52, 180, 148, 152, 117, 241, 218, 220, 75, 43, 96, 218, 132, 199, 248, 60, 62, 15, 49, 75, 62, 128, 31, 69, 2, 124, 250, 164, 60, 65, 127, 112, 197, 53, 157, 120, 148, 100, 146, 245, 132, 192, 192, 188, 64, 1, 142, 206, 132, 241, 210, 161, 126, 56, 5, 95, 204, 89, 53, 143, 224, 137, 126, 182, 71, 12, 49, 39, 211, 33, 48, 177, 234, 136, 205, 169, 53, 209, 141, 89, 219, 83, 102, 12, 43, 94, 96, 66, 2, 232, 131, 85, 182, 130, 222, 71, 121, 228, 246, 9, 41, 141, 95, 73, 70, 51, 58, 86, 168, 193, 76, 25, 196, 40, 203, 62, 139, 217, 178, 187, 87, 171, 212, 85, 42, 136, 145, 174, 134, 171, 113, 188, 28, 31, 4, 77, 87, 237, 194, 98, 20, 111, 165, 95, 45, 204, 150, 176, 85, 128, 75, 131, 175, 45, 197, 209, 224, 176, 179, 39, 216, 114, 150, 202, 79, 153, 178, 197, 176, 237, 84, 123, 207, 52, 250, 56, 55, 191, 20, 249, 173, 204, 8, 59, 199, 237, 23, 234, 158, 246, 203, 222, 105, 163, 152, 99, 137, 47, 112, 98, 79, 161, 88, 198, 125, 106, 174, 85, 134, 216, 35, 80, 161, 140, 177, 161, 154, 169, 80, 193, 224, 238, 238, 31, 92, 124, 238, 147, 162, 209, 186, 50, 48, 59, 48, 31, 48, 7, 6, 5, 43, 14, 3, 2, 26, 4, 20, 249, 117, 64, 150, 197, 135, 218, 207, 32, 100, 203, 75, 240, 98, 164, 185, 50, 202, 93, 125, 4, 20, 180, 36, 134, 220, 75, 81, 26, 153, 143, 72, 201, 209, 29, 87, 166, 59, 206, 207, 221, 99, 2, 2, 7, 208 }; - X509Certificate2 certificate = new X509Certificate2(certificateRawBytes, "", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet); - X509Store certStore = null; - try - { - certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); - certStore.Open(OpenFlags.ReadWrite); - if (!certStore.Certificates.Contains(certificate)) - { - certStore.Add(certificate); - } - - } - finally - { - if (certStore != null) - { - certStore.Close(); - } - } - - return certificate; - } - /// /// Encrypt Data using AED /// From 24c42931af2a388861c80d3a987678780dc8413e Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:51:39 +0000 Subject: [PATCH 6/9] Collection fixtures are unnecessary --- .../AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs | 9 +-------- .../SqlColumnEncryptionCertificateStoreProviderShould.cs | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs index 593f0f8ebd..ba90ddf4f0 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs @@ -13,8 +13,7 @@ namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests { - [Collection(nameof(SqlColumnEncryptionExceptionAlgorithmErrorCollection))] - public class ExceptionsAlgorithmErrors + public class ExceptionsAlgorithmErrors : IClassFixture { // Reflection public static Assembly systemData = Assembly.GetAssembly(typeof(SqlConnection)); @@ -259,10 +258,4 @@ public void TestExceptionsFromCustomKeyStore() } } } - - [CollectionDefinition(nameof(SqlColumnEncryptionExceptionAlgorithmErrorCollection))] - public class SqlColumnEncryptionExceptionAlgorithmErrorCollection - : ICollectionFixture - { - } } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs index 8500a1c536..3a220cd9c7 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs @@ -17,8 +17,7 @@ namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests { - [Collection(nameof(SqlColumnEncryptionCertificateStoreProviderCollection))] - public class SqlColumnEncryptionCertificateStoreProviderWindowsShould + public class SqlColumnEncryptionCertificateStoreProviderWindowsShould : IClassFixture { private const string PRIMARY_CERTIFICATE_PATH = "CurrentUser/My/{primary_thumbprint}"; private const string SECONDARY_CERTIFICATE_PATH = "CurrentUser/My/{secondary_thumbprint}"; @@ -653,10 +652,4 @@ public void ThrowPlatformNotSupportedExceptionInUnix() Assert.Throws(() => provider.VerifyColumnMasterKeyMetadata("", false, new byte[] { })); } } - - [CollectionDefinition(nameof(SqlColumnEncryptionCertificateStoreProviderCollection))] - public class SqlColumnEncryptionCertificateStoreProviderCollection - : ICollectionFixture - { - } } From 5f16bd04d1233200a04270d6b9a82d4f6eff98b0 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 20:31:43 +0000 Subject: [PATCH 7/9] Update build.proj --- build.proj | 1 + 1 file changed, 1 insertion(+) diff --git a/build.proj b/build.proj index 92c323c544..2853492363 100644 --- a/build.proj +++ b/build.proj @@ -59,6 +59,7 @@ + From f6e1ea703438128631728f6fdb6dfa37c1596057 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Sun, 24 Nov 2024 21:28:09 +0000 Subject: [PATCH 8/9] Running PowerShell with "runas" verb --- .../Fixtures/CertificateFixtureBase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs index 4c0f3599a2..54ce937151 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs @@ -149,7 +149,8 @@ exit 1 UseShellExecute = false, CreateNoWindow = true, // Pass the Base64-encoded command to remove the need to escape quote marks - Arguments = "-EncodedCommand " + Convert.ToBase64String(Encoding.Unicode.GetBytes(formattedCommand)) + Arguments = "-EncodedCommand " + Convert.ToBase64String(Encoding.Unicode.GetBytes(formattedCommand)), + Verb = "runas" } }) { From 1ff8f1cbe68246b605966cb177cf09c3b4db2fcc Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon, 25 Nov 2024 22:28:33 +0000 Subject: [PATCH 9/9] Switched to new .NET 9.0 APIs --- .../Fixtures/CertificateFixtureBase.cs | 2 +- .../Fixtures/ColumnEncryptionCertificateFixture.cs | 2 +- .../Microsoft.Data.SqlClient.TestUtilities.csproj | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs index 54ce937151..79699c32d5 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs @@ -83,7 +83,7 @@ protected static X509Certificate2 CreateCertificate(string subjectName, IEnumera // This is to ensure that it's imported into the certificate stores with its private key. using (X509Certificate2 ephemeral = request.CreateSelfSigned(notBefore, notAfter)) { - return new X509Certificate2(ephemeral.Export(X509ContentType.Pkcs12, password), password, + return X509CertificateLoader.LoadPkcs12(ephemeral.Export(X509ContentType.Pkcs12, password), password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); } #else diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs index b7d73ff751..906f27039b 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnEncryptionCertificateFixture.cs @@ -27,7 +27,7 @@ public ColumnEncryptionCertificateFixture() using (X509Certificate2 createdCertificate = CreateCertificate(nameof(CertificateWithoutPrivateKey), Array.Empty(), Array.Empty())) { // This will strip the private key away from the created certificate - CertificateWithoutPrivateKey = new X509Certificate2(createdCertificate.Export(X509ContentType.Cert)); + CertificateWithoutPrivateKey = X509CertificateLoader.LoadCertificate(createdCertificate.Export(X509ContentType.Cert)); AddToStore(CertificateWithoutPrivateKey, StoreLocation.CurrentUser, StoreName.My); } diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj index 2895ef3a6a..c719a37006 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj @@ -16,5 +16,7 @@ PreserveNewest + + \ No newline at end of file