Skip to content

Always Encrypted - 'Keyset Does not exist' #195

@ph1294

Description

@ph1294

Description of Issue

Always Encrypted cannot find the certificate to decrypt the column keys, although it has been generated automatically using SSMS and placed into the machine certificate store. Feature works correctly in a .NET Framework project with exact same steps followed.

Microsoft.Data.SqlClient.SqlException
  HResult=0x80131904
  Message=Failed to decrypt column 'Password'.
Failed to decrypt a column encryption key using key store provider: 'MSSQL_CERTIFICATE_STORE'. The last 10 bytes of the encrypted column encryption key are: '2E-60-91-33-22-5C-A2-FA-22-B7'.
Keyset does not exist
  Source=Core Microsoft SqlClient Data Provider
  StackTrace:
   at WebAutomation.DBAccess.GetCreds() in H:\Web Automation\WebAutomation\WebAutomation\DBAccess.cs:line 42
   at WebAutomation.SeleniumSite.get_Creds() in H:\Web Automation\WebAutomation\WebAutomation\SeleniumSite.cs:line 21
   at WebAutomation.SeleniumSite.AccessDRAS(Boolean visualCron) in H:\Web Automation\WebAutomation\WebAutomation\SeleniumSite.cs:line 124
   at WebAutomation.Run.RunSiteReports(SeleniumSite SeleniumSite) in H:\Web Automation\WebAutomation\WebAutomation\Run.cs:line 71
   at WebAutomation.Run.Main(String[] args) in H:\Web Automation\WebAutomation\WebAutomation\Run.cs:line 40

Inner Exception 1:
WindowsCryptographicException: Keyset does not exist

To reproduce

Access a SQL 2017 named instance Database in a .NET Core application which uses the Always Encrypted Drivers.

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using Microsoft.Data.SqlClient;
using System.Data;

namespace WebAutomation
{
    class DBAccess
    {
        private readonly string connectionString = "Data Source={FQDN}\\{INSTANCE};Initial Catalog=Operations;Persist Security Info=True;User ID=Selenium;Password=***********;Column Encryption Setting=Enabled";
        private readonly string queryString = "SELECT * FROM selenium.Credentials WHERE [Automator] = @a";

        private string Automator { get; set; }
        
        public DBAccess(string automator)
        {
            Automator = automator;
        }

        /// <summary>
        /// Gets credentials for a specific automtaor from the database.
        /// </summary>
        /// <returns>A datatable containing decrypted credentials.</returns>
        internal DataTable GetCreds()
        {
            using(SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlCommand command = new SqlCommand(queryString, connection);
                command.Parameters.AddWithValue("@a", Automator);
                connection.Open();
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                DataTable ret = new DataTable();
                try
                {
                    adapter.Fill(ret);
                    return ret;
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    adapter.Dispose();
                }
            }
        }
    }
}

Expected behavior

Should connect to data source and automatically decrypt data.

Further technical details

Microsoft.Data.SqlClient version: 1.0.19249.1
.NET target: Core 2.1.4
SQL Server version: SQL Server 2017
Operating system: Windows 10 1903

Additional context
I am confident that the client is at least trying to implement always encrypted, because the error varies from the 'not implemented' type of message thrown by System.Data.SqlClient.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions