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.
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:
IF(CERT_ID('ACertificate') IS NOT NULL) DROP CERTIFICATE ACertificate; GO CREATE CERTIFICATE ACertificate WITH SUBJECT = 'A Subject';
With the certificate in place, we can now use the CERTENCODED function:
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:
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.
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:
CREATE CERTIFICATE [ACertificate] FROM BINARY = 0x308201AB30820114A003020102021035C0FB3E31F2929742E56FA4A197CC31300D06092A864886F70D01010505003014311230100603550403130941205375626A656374301E170D3134303531353137333331355A170D3135303531353137333331355A3014311230100603550403130941205375626A65637430819F300D06092A864886F70D010101050003818D00308189028181008A14AC241A0103E8BDBAD7AC3545AD0D5E11EC320CA7AED2F18BC001D42A3E4F35D0F67D69EF1E4CEF2281C773A3C916224761044445FA765F235C190E11BF9900961349194B5CE114B4ACA387F80ADDD92595AF8E020789C508BA64AA417850C40F266E09CA017AFF9273FD71FEDA3CA8B0FE6351998B4EFE65E50039381C4B0203010001300D06092A864886F70D010105050003818100108D1338D10F80FB63D70807B48942DAE4A4DC7648E2316D8F46FA12B60983EFD96900DC92934C0E1DFF185096A24468C6BC658E2D6FB32FE3C95DF5E70B07DFB476D287F65CD9DA1516F3F7EAB323142F30300386823EB6D72319BEDE748C21A552106CC9818817895078980276C56FCE42ACA9B66AE4AC6097E9D09179A875;
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.
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:
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';
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:
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.
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.