How to back multiple master database key DEK on SQL with TDE Enable - sql-server

I have an SQL instance with multiple data bases. Each of them are TDE encrypted.
I know that all data bases use the same service master key, SMK, to encrypt tempdb. I have back up the SMK using:
BACKUP SERVICE MASTER KEY
TO FILE = 'tmp-path.key'
ENCRYPTION BY PASSWORD = 'temp-password';
Now, how do I back up the distinct database master key, DMK? Each data base use a different one, but the SQL statement doesn't allow to specify which one to back up. Next, is the command I'm running.
BACKUP MASTER KEY
TO FILE = 'tmep-path.key'
ENCRYPTION BY PASSWORD = 'temp-passowrd'
I though that by:
use [specific-db];
GO
It will back up an specific one, but the command won't run. You need to be on master, to run the command.
Thanks

The way TDE is configured in SQL Server is as follow:
Create Master key in master database
Create Certificate using the master key
Create Database Encryption key using the certificate
There are only two things you need to/can backup here:
Master Encryption Key - The script you have shown in your question will do that.
BACKUP MASTER KEY
TO FILE = 'tmep-path.key'
ENCRYPTION BY PASSWORD = 'temp-passowrd'
Certificate - You can either create a separate Certificate for each database to be encrypted or a single certificate to encrypt all database, You will create and backup the certificate as follow:
-- Create Certificate
USE Master;
GO
CREATE CERTIFICATE TDE_MyDB_Cert
WITH SUBJECT = 'My TDE Certificate for MyDB user database'
GO
This certificate is protected by the service master key.
-- Encrypt Database using the Certificate
USE [MyDB]
GO
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_128
ENCRYPTION BY SERVER CERTIFICATE TDE_MyDB_Cert
GO
Now you need to backup the certificate with the private key for the database which you would do, doing:
USE master;
GO
BACKUP CERTIFICATE TDE_MyDB_Cert
TO FILE = 'C:\TDE_MyDB_Cert_File.cer'
WITH PRIVATE KEY (FILE = 'C:\TDE_MyDB_Cert_PKey.pvk' ,
ENCRYPTION BY PASSWORD = 'S0M34tR0nGP#$$w)rd' )
GO
TDE_MyDB_Cert_File.cer Is the certificate backup
TDE_MyDB_Cert_PKey.pvk is the backup for Private key for the database

Related

SQL Server 2019 Enterprise - High Availability with Master Key

