CERTENCODED: How to Script your Certificates

2014-05-16 - Backup, Cryptography, General, Security

Introduction

When dealing with certificates in SQL Server we sometimes need to be able to copy a specific certificate from one database to another. For example, when using certificates for permission management, we often need the same certificate to exist in the user database as well as in master.

A few days ago I wrote about how to create a backup of your certificate. To copy a certificate you can certainly create a backup and then restore it to another database. In fact, that is the only way to do it in SQL Server versions before SQL 2012. However, in SQL 2012 Microsoft introduced the capability to script out certificates. In this article, I am going to show you how to use that new feature.

CERTENCODED in Action

Scripting a certificate through SQL Server Management Studio is not (yet) possible. Instead we have to generate the CREATE CERTIFICATE statement ourselves. For that we can use the CERTENCODED built-in function. CERTENCODED takes one parameter, the certificate_id of the certificate we want to script, and returns a VARBINARY value that contains all the public information of the certificate, including the public key.

Let us look at an example. First, we need a certificate to script:

[sql] IF(CERT_ID('ACertificate') IS NOT NULL) DROP CERTIFICATE ACertificate;
GO
CREATE CERTIFICATE ACertificate WITH SUBJECT = 'A Subject';
[/sql]

This snippet uses a conditional drop technique to first clean up. Then it creates a simple certificate that is protected by the database master key.

With the certificate in place, we can now use the CERTENCODED function:

[sql] SELECT CERTENCODED(CERT_ID('ACertificate'));
[/sql]

As CERTENCODED takes the certificate_id and not the name, we have to use the CERT_ID function to get to that value.

The output of CERTENCODED is a lengthy VARBINARY value:

CERTENCODED in Action.

Now we have a binary representation of our certificate. The next step is to turn that value into a certificate again. For that we can use yet another variation of the CREATE CERTIFICATE statement.

CREATE CERTIFICATE FROM BINARY

We have already seen two ways to create a certificate with different forms of the CREATE CERTIFICATE statement. The first form is the default. It generates a new certificate based on the values provided. The second form takes a DER formatted file following the X.509 standard as input and can be used to restore a certificate backup.

Now it is time to look at the third form of the CREATE CERTIFICATE statement. CREATE CERTIFICATE has a FROM BINARY clause that you can use to create a certificate for a binary value. The syntax looks like this:

[sql] CREATE CERTIFICATE [ACertificate] FROM BINARY = 0x308201AB30820114A003020102021035C0FB3E31F2929742E56FA4A197CC31300D06092A864886F70D01010505003014311230100603550403130941205375626A656374301E170D3134303531353137333331355A170D3135303531353137333331355A3014311230100603550403130941205375626A65637430819F300D06092A864886F70D010101050003818D00308189028181008A14AC241A0103E8BDBAD7AC3545AD0D5E11EC320CA7AED2F18BC001D42A3E4F35D0F67D69EF1E4CEF2281C773A3C916224761044445FA765F235C190E11BF9900961349194B5CE114B4ACA387F80ADDD92595AF8E020789C508BA64AA417850C40F266E09CA017AFF9273FD71FEDA3CA8B0FE6351998B4EFE65E50039381C4B0203010001300D06092A864886F70D010105050003818100108D1338D10F80FB63D70807B48942DAE4A4DC7648E2316D8F46FA12B60983EFD96900DC92934C0E1DFF185096A24468C6BC658E2D6FB32FE3C95DF5E70B07DFB476D287F65CD9DA1516F3F7EAB323142F30300386823EB6D72319BEDE748C21A552106CC9818817895078980276C56FCE42ACA9B66AE4AC6097E9D09179A875;
[/sql]

You just specify the certificate name and the binary value that you got for example by using the CERTENCODED function. The binary value has to be specified as a constant. You cannot directly create a certificate from a value in a variable.

Scripting a Certificate

Now that we have the two parts that are required to script a certificate, we can build a query to return the CREATE CERTIFICATE statement for a specific certificate:

[sql] SELECT 'CREATE CERTIFICATE ' +
QUOTENAME(C.name) +
' FROM BINARY = ' +
CONVERT(NVARCHAR(MAX),CERTENCODED(C.certificate_id),1) +
';' AS create_cmd
FROM sys.certificates AS C
WHERE C.name = 'ACertificate';
[/sql]

This query returns the CREATE CERTIFICATE statement for the specified certificate. However, as it is a query against the sys.certificates catalog view, you can certainly use it to script out all certificates too. You just have to remove the WHERE clause.

In the above single-certificate form the result of the query looks like this:

A generated CREATE CERTIFICATE statement.

What About The Private Key?

This entire article is only concerned with the public parts of the certificate. To also script and create the private key, additional functionality is required. However, in most situations, which require the same certificate in more than one database, copying just the public key is enough. How to also include the private key is topic of a later article.

Summary

Besides of generating a new certificate and creating one base on a file, the CREATE CERTIFICATE statement can be used to create a certificate based on a binary value. The CERTENCODED function can be used to generate such a binary value for an existing certificate.

Categories: Backup, Cryptography, General, Security
Tags: , , ,

One Response to CERTENCODED: How to Script your Certificates

  1. Pingback: CERTPRIVATEKEY: Scripting the Private Key of a Certificate - sqlity.net

Leave a Reply