I have a SQL Server 2019 Enterprise HA system that has a encrypted master key, and every time that I have to fail over to the secondary database (or vice n versa) I have to run this script in order to have the Secondary working after the failover.
DROP SYMMETRIC KEY DataProtectionKey
DROP CERTIFICATE DataProtection
DROP MASTER KEY
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'My_encryption_key'
CREATE CERTIFICATE DataProtection WITH SUBJECT = 'Data Protection'
CREATE SYMMETRIC KEY DataProtectionKey WITH ALGORITHM = AES_256 ENCRYPTION BY CERTIFICATE DataProtection
USE [MYDATABASE]
GO
ALTER MASTER KEY FORCE REGENERATE 
WITH ENCRYPTION BY PASSWORD = 'My_encryption_key'
GO
I also tried to use this other script after failing over to see if I could finally insert the Master Key and solve for all the issue.
USE [MYDATABASE]
GO
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'My_encryption_key';
ALTER MASTER KEY DROP ENCRYPTION BY SERVICE MASTER KEY
ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY
CLOSE MASTER KEY;
Unfortunately, every time that I fail over the DB, I have to run one of the two scripts.
There is any way that I could do this once for all ?
Thank you
You can try to create the certificate on primary, backup, and restore on secondary.
This code is from my repo created for a demo for AlwaysOn with docker.
Primary
-- PRIMARY
USE [master]
GO
-- Create masterkey
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P#ssw0rd!';
GO
-- Create certificate
CREATE CERTIFICATE ao_certificate WITH SUBJECT = 'ao_certificate';
GO
BACKUP CERTIFICATE ao_certificate
TO FILE = '/var/opt/mssql/shared/ao_certificate.cert'
WITH PRIVATE KEY (
FILE = '/var/opt/mssql/shared/ao_certificate.key',
ENCRYPTION BY PASSWORD = 'P#ssw0rd!'
);
GO
Secondary
-- SECONDARY
USE [master]
GO
-- Create master key
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P#ssw0rd!';
GO
-- create certificate with private key created on primary server and saved to shared location
CREATE CERTIFICATE ao_certificate
FROM FILE = '/var/opt/mssql/shared/ao_certificate.cert'
WITH PRIVATE KEY (
FILE = '/var/opt/mssql/shared/ao_certificate.key',
DECRYPTION BY PASSWORD = 'P#ssw0rd!'
)
GO
Yes, and the fix is relatively simple. Take a backup of the service master key (SMK) from the secondary replica and restore it to the primary replica. This will re-encrypt anything already encrypted with the existing SMK with the restored SMK. And since the SMK is now the same between both replicas, the failover will be seamless.
The reason that the direction is from secondary to primary is that the re-encryption performs writes (albeit not many) into your user database which is allowed only on the primary replica.
A colleague from my team found a better solution for this issue.
On the primary DB, I will call DBS1 backup the master key using the encryption password that you used to create the DB:
BACKUP SERVICE MASTER KEY TO FILE = 'D:\Backup\dbs1_service_master_key.key' ENCRYPTION BY PASSWORD = 'Wh#t3v3r_P#$$w0rd';
Promote the secondary DB to primary on the HA (failover), so you can run the script below:
USE [YOURDATABASE]
GO
open master key decryption by password = 'Wh#t3v3r_P#$$w0rd'
Alter Master Key Add encryption by Service Master Key
GO
Copy the service master key that you backed up on the primary DBS1 and copy in a location on DBS2.
Still on the "secondary" DBS that now is primary on the HA group, restore the certificate:
RESTORE SERVICE MASTER KEY FROM FILE = 'D:\Backup\dbs1_service_master_key.key' DECRYPTION BY PASSWORD = 'Wh#t3v3r_P#$$w0rd';

Restoring a TDE Encrypted Database Backup to a Different Server - SQL Server 2008

Two years ago, I used the below code to encrypt (TDE) the database in SQL Server 2008
USE MASTER;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Strong Password'
GO
USE MASTER;
CREATE CERTIFICATE DB_CER WITH SUBJECT = 'DB Certificate'
GO
USE DB
GO
CREATE DATABASE ENCRYPTION KEY WITH
ALGORITHM = AES_256 ENCRYPTION BY
SERVER CERTIFICATE DB_CER ;
GO
USE DB
ALTER DATABASE DB
SET ENCRYPTION ON ;
GO
USE master;
GO
BACKUP CERTIFICATE DB_CER
TO FILE = 'c:\Backup\certificate_DB_Certificate.cer'
WITH PRIVATE KEY
(FILE = 'c:\Backup\certificate_DB_Key.pvk',
ENCRYPTION BY PASSWORD = 'Strong Password')
I took full backup for DB Database and the certificate_DB_Certificate.cer & certificate_DB_Key.pvk and save it to my hard drive.
After two years I used different PC to restore the MASTER KEY & the CERTIFICATE, so I can to restore the Backup file
CREATE CERTIFICATE DB_CER
FROM FILE = 'D:\Backup\certificate_DB_Certificate.cer'
WITH PRIVATE KEY (FILE = 'D:\Backup\certificate_OCV_DB_Key.pvk',
DECRYPTION BY PASSWORD = 'Strong Password')
After I run the code I got this message
Warning: The certificate you created is expired.
So I delete the CERTIFICATE and I change the Pc date to 2015/Jun (the date when The CERTIFICATE was created) then I re-create the certificate again with successfully completed command, but when I restore the backup file I got this message
Restore of database 'DB' failed.
(Microsoft.SqlServer.Management.RelationalEngineTasks)
System.Data.SqlClient.SqlError: Cannot find server certificate with thumbprint '0xFC01AD2683E08A4C8CD6A0F037DC66A945FBA44D'. (Microsoft.SqlServer.SmoExtended)
Any suggestions?
The "expired certificate" message was a warning, not an error. You can still use an expired certificate.
Delete the certificate you created with the changed date, then restore the certificate again with the correct date.

Implement TDE and log shipping on different domains

I have two instances of SQL Server 2016 Enterprise, each running on a different server. They are standalone servers. There is a shared drive on ServerA which can be accessed from ServerB.
I have set up log shipping from a database (TESTDB) on MAIN_DB to one on MAIN_UAT. I did this by creating the same local user profile on each server (SQLService) with the same password and changing the SQL Agent and SQL Server jobs to run under this profile on each server using SQL Server Configuration Manager. This seems to work quite happily.
I then tried to implement TDE on the databases.
In the first instance, I stopped log shipping. I then created a second database (TESTDB2) on MAIN_DB and set up log shipping to that from the primary database on MAIN_UAT. Then I used this script to set up TDE. Once the backup and restore cycle had run, TESTDB2 was also encrypted. Again, this worked without problems.
use master
go
create master key encryption by password='something cryptic'
go
create certificate TDECertificate with subject='Log Shipping certificate'
go
create database encryption key with algorithm=AES_256 encryption by server certificate TDECertificate
alter database TestDB set encryption on
I then tried to reproduce this on the secondary server – MAIN_UAT. On the primary server I ran this script.
backup certificate TDECertificate to file='D:\Certificates\myCertificate.crt'
with private key (file='D:\LANSHARE\Certificates\LogShippingKey.key',encryption by password='something cryptic')
backup master key to file='D:\Certificates\MasterKey.key' encryption by password='something cryptic'
I copied the three resulting files into a folder on the secondary server and gave SQLService (the local user) full control over the folder and files. I then tried to install the certificate on the secondary server with this script.
use master
go
restore master key from file='D:\Certificates\MasterKey.key' decryption by password='something cryptic'encryption by password='something cryptic'
go
create certificate TDECertificate from file='D:\Certificates\myCertificate.crt' with private key (file='D:\Certificates\LogShippingKey.key',decryption by password='something cryptic',encryption by password='something cryptic')
go
use TESTDB2
go
create database encryption key with algorithm=AES_256 encryption by server certificate TDECertificate
This gave me this error, which is where I’m stuck.
Msg 15151, Level 16, State 1, Line 14
Cannot find the certificate 'TDECertificate', because it does not exist or you do not have permission.
In a nutshell, how do I implement TDE with log shipping on servers on different domains?
Thanks for any help you can give.

SQL Server DMK password

Where is the SQL Server Database master key (DMK) password stored? Is it stored in master database? in registry?. If the hacker gets hold of the mdf files will he be able to get the password that was used to create DMK?
In the SQL Server there is Encryption Hierarchy - everything is encrypted by something. You can create one Database Mater Key in each database in order to protect the certificates, assymetric and symetric keys in it - the DMK is used to encrypted them.
Database master keys are protected by the Service Master Key. The
Service Master Key is created by SQL Server setup and is encrypted
with the Windows Data Protection API (DPAPI).
Let's say we have a database backup and restore it to our local instance. If I try to read some of the ecnrypted data, without knowing the DMK password in order to encrypt the certificate I am getting the following error:
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'I_DO_NOT_KNOW_THE_PASS';
SELECT *, CAST(DecryptByAsymKey(AsymKey_ID(N'smGK_АSymmetricKey_01'), BufferEncryptedEmail) AS NVARCHAR(444))
FROM SecurityUsersAssimetricKey
CLOSE MASTER KEY
Msg 15313, Level 16, State 1, Line 1 The key is not encrypted using
the specified decryptor.
So, in my case (when the DMK is encrtpyed by password), I can only read the ecnrypted data knowing the password:
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'smGK_MasterKeyPassword';
SELECT *, CAST(DecryptByAsymKey(AsymKey_ID(N'smGK_АSymmetricKey_01'), BufferEncryptedEmail) AS NVARCHAR(444))
FROM SecurityUsersAssimetricKey
CLOSE MASTER KEY
In order to protect the whole data, you can check howbackup encryption is made.
If backup encryption is applied, the backup is encrypted using certificate. Without this certificated, the backup cannot be restored. You can store this certificate anywhere you like. Generally, you are right for the brute force - if the database is restored, you can try to brute force the DMK, when you have it, you can read all encrypted columns. But when you cannot restore the database using its backup, you can do nothing.

Encryption with an AlwaysOn cluster

I have a database that was moved off of an old SQL Server 2008R2 instance and into a SQL Server 2012 AlwaysOn cluster. There are several fields within the database that are encrypted using SQL Servers built-in encryption features (master key, cert, symmetric key.)
I have run the following commands on my QA AO instance (the same steps that had been run on the old server):
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'password'
CREATE CERTIFICATE myCert
WITH SUBJECT = 'password'
CREATE SYMMETRIC KEY myKeyName
WITH ALGORITHM = TRIPLE_DES
ENCRYPTION BY CERTIFICATE myCert
Additionally I had to run the following commands to correctly decrypt the data:
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'password'
ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY
When I run this command I then see all of the data decrypted:
OPEN SYMMETRIC KEY myKeyName
DECRYPTION BY CERTIFICATE myCert
select TOP 1000 userid, CONVERT(nVARCHAR(255),DECRYPTBYKEY(password)) from users
CLOSE SYMMETRIC KEY myKeyName
So far so good. However, if I run these same steps on my production AO cluster this query:
select TOP 1000 userid, CONVERT(nVARCHAR(255),DECRYPTBYKEY(password)) from users
returns NULL for the password. To make this a little bit more maddening, this statement (run in the context of the QA environment) decrypts everything from both databases just fine:
OPEN SYMMETRIC KEY myKeyName
DECRYPTION BY CERTIFICATE myCert
SELECT TOP 1000
userid,
CONVERT(nVARCHAR(255),DECRYPTBYKEY(password))
FROM users
SELECT TOP 1000
userid,
CONVERT(nVARCHAR(255),DECRYPTBYKEY(password))
FROM PRODUCTIONAO.prod_database.dbo.users
CLOSE SYMMETRIC KEY myKeyName
I am not sure why this would work on my QA instance, but not on my production instance. Any help would be greatly appreciated!
The reason your last query works is due to the fact that you're using the QA instance's key/cert to do the decryption of the production data. In QA you can auto-decrypt the cert with the database master key (DMK) since it's encrypted by the QA service master key (SMK) as follows:
Service Master Key (QA)
Database Master Key (QA)
Certificate (QA)
Symmetric Key (QA)
Data (Prod)
In prod, you have a different SMK so the only option to open the DMK is by using the password. It seems that you ran the following in the QA environment but not in prod:
/* Add service master key encryption to the database master key */
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'password'
ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY
Try this in prod:
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'password'
OPEN SYMMETRIC KEY myKeyName
DECRYPTION BY CERTIFICATE myCert
select TOP 1000 userid, CONVERT(nVARCHAR(255),DECRYPTBYKEY(password)) from users
CLOSE SYMMETRIC KEY myKeyName
If that returns data, you need to add the SMK encryption to your DMK in production (the first script). The other option is backing up the SMK from the source instance and restoring it on the secondary. I'd only recommend this in HA use-cases where the instances are fail-over partners and both are in the same environment. Sharing SMKs between QA and prod is a bad practice.
When a database master key is created, the server saves 2 versions of key. One version is encrypted by the master service key and by default is used by the server. The second version is encrypted by the password that you supply to the server when you create the database master key. This version usually is not used. When you move your database into a different environment (production in your case), the new server has a different master service key. Since it is not the service key that was used to encrypt the database’s master key, it also can’t be used in order to open the database’s master key. This is where you should use the version that was encrypted with your password. You need to open the master key using your password, then encrypt it using the new service key and close it. After you do that, the database’s master key can work with the master service key, so you don’t need to do it again.
steps/code:
open master key decryption by password = 'WriteYouOriginalPasswordHere'
alter master key add encryption by service master key
close master key

Resources