<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>YABVE</title>
	<atom:link href="http://bwunder.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://bwunder.wordpress.com</link>
	<description>SQL stuff</description>
	<lastBuildDate>Fri, 17 Feb 2012 03:10:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='bwunder.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/9641dfae18fbc47185581060e30121f0?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>YABVE</title>
		<link>http://bwunder.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://bwunder.wordpress.com/osd.xml" title="YABVE" />
	<atom:link rel='hub' href='http://bwunder.wordpress.com/?pushpress=hub'/>
		<item>
		<title>T-SQL Cryptographic Patterns &#8211; part 2: Hotel Juliet</title>
		<link>http://bwunder.wordpress.com/2012/01/27/t-sql-cryptographic-patterns-part-2-hotel-juliet/</link>
		<comments>http://bwunder.wordpress.com/2012/01/27/t-sql-cryptographic-patterns-part-2-hotel-juliet/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 23:37:38 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/?p=348</guid>
		<description><![CDATA[SQL Server 2008 R2 Books Online clearly spells out why to consider the primary key as the authenticator when encrypting a column value in SQL Server: If an authenticator parameter is specified when data is encrypted, the same authenticator is &#8230; <a href="http://bwunder.wordpress.com/2012/01/27/t-sql-cryptographic-patterns-part-2-hotel-juliet/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=348&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>SQL Server 2008 R2 Books Online clearly spells out <em>why</em> to consider the primary key as the authenticator when encrypting a column value in SQL Server:</p>
<blockquote><p>If an authenticator parameter is specified when data is encrypted, the same authenticator is required to decrypt the data. At encryption time, a hash of the authenticator is encrypted together with the plaintext. At decryption time, the same authenticator must be passed to the decryption function. If the two do not match, the decryption will fail, indicating that the value has been moved since it was encrypted. <u>We recommend using the primary key of the table in which the result will be stored as an authenticator</u>. &#8211; <a title="http://msdn.microsoft.com/en-us/library/ms365192(v=sql.105).aspx" href="http://msdn.microsoft.com/en-us/library/ms365192(v=sql.105).aspx">http://msdn.microsoft.com/en-us/library/ms365192(v=sql.105).aspx</a>&nbsp;</p>
</blockquote>
<p>The authenticator effectively protects the data from substitution attack vectors. The encrypted column in one row cannot be substituted for that same column from another row if a unique authenticator column is used, e.g. the primary key, unless of course the attacker(s) know to move the primary key to. Granted, that has it&#8217;s own set of challenges but nonetheless <em>can be done</em>. Or, in some cases, could not the attack swap all columns except the encrypted column and the primary key to successfully perpetrate the attack this is supposed to prevent? It would surely come to the surface faster as the executive would suddenly get a laborers wage and squawk real loud. Further, in the BOL example where all rows contain personally identifiable information (PII) stored in clear text how much protection does encrypting one column provide anyway?</p>
<p>The &#8220;Authenticators&#8221; <a href="http://msdn.microsoft.com/en-us/library/ms365192(v=sql.105).aspx" target="_blank">page</a> referenced above seems to be removed from the SQL Server 2012 BOL. That is too bad. It needed to be strengthened not removed. Instead the keyword is now indexed to the EncryptByKey() <a href="http://msdn.microsoft.com/en-us/library/ms174361(v=sql.110).aspx" target="_blank">page</a> &#8211; that admittedly already had much of the same information, and I certainly understand the need to consolidate. The recommendation on the new landing page is somewhat different:</p>
<blockquote><p><u>We recommend using a column containing a unique and unchanging value as the authenticator.</u> </p>
</blockquote>
<p>I agree the authenticator must be unchanging but it still goes too far to one extreme to be the default usage or a dangerous recommendation without understanding the user data. Just as there are other possibilities as valid as using the primary key, there are other possibilities than a unique and unchanging value. Yes, there is protection from a cut-n-paste attack if a unique value is used as the authenticator. Is this also true if&nbsp; the letter &#8216;a&#8217; is always appended to the value before encrypting. Not quite. The encryption operation will a have a randomizing effect that could thwart the dictionary attacker by obfuscation even when a static salt is added, but it is portable to that column in any row that contains a value that can be decrypted using the same authenticator value &#8211; even without any nasty gyrations like trying to swap key values. This easily justifies the additional processing required to increase the uniqueness of the authenticator when compared to using a static value like &#8220;a&#8221;, but it does not <em>have</em> to be unique to realize the protection. Other values with high selectivity are also candidate authenticators. The less unique the authenticator the more resistant to dictionary attack in the stolen database scenario, the more unique the more resistant to a substitution attack. Somebody must finally decide the balance. Saves a lot of time if that happens before development begins. </p>
<p>The requirement that the value used for an authenticator cannot change too is a bit over zealous. All that is absolutely necessary is to re-create the cypher text using the authenticator&#8217;s new value when ever the authenticator column is updated. Not something you would want to do many times a second, but of far less consequence if done in a singleton query 1000-2000 times a day. The question to answer is how often the authenticator column is updated for all rows, not whether or not it is updated. Remember, the algorithm itself does the randomizing, not the uniqueness of the authenticator. </p>
<p>There is also a concern to me that when the authenticator is a clear text value stored with the data &#8211; regardless how unique -swapping the encrypted value and the authenticator or alternately all columns but those two could still be an effective attack. Furthermore, if the database or a backup is stolen, even a brute force attack could benefit from awareness that there are unique un-encrypted column(s) in the row &#8211; and even more if it is <em>known</em> which column is used as the authenticator. It is even something of a leg up for the database thief that the SQL Server documentation makes that exclusive recommendation. Doesn&#8217;t that make this configuration a likely vector for attackers? Maybe this has something to do with the removal of that Authenticators page for the documentation? I mean, if you use salt but it is not a secret, exactly how is that different than not using salt? And in particular in the stolen database scenario?</p>
<p>Imagine now that the first developer to write T-SQL encryption for an application either thinks a bit like me (poor bastard) or has no idea what to use for an authenticator so picks the only column that can be used as an authenticator parameter without a type conversion. For example, the Standard_Title column is chosen from the salary swapping example&#8217;s table included in the documentation pages referenced above instead of the primary key Employee_Id column. Standard Corporate Job Titles are not very likely to change and there is not likely to be a large number of folks with the same job title &#8211; but it can and does happen that people may share a job title. Then along comes someone that spots the discrepancy between what was done and what Microsoft recommended. Of course several people decide to weigh in on the matter and eventually someone decides what to do from here. Regardless the resulting interruption takes some time and slows the general progress of the application. Making such a change after the application is live can bring even more pain. </p>
<p>I intend to dig more into choosing and using authenticators in the next post in the series. This post must first turn more toward the burdens T-SQL encryption adds to foundational architectural decisions and application design: specifically in business continuity planning. This planning should be business reason focused and may include:</p>
<ul>
<ul>
<li>standards and compliance targets
<li>criteria for identifying crypto-technology candidates
<li>communication plan
<li>division of responsibility/ownership&nbsp;
<li>forward-recovery expectations<!--EndFragment-->
<li>SLAs
<li>key management</li>
</ul>
</ul>
<p>The&nbsp; Open Web Application Security Project&#8217;s (OWASP) &#8220;<a href="https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet#Rule_-_Define_a_key_lifecycle" target="_blank">Cryptographic Storage Cheat Sheet</a>&#8220;, for an example, may be a good general instrument to kick off the discussion. </p>
<p>Assuring the ability to change keys as required is essential. Disaster recovery is important but there are many requirements for key-changes that are not calamity based, e.g. key lifecycle, SLAs, compliance, key expiration, organizational security best practices, etc.; and some calamities requiring a key change that need not be a disaster, e.g., key corruption, newly uncovered vulnerabilities, intruders, hardware failures, etc..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>When a column in the row is used as the authenticator, all the machine pieces required to reverse engineer the cipher text are included in the database. And all full database backups also include the encryption key, the encrypted value and the authenticator. There may still be protection by passphrase, however that is most likely the easiest value to determine brutally. This is precisely the reason the database is not often the stage for encryption of application values. It is worthwhile to consider authorizing access to the encryption hierarchy through physical presentation of a fob, blob, key file or other public/private key-pair(s) that will never spend time in SQL Server. This affords more protection than a phrase but can also add to the security burden and adds some risk to recoverability.&nbsp; </p>
<p>One strength of the T-SQL authenticator parameter is that a <em>hash</em> of the authenticator value is encrypted with the value. It is not clear how this hashing operation compares to a HASHBYTES() operation. It is clear only that the relationship between the authenticator value and the encrypted value has to be based upon some system generated one-way digest of the authenticator so is more random than simple concatenation of the character &#8216;a&#8217; as salt or authenticator. An attacker may also need to reproduce the hashing operation applied to the authenticator to crack the encryption whether the key or any other value &#8211; no matter how static or random &#8211; is used as the authenticator.&nbsp; For better and worse, hashes are deterministic digests so results are reproduce-able on another SQL Server instance &#8211; if not anywhere and on-demand.</p>
<p>The completeness of the cryptographic keys revealed can be used to seed an attacker&#8217;s dictionary automation if the database is successfully stolen, though few details about the authenticator and the hashing operation used are exposed superficially. If the database is stolen or compromised with elevated authority access, all data &#8211; encrypted or not- should be considered compromised and appropriate action initiated.&nbsp; </p>
<p>Once a malicious user is able to connect to the database, especially with elevated authority, prevention of data theft is unlikely. Layers of authentication, authorization, firewalls, proxies and intrusion detection external to the database server are necessary. Audit , including Common Criteria or C2, and alerts offer only after-the-fact forensic protection and can also therefore also be manipulated maliciously from the inside with adequately elevated authority. It&#8217;s the old put a picture of an empty bank vault in front of the security camera while you clean the place out trick.&nbsp; </p>
<p>The best protection once data has been stolen or compromised through a valid database connection is cell level encryption&#8230; and perhaps self-destructing data &#8211; what ever that is.&nbsp; Knowing what needs to be done to change keys and how long it will take to re-key and get your application back on line when thusly compromised is of utmost importance to stop the breech in a live environment.&nbsp;&nbsp; </p>
<p>An example might be the Zappos breech of Jan 16, 2012 concerning the compromise of&nbsp; the address and last 4 digits of credit card from apparently all(?) 24 million customers. Check out the coverage in the <a href="http://www.theonion.com/articles/zappos-hacked,27082/" target="_blank">Onion</a>. Sounds like they only got unencrypted data to me. Maybe even only a replica in the DMZ if they are lucky? No way to tell for sure from here. People cannot change their address, the cards will all surely have to be replaced even if the encrypted credit card number was not also stolen. What good did it do to encrypt any data when enough to steal the identity was left exposed?</p>
<p>What I still wonder is if they notified the 24 million customers directly and if so what they said them? Or were these people left to find out the next time they swiped the card after being invalidated?</p>
<p>The ability to execute a complete coordinated re-key (aka HJ or <em>Hotel Juliet </em>to cold war cryptographers in the mid 20th century) is often among the best if not only available actions to close a breech. Application incorporating planned key rotation at the onset are superior in their ability to re-key on demand. Retrofitting a key rotation plan is likely to involve some time offline.&nbsp; </p>
<p>The need to figuring out how to rekey while under attack may be dooming. With the database there is no possibility to <em>go high &amp; blind</em> like they did back in the day to reset the keys manually. A forced re-key, i.e. without access to the old key, when data is stored in the database, will result in loss of all encrypted data. A safe re-key must re-encrypt cipher text using the old key to decrypt and the new key to encrypt. This can be a long running operation that may leave the database temporarily degraded or possibly temporarily unusable. </p>
<p>The need and urgency of communicating the breach to the data owners/customers is a clear and unequivocal responsibility.&nbsp; Without an established protocol this can be chaotic and often destructive for the organization that has been breached. Much better if individual responsibilities in such communications are clearly laid out in the plan. </p>
<p><strong>Planning&nbsp; Begins Now</strong></p>
<p>The bottom line is the same here as with most software design issues. Decisions made early are highly advantageous if correct or correct-able and very costly if incorrect or delayed. Depending upon the criticality and&nbsp; level of malicious interest in the data, a bad decision can be fatal. No security strategy should be the work of one mind or be implemented over night. The more perspectives that can be shed and experience gained with this topic before and while software is built, the more likely the end result will meet the requirements. Key rotation should be a measurable and measured task from the onset.</p>
<p>The front loaded thought of planning can consider many recovery scenarios.&nbsp; A retrofit key change instead must often have as its primary goal figuring out a way to pick up the pieces and get the application running again pronto. Another &#8211; perhaps more obtuse &#8211; way to say it: </p>
<ul>
<li>If you don&#8217;t <em>need </em>a business continuity focused forward recovery plan for your application, it is hard to imagine why you would bother with T-SQL encryption.
<li>If you don&#8217;t <em>have</em> a business continuity plan but <em>need</em> a forward recovery plan work on fleshing out the forward recovery plan as &#8211; or better yet before &#8211; you take on T-SQL encryption. </li>
</ul>
<p>Its also hard to image how a forward recovery plan for the application could be devised without an overarching business/organizational continuity plan unless the organization can absorb a whole lot of quickly made and often risky assumptions. </p>
<p><strong>Forward Recovery Considerations by Key Type</strong></p>
<p><strong>Service Master Key (SMK)</strong> &#8211; Even applications that do not think they use encryption in SQL Server may reply upon the SMK to encrypt linked server passwords. Backup of the SMK may be critical to forward recovery and should be one of the first post installation steps for most SQL Servers. DMKs, Certificates and Asymmetric keys need not be encrypted into the SQL Server Encryption Hierarchy, though the SMK will always be used to CREATE MASTER KEY of the database before any other encryption objects other than the DEK can be created in that database. The DMK can be configured without SMK encryption, but the CREATE DDL will only and always encrypt a copy of the DMK into the master database and use the provided phrase or key to encrypt a copy into the database, then an ALTER MASTER KEY DROP ENCRYPTION BY SERVICE MASTER KEY can remove the copy in master. (The documentation shows bogus options for dropping the encryption by phrase. It doesn&#8217;t work.)</p>
<p>In SQL Server 2012 the DPAPI uses an AES encryption algorithm. Does this mean SQL Server 2012 will use AES-NI (Xeon onboard hardware acceleration)? It is also an interesting upgrade scenario. An in-place upgrade to SQL Server 2012 RC0 leaves the old 3DES algorithm&#8217;s SMK in place. To upgrade to AES it is necessary to run ALTER SERVICE MASTER KEY REGENERATE. This can be a long running operation if TDE is enabled. Otherwise it could just be a matter of re-encrypting the copies of DMKs that are stored in master.</p>
<p>A side-by-side upgrade may be able keep most of the REGENERATE time off line if the re-key is coordinated with the migration. A simple example scenario would be to keep the old server on line in read-only mode for the REGENERATE phase, then go off-line a moment to switch to the new server when the upgrade is complete. It could well be that no matter what, if you want AES encryption after an upgrade there is going to be some down-time. Consider yourself warned on that one. It would be good for the business continuity forward recovery plan if it were used&nbsp; co Try to use the same process that is planned for periodic REGENERATEs. </p>
<p><a href="https://w2.eff.org/Privacy/Crypto/Crypto_misc/DESCracker/HTML/19980716_eff_des_faq.html" target="_blank">DES has been vulnerable a long time</a>. Triple DES is better but growing weaker by the day. In fact the expected life of AES was just over 15 years when they started thinking about it over 10 years ago and <a href="http://www.sciencemag.org/content/335/6066/303" target="_blank">blind quantum mechanics</a> &#8211; where the data is encoded onto photons &#8211; in cryptography is on the horizon. Today we can fit a bit in 12 bytes on an atom in the lab. More like a million bytes on your hard drive. </p>
<p>Consider a quarterly test restore of the SMK beginning soon after the application is ready for an integration testing environment and continue until the last row of sensitive data is no longer needed. That is too often to test a live system but the live system should still be tested to make sure the key backup is good each time it is REGENERATED. Once a year may not be often enough to REGENERATE to assure an aggressive attacker breaks your encryption&#8230;&nbsp; </p>
<p><strong>Database Encryption Key (DEK)</strong> &#8211; The DEK is encrypted by a certificate or asymmetric key in the master database. That certificate or key can be built with the SQL Server encryption hierarchy (SMK&#8211;&gt;DMK&#8211;&gt;private key of cert or asymmetric key), or from a file source(s), or externally managed key hierarchies using EKM.</p>
<p>Regeneration is always&nbsp; an online operation for the DEK. The documentation warns about a potential performance hit, but when data change happens one row at a time the added overhead may go unnoticed on a properly sized SQL Server. Pretty sure I read somewhere it is expected to be a 5-10% hit on CPU. Compare that to an ALTER INDEX REBUILD of about the same number of bytes as the data that must be re-encrypted in the ALTER MASTER KEY REGENERATE. Just a guess though. I did see <a href="http://1dotnet.wordpress.com/2009/12/07/rotating-sql-encryption-keys-in-ms-sql-server-2008/" target="_blank">Kevin Finke&#8217;s post</a> reporting about 46GB an hour to regenerate a DEK on SQL Server 2008 in late 2009, unknown hardware. He does not describe performance issues. Instead he shows the query he used to monitor the progress. </p>
<p>Like everything else about TDE, key re-generation is relatively painless compared to real cell level encryption. I hope only that data owners and DBAs are fully cognizant of the <a href="https://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/" target="_blank">features and foibles of TDE</a>&#8230;</p>
<p>One thing I really like about TDE is that you have to have the certificate used to create the DEK to restore the database on another server. All backups are encrypted when TDE is enabled in the database. And no matter where they are stored. This is about as safe as SQL Server databases backups can get. I say use it if you have it, but also consider file system encryption if you don&#8217;t. File system encryption can actually provide more protection. Everything, including swap files, cores, backups and all other user created files on the server that might unexpectedly expose the clear text of cipher text or other secrets when the server is shut down even thought the database backups cannot be used freely and anywhere. The biggest downside to file system encryption is that if a file if copied to an unencrypted network location the encryption is lost.</p>
<p><strong>Database Master Key (DMK)</strong> &#8211; The DMK shares no direct dependencies with the DEK. The DMK is always encrypted into the database by a phrase. As mentioned above, a copy of the key is encrypted into master by the SMK. This copy enables the DMK to automatically open when needed. Without the copy in master, the phrase must always be provided to open the DMK and use and cell encryption certificate that are encrypted by the DMK into the database. Conversely, the database without a DMK copy in master can be restored and used on another SQL Server and can provide privacy even from members of the <em>sysadmin</em> fixed server.</p>
<p>I have seen a few troubling search strings seeking information about the DMK that managed to find on my blog. Among them I can recall off hand:</p>
<blockquote><p>&#8220;deadlock symmetric_key_id = 101&#8243;</p>
<p>&#8220;steal database master key&#8221;</p>
</blockquote>
<p>Hopefully it is nothing to be concerned about. I certainly have not experienced a DMK deadlock to my knowledge. Of course to steal one all you need is ALTER DATABASE permissions to execute a BACKUP MASTER KEY.</p>
<p>A REGENERATE of a DMK will re-encrypt all dependent certificates, and keys. This too can be a long running process.</p>
<p>Like the DEK, the application should not have to interact directly with the DMK unless the copy in master is dropped. In that case it will have to be opened with the phrase before certificates encrypted by DMK can be opened.</p>
<p><strong>Certificates</strong> &#8211; T-SQL Certificates are X.509 public key/private key pairs. The BACKUP CERTIFICATE DDL is similar to the SMK and DMK. The big difference is that there are two files output from a certificate export: one for the public key, one for the private key. </p>
<p>DECRYPTBYCERT() and VERIFYSIGNEDBYCERT() requires only the public key. Encryption and Signing need to used the private key. Other T-SQL methods for checking signatures (IS_OBJECTSIGNED, sys.fn_check_object_signatures() ) may only be looking in the system catalog access to verify a signature. The private key must first be opened to SIGNEBYCERT() or ADD SIGNATURE. </p>
<p>If you only need a certificate for DECRYPTBYCERT() it is much safe to export the certificate then drop the private key. This alone can thwart the database thief from learning the secrets. For a certificate used to verify signatures, never drop the private key.&nbsp;&nbsp; </p>
<p>CREATE CERTIFICATE accepts a user specified <strong>[StartDate]</strong> and <strong>[ExpiryDate]</strong> however SQL Server does not do anything with the values other than store them and expose them. With T-SQL encryption, if you want rotation automation you must supply the mechanism to use these attributes. Not so much to know when it is time to rotate as a way to tell which is active in scenarios where it makes sense to rotate keys without the need to REGENERATE by using &#8216;virtual partitions&#8217; by certificate, perhaps aligned with database PARTITIONSs. The application will need to know which certificate is active only to encrypt data and for signing. T-SQL DECRYPTBYCERT and DECRYPTBYKEY will use the the correct key &#8211; but only if it is already open or does not need to be opened before use.&nbsp;&nbsp;&nbsp; </p>
<p>A <em>crypto-period</em> is an interval of time that a key should be available for use before it is considered too likely it has been compromised. Ideally this would be the information placed in the certificate&#8217;s date attributes A <em>crypto-period</em> is often taken &#8211; somewhat off-hand &#8211; to be 1 year. If that ever was more effective than the &#8220;duck and cover&#8221; nuclear defense strategy I was taught in second grade, it is not at this time. If I understand the evolution of things correctly, it looks like 1 year may originally have come from the arbitrary decision by the Certificate Authorities (CA) to collect an annual fee. While one year may have never have had much empirical relevance to key compromise risk, annual renewal is still often the norm, and still the fee interval. hmmm. I have a feeling the right interval for many (most?) security focused expirations could be somewhere on the short side of annually these days. That was probably way to frequent at the time the practice started. (Moore&#8217;s Law right?)</p>
<p>The <em>strength of any cryptographic key</em> is statistically known as the <em><a href="http://math.ucsd.edu/~crypto/java/ENTROPY/" target="_blank">Shannon Entropy</a>. </em> From that entropy, the time to guess the clear text of a cipher by brute force can be estimated. Just for example, Wikipedia estimates the time to unscramble data when a 56 bit encryption key is used as 1 second, the same algorithm with a 64bit key about 4 and half minutes and a 128 bit key almost 150 trillion years! This is oversimplified, but the far less costly 64 bit may still be useful for data that must live only a few seconds if the performance advantage out-weights the security risk. I am unable to even fabricate a valid scenario for a 56 bit key. However if the data is compelling to the attacker, parallel processing can cut all the times. Additionally, the reality is that some 128bit algorithms are in fact already broken: most through some variant of the padding oracle attack. Conversely, Seagate argues that 128 bit AES encryption is about equally beyond the ability of current technology to crack as 256 bit AES. That is evidence that the algorithm as a major role in key strength. And I have every reason to believe that there may be a better way than &#8220;the stronger and longer the better&#8221; some day. Until there are application performance concerns related to encryption overhead, &#8220;the stronger and longer the better&#8221; seems a better rule of thumb as far as I can tell. One thing is more clear: AES is the most widely recognized by government and industry standards. Still, I will not be surprised when someone publishes a previously unknown 60 second AES hack that works.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p><strong>Symmetric Keys</strong> &#8211; Symmetric keys can be encrypted by certificates, asymmetric keys or even other symmetric keys. These methods produce a key that cannot be moved to another SQL Server unless the entire database is moved. Symmetric keys can also be created by specifying the source and identity attributes. This technique can be used to produce the same symmetric key on two or more instances or 2 or more database of the same instance. However, this is not recognized &#8211; even by the often overly generous BOL documentation &#8211; for producing a key with particularly strong entropy.&nbsp;&nbsp; </p>
<p>I repeat, there is no BACKUP SYMMETRIC KEY statement in T-SQL. Don&#8217;t plan on moving a symmetric key to another instance unless you move the complete database. Symmetric keys are remarkably faster than encryption/decryption by certificate. </p>
<p><strong>Asymmetric Keys</strong> &#8211; Asymmetric keys are similar to certificates. I don&#8217;t think this is true in other settings, but in SQL Server the asymmetric key is the functional equivalent of the certificate. They require different sources from which the public/private key pair is built. Certificates must be imported from X.509 certificate files while asymmetric keys can come from strong named assemblies, executables, key files and CRYPTOGRAPHIC PROVIDERS (EKM). Unlike the certificate, an asymmetric key is not an x.509 compliant key pair format. Like the certificate the asymmetric key is and RSA public/private key pair. Like the symmetric key, there is no BACKUP ASYMMETRIC KEY statement.</p>
<p><a href="http://blogs.msdn.com/b/lcris/archive/2006/03/13/550904.aspx" target="_blank">This</a> Laurentiu Cristofor SQL 2005 SQL Security blog post recommends certificates over asymmetric keys mostly because the certificate can be export. That is an advantage for both forward recoverability and the database thief. </p>
<p align="center">-</p>
<p>No matter what the the technical details for any patterns used to encrypt, sign or hash a cell it is critical to first establish the overarching forward recoverability guidance. Skipping this step guarantees a waterfall methodology for data protection. That is about where we are today: locked in an endless dance between breaches and patches that (try to) protect as much as possible against the last beach. The details may not be reachable in early design but without a framework they may never be reached. </p>
<p>One critical benefit of planning your stay at the <em>Hotel Juliet</em> is a chance to experience, and ideally eliminate,&nbsp; your weaknesses <em>before</em> you lose your data. A significant improvement over what most have now.&nbsp;&nbsp;&nbsp; </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/348/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/348/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/348/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=348&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2012/01/27/t-sql-cryptographic-patterns-part-2-hotel-juliet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>T-SQL Cryptographic Patterns &#8211; Part 1: hashed, scrambled or over easy?</title>
		<link>http://bwunder.wordpress.com/2011/12/31/t-sql-cryptographic-patterns-part-1-hashed-scrambled-or-over-easy/</link>
		<comments>http://bwunder.wordpress.com/2011/12/31/t-sql-cryptographic-patterns-part-1-hashed-scrambled-or-over-easy/#comments</comments>
		<pubDate>Sun, 01 Jan 2012 03:48:15 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Backups]]></category>
		<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/?p=336</guid>
		<description><![CDATA[Even for the laggards among us, the time to recognize that we have not been building adequate security into most data stores is long past. Now is the time to set things straight. Predictably, mastery of the fundamentals is almost &#8230; <a href="http://bwunder.wordpress.com/2011/12/31/t-sql-cryptographic-patterns-part-1-hashed-scrambled-or-over-easy/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=336&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Even for the laggards among us, the time to recognize that we have not been building adequate security into most data stores is long past. Now is the time to set things straight. Predictably, mastery of the fundamentals is almost all of what is needed. </p>
<p>Consider the principals that are consistently left undercooked in database applications in purported pursuit of the performance and usability Sasquatch: </p>
<ul>
<li><em>set-based processing</em>
<li><em>audit</em>
<li><em>principle of least privilege</em>
<li><em>defense-in-depth</em>&nbsp;
<li><em>division of responsibility</em>
<li><em>protection for sensitive data </em></li>
</ul>
<p>Not only is this application ruining bigfoot an indefensible justification for reduced security, but strong data security need not inhibit performance, usability or innovation. These principals are far too important to a good outcome to forego. We so easily get caught up in making and managing the organizational bias between strong security and best usability that we loose sight of the real possibility to have both. Seems to me that most of us would prefer to wait for the careful transaction at the bank or store or pharmacy&nbsp; &#8211; even if impatiently &#8211; than to find out we are 5 bucks short or just swallowed a capsule of wart remover compound expecting it to be prescription pain medication. About the same is true for software. Methodical secure processing is the most direct route to secure results all other things being equal.</p>
<p>(Instead, two slight imperfections in the legacy from our base ancestral instincts expose our economic system as as unsustainable as any other. Greed and corruption rear their heads to value Capitalist dogma (e.g. cash flow, P/E&nbsp; and <a href="https://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/" target="_blank">me too features</a>) above innovation and fundamental security obligations. Compliance becomes an ever more ineffective stand-in for security. The difference between leaders and shady followers, swindlers and <a href="http://cassiopaea.com/cassiopaea/psychopath.htm" target="_blank">psychopaths</a> blurrs. But I digress&#8230;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>Cryptographic methods will generally be leavened and baked into the security disciplines listed above to create patterns in the application. Cryptography from the Windows perspective is a set of low level system services known collectively as the CryptoAPI. SQL Server relies upon the CryptoAPI for all intrinsic encryption capabilities. The implementation of these services is an application decision. Furthermore &#8211; and <em>almost</em> without exception &#8211; if there is a choice between encrypting in the application layer or encrypting at the data layer using T-SQL, encrypting at the application layer has at least a couple of advantages in security.&nbsp; </p>
<ol>
<li>Encrypting sensitive data at the <em>moment of origination</em> is the best moment to confidently prevent leaks of the clear text value.
<li>Encryption certificates and keys are stored <em>with</em> the encrypted data in SQL Server. </li>
</ol>
<p>Data that originates at the database may indeed be better encrypted at the database. That is just not where most data comes from. Data that enters the system in bulk may also be candidate for encryption at the database layer but I have to wonder why it isn&#8217;t encrypted already if it needs to be encrypted upon bulk load? In this last case the larger security burden may be assuring the secure import of an encryption key to first decipher such data before scrambling it with the local key. Most data cannot quite meet the test of proximity to origin when encrypted at the database server. User entered data is best encrypted and decrypted only while in the context of a man-in-the-middle protected session where an authorized user enters, requests or otherwise requires access to the clear text data. To be in the<em> moment of origination</em> all transactions are best committed or rolled-back at or within the context of that user&#8217;s secure and encrypted session i.e. SSL, IPSEC, etc.. </p>
<p>If a T-SQL encrypted database is stolen or compromised, the thief gets the keys <em>and</em> the data. EKM, and to a lesser extent keys that require a very strong and well protected phrase to open weaken this argument favoring application layer cell encryption via a secure encryption services layer (HSM, encryption appliance, certificate authority, etc.) over T-SQL with the keys stored in the database and encrypted under the Service Master Key. Another challenge for keys that live with the data is restore-recovery. Restores may be undermined or made more complex by necessary key rotation practices. Unresolvable overlaps in the division of responsibility may arise when encryption uses keys from the database. On the other hand key rotation can be easily automated for off hours and there will be no gaps in responsibility if at least some of the DBA staff controls both keys and data. </p>
<p>The CryptoAPI functionality available to T-SQL consumption is actually quite narrow when compared to the universe of properties, methods and objects exposed by the CryptoAPI. That is good and bad. It means there are limits to what can be done in T-SQL. It also means most developers will not find the learning curve to get productive and effective with T-SQL encryption too steep. Also T-SQL encryption&#8217;s advantage, it allows and supports piecemeal implementation and includes a number of features and options that may be appealing when tenable: </p>
<ul>
<li>Familiar T-SQL object administration and DDL syntax
<li>Built-in cryptographic functions
<li>Selection of encryption algorithm&nbsp;
<li>Auto-decryption of the Database Master Key for authorized users by default&nbsp;&nbsp;&nbsp;
<li>Keys and certificates included in all full database backups&nbsp;&nbsp;
<li>More efficient utilization of CPU resources on the typically underutilized CPUs of dedicated SQL Server database servers
<li>Optional passphrase only decryption of the Database Master Key for division of responsibility fidelity that overrides both database and local administrator authority</li>
</ul>
<p>What I most wish to convey in this series, are some recipes for baking encryption into T-SQL. This is done with the presumption that you have fairly weighed all application layer alternatives and come to the empirical decision that T-SQL encryption is right for your application. </p>
<p>All examples are from SQLClue&#8217;s Encryption Hierarchy Backup &amp; Restore that uses SQL Azure for secure offsite storage. The installer is a not much more than than a check list and a few T-SQL scripts at this time so can be installed without any other SQLClue components. I&#8217;ll include snippets from the installer to demonstrate several cryptographic implementation patterns. To see how the pattern is fully implemented, review the T-SQL or install the Encryption Hierarchy Backup &amp; Restore component script in an evaluation SQL Server 2012 environment to create the schema. You can download a zip file or grab a fork of my SSMS project at <a title="https://github.com/bwunder/EHAdmin" href="https://github.com/bwunder/EHAdmin">https://github.com/bwunder/EHAdmin</a>.</p>
<p>Most data originates in the database in this application so it meets the sniff test for using T-SQL cryptography. The schema is based upon the script in the <a href="https://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/" target="_blank">Encryption Hierarchy Administration</a> post. That script made only limited use of encryption. In the version now under consideration, the cryptography yields a translucent database state: where even the sysadmin role members need not have a clear text view of all data. This is very powerful with regard to establishing an enforceable separation of responsibilities. </p>
<p><a href="http://bwunder.files.wordpress.com/2012/01/separationofresponsibilites.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="SeparationOfResponsibilites" border="0" alt="SeparationOfResponsibilites" src="http://bwunder.files.wordpress.com/2012/01/separationofresponsibilites_thumb.png?w=658&#038;h=471" width="658" height="471"></a>
<p>The example application is also interesting because it uses SQL Azure for secure offsite storage. It does involve a trick: exporting certificate and key backups to an encrypted VHD and then importing the VHD&#8217;s container file into the database to move it to a central SQL Azure hub for safekeeping and recall on demand. SQL Azure is a reasonably secure offsite repository for the heterogeneous layers of encryption bundled around the data <em>before</em> it is sent offsite:</p>
<ul>
<li>The container file for the VHD is encrypted by a key file or phrase. Once dismounted and loaded into the database it cannot be mounted from the database location. It must be restored to the file system and the phrase or key file required supplied just to get visibility of the backup files.
<li>The certificate and key export files are encrypted onto the VHD by a phrase with a strong &#8211; and configurable &#8211; phrase strength policy. Once written to the VHD the phrase is required to open.&nbsp;
<li>The copy of the user database&#8217;s Database Master Key is dropped from the master database. When this copy is removed, an application enforced strength policy compliant phrase must be provided.
<li>All key and certificate exports created are encrypted into the output file using a key that meets the application enforced strength policy.
<li>All keys and certificates used by the application require a key or certificate to be open that can only be opened by providing a strength policy compliant phrase to open the Database Master Key, a certificate or a symmetric key. </li>
</ul>
<p>The <em>sysadmin</em> running the install can select either change tracking or change data capture on supported SKUs along with a linked server to an ODBC DSN. The DSN can point directly to a SQL Azure instance or to a locally configured hub and then SQL Azure&#8217;s Sync services used to maintain the offsite mirror of all keys and certificates in local environment(s). With the ODBC option the secure offsite can as easily be SQL Azure as another database on the local network or a private cloud location that serves as a hub for <em>n</em> number of SQL Server&#8217;s. The offsite schema does not require any ability to encrypt or decrypt data. In fact the data on the hub may be comingled with rows from other SQL instances that use different keys. This allows a common storage and recovery scheme at the hub to support multiple SQL instances with an ability to prevent one instance from accessing artifacts taken from another instance &#8211; unless you explicitly ask for it that way.&nbsp;&nbsp; </p>
<p><u>some proposed encryption rules of thumb</u></p>
<p>Use symmetric keys for cell encryption/decryption in T-SQL. Symmetric keys add far less overhead to IO processing than public key/private key encryption/decryption with a certificate or asymmetric key. Instead use the certificate or asymmetric key to encrypt a symmetric key.&nbsp; </p>
<p>Use each key and certificate for only one purpose. Sure you can do it all with one key but if that key is compromised, the entire data set is compromised. In this usage you might have one certificate with a sole purpose of encrypting symmetric keys used for cell encryption and under that certificate might be a symmetric key for each encrypted column. </p>
<p>Never trust a DML object to verify its own signature. There is no way to get a monolithic procedure to reliably tell you if its signature is in place. If hacked in an elevation of authority or insider attack, what&#8217;s to stop the hacker that modifies the stored procedure from saying the signature is just fine even if now gone? For elevated security at the database to validate the authenticity of stored procedure all stored procedures are built WITH ENCRYPTION, each stored object, e.g., stored procedure, function, trigger, view, is signed and all stored procedures call a second stored procedure also protected by WITH ENCRYPTION and a signature from the same certificate as the called stored procedure that shares the validation processing with the primary called stored procedures. The processing cannot proceed unless this two part schema authentication processing succeeds.</p>
<p><u>design objectives </u></p>
<p>The main purpose of this application is in making sure no database objects are surreptitiously added, modified or removed from the schema to assure the integrity of the data.&nbsp; The aim is to create a background server side application that is able to enforce a division of responsibilities among administrators. Unauthorized users, even if they can connect to the SQL instance as a member of the <em>sysadmin</em> server role, cannot access stored secrets used to create the key and certificate backups because they are unable to open the Database Master Key. In contrast, authorized administrators can also chose to store additional secrets in the secure passphrase manager and to password protect any private secrets as desired. File system paths are also encrypted to thwart unauthorized user&#8217;s from mapping files to database objects. </p>
<p>Even if someone does figure out which files(s) there are after, they will still need the phrases used for backup encryption of each to load the key and then perhaps even another phrase to open the key.&nbsp;&nbsp; </p>
<p><u>patterns covered in upcoming posts</u></p>
<ul>
<li>Column encryption using the primary key column as authenticator
<li>Column encryption with clear text of another encrypted column in the row as authenticator
<li>Schema object signing run-time verification&nbsp;
<li>Using WTH ENCRYPTION to safely embedded certificate phrases in stored procedures&nbsp;&nbsp;
<li>Hashing a random seed to generate a random salt.
<li>Authenticating by a hash re-using a salt persisted to an encrypted column (secret salt)&nbsp;&nbsp;
<li>Encryption of passed variables into the audit trail as data administrators and developers cannot decrypt because they cannot access the phrase encrypted key.&nbsp;
<li>In-flight row signature for message authentication and schema validation
<li>TRY-CATCH error event data encryption to prevent unauthorized access and attack vector exploitation of exception information&nbsp;
<li>Sharable symmetric key that can be implemented on many instances and securely conveyed by a combination of phrase, fob and/or file&nbsp;&nbsp;
<li>In-flight encryption in a table variable/table valued parameter
<li>Signing rows in sys.messages (or any other system or user table)
<li>Signing a file&#8217;s VARBINARY(MAX) image<!--EndFragment--></li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/336/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/336/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/336/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=336&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/12/31/t-sql-cryptographic-patterns-part-1-hashed-scrambled-or-over-easy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2012/01/separationofresponsibilites_thumb.png" medium="image">
			<media:title type="html">SeparationOfResponsibilites</media:title>
		</media:content>
	</item>
		<item>
		<title>Throw FORMATMESSAGE() in the SQL Server 2012 Tool Bag</title>
		<link>http://bwunder.wordpress.com/2011/11/16/throw-formatmessage-in-the-sql-server-2012-tool-bag/</link>
		<comments>http://bwunder.wordpress.com/2011/11/16/throw-formatmessage-in-the-sql-server-2012-tool-bag/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 20:48:18 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Code Review]]></category>
		<category><![CDATA[FORMATMESSAGE()]]></category>
		<category><![CDATA[TRY-CATCH]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/11/16/throw-formatmessage-in-the-sql-server-2012-tool-bag/</guid>
		<description><![CDATA[SQL Server 2012 chucks THROW into Try-Catch block error handling brewery. Throw is designed as part of the TRY-CATCH contraption giving THROW the ability to reliably relay an exception down the T-SQL call stack. However, the inability of a THROWn &#8230; <a href="http://bwunder.wordpress.com/2011/11/16/throw-formatmessage-in-the-sql-server-2012-tool-bag/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=313&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>SQL Server 2012 chucks <a href="http://msdn.microsoft.com/en-us/library/ee677615(v=SQL.110).aspx">THROW</a> into Try-Catch block error handling brewery. Throw is designed as part of the TRY-CATCH contraption giving THROW the ability to reliably relay an exception down the T-SQL call stack. However, the inability of a THROW<em>n</em> message to accept replacement values is a show stopper without FORMATMESSAGE() in the current implementation.</p>
<p><em>FORMATMESSAGE() will see more utilization as THROW catches on.</em></p>
<p>T-SQL&#8217;s FORMATMESSAGE() function is too often overlooked anyway. The script below shows that the Denali <strike>CTP3</strike>RC0 FORMATMESSAGE() is a little different beast than we&#8217;ve had before. Looks like it gets a lot more like a .NET String.Format() method. For one thing, it lets me stuff CASE and system functions in the parameter list with abandon. (If it would let me pass a column or variable from the local database as the format string it would be even better. I can work around that with nesting, i.e. FORMATMESSAGE() can be used in a parameter of a FORMATMESSAGE()).&nbsp; More noticeably, it allows me to specify a format string in addition to referencing a<em> message_id</em> in <strong>sys.messages</strong>. Not that there would be anything you could do with the formatting string that you cannot do in <strong>sys.messages</strong>, just that <strong>sys.messages</strong> is in <strong>master</strong><em> </em>so using messages from the table binds the application to the SQL instance. FORMATMESSAGE() has long been effective way to assure type when you must combine disparate types into a single NVARCHAR value. FORMATMESSAGE() will see more utilization as THROW catches on. Error messaging, e.g. RAISERROR(), is the obvious use case. So much so that it is easy to overlook other great places to benefit from a low level (high performance?) system method:</p>
<ul>
<li>code generation
<li>dynamic SQL (almost the same principles as code generation)
<li>cryptography &#8211; FORMATMESSAGE() can be used in-line as the clear text or authenticator but <a href="http://msdn.microsoft.com/en-us/magazine/cc163523.aspx" target="_blank">no implicit conversions like QUOTENAME() or REPLACE()</a>
<li>output formatting &#8211; columns can be aligned and trimmed for display
<li>display formatting (almost the same principles as output formatting)&nbsp;
<li>messaging &#8211; a native alternative to XML
<li>logging&nbsp;
<li>data cleansing
<li>data conversion </li>
</ul>
<p>Of course the most important usage will continue to be in error handling.</p>
<p><em>November 24 Update &#8211; the T-SQL in this post continues to work with the RC0 bits (11.0.1750.32) but still no update to the documentation confirming any new powers for FORMATMESSAGE().</em></p>
<p>Application stored procedures that experience runtime <em>type</em> and <em>conversion</em><strong> </strong>exceptions are good candidates for FORMATMESSAGE() conformity. My personal favorite example <em>conversion</em> exception in this moment is:</p>
<pre class="code"><span style="color:blue;">SELECT </span><span style="color:magenta;">CAST</span><span style="color:gray;">(-</span>1234567890 <span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>10<span style="color:gray;">) )
</span></pre>
<p>which returns only the error message;</p>
<p><font color="#ff0000">Msg 8115, Level 16, State 2, Line 1<br />Arithmetic overflow error converting expression to data type nvarchar.</font></p>
<p>Cracks me up! At the same time it is embarrassing to admit how often I have cast INTs to VARCHAR(10)s for formatting into a string. Negative numbers less than -999999999&nbsp; need 11 characters for display. I have benignly ignored this fact for years. I remain confounded about how that is an arithmetic overflow though.</p>
<p>The same problem using FORMATMESSAGE() instead of&nbsp; the mushy SQL Server native type system is no problem at all.</p>
<pre class="code"><span style="color:blue;">SELECT </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%d'</span><span style="color:gray;">,-</span>1234567890<span style="color:gray;">);
</span></pre>
<p>and the result is -1234567890 of type NVARCHAR.</p>
<p>FORMATMESSAGE() also adds protection against the escape sequence or truncation attack vectors that aim to execute malicious T-SQL.</p>
<p><strong>Is This Really FORMATMESSAGE()?</strong></p>
<p>The documentation is very clear that FORMATMESSAGE works only with messages stored in sys.messages. The Denali documentation is not changed from the SQL Server 2008 documentation &#8211; so far. Nonetheless, the example successfully uses a message string instead of a message_id even though it is not documented to do so:</p>
<pre>FORMATMESSAGE ( msg_number , [ param_value [ ,...n ] ] )</pre>
<p>Notice that there is no option for text instead of a <em>msg_number</em>. Denali <strike>CTP3</strike> RC0 Books OnLine even adds a special Note, &#8220;FORMATMESSAGE works only with messages created using <strong>sp_addmessage</strong>,&#8221; yet here I am with the CTP3 able to use a message instead. I guess that says things could change by RTM. On a SQL Server 2008 instance The script below will fail with the message</p>
<p><font color="#ff0000">Msg 8116, Level 16, State 1, Line 17<br />Argument data type varchar is invalid for argument 1 of formatmessage function.</font></p>
<p>As mentioned earlier, SQL Server 2012 introduces <a href="http://msdn.microsoft.com/en-us/library/ee677615(v=SQL.110).aspx">THROW</a> for use in Try-Catch blocks. A THROW statement or a system generated error in the TRY block transfers control to the CATCH BLOCK.&nbsp; That&#8217;s about like RAISERROR. A THROW in the CATCH block throws the error down the call stack. Again no so difficult to get that behavior out of RAISERROR. <em>The real difference is most obvious when an unexpected exception occurs in the CATCH block. A RAISERROR implementation is likely to throw that error on the floor while a THROW implementation will abort the batch.</em> FORMATMESSAGE() may get more attention as THROW catches on, especially given the more elegant, i.e. less prone to failure and exploitation usage profile when unexpected data is encountered.</p>
<p>THROW does not support the <em>printf</em> formatting available with RAISERROR at all. Denali Books-On-Line &#8211; the web version &#8211; shows an example using the FORMATMESSAGE() function to format a message_id from <strong>sys.messages</strong> before passing it to the THROW.</p>
<p>FORMATMESSAGE(), at least in the guise of RAISERROR() has been in the database engine throughout the evolution of SQL Server. In SQL Server 2005/2008/2012 FORMATMESSAGE offers some help to &#8216;load&#8217; up to 20 values of disparate type into an NVARCHAR. It is necessary to specify the type of the inputs using a subset of the <em>printf </em>formatting codes of the standard C language. (read all about <em>printf</em> in your favorite <em>C </em>header <em>- hint: search local drives for a file containing the text &#8220;#define printf&#8221;)</em>.</p>
<p align="left">Binary data remains more difficult to work with. More examples in the documentation would probably be helpful.</p>
<p align="left">As an example, here is a FORMATMESSAGE testing script that uses FORMATMESSAGE to &#8216;dog food&#8217; FORMATMESSAGE statements for each of the 42 combinations of printf <em>flag</em> and <em>type</em> supported by SQL Server.&nbsp; Specify a value to match the data you supply, the @Type of that data and the desired @Format of the output string format:</p>
<pre style="width:596px;height:965px;" class="code"><span style="color:green;">-- printf formatting  %[[flag][width][.precision]]type
</span><span style="color:blue;">DECLARE </span><span style="color:teal;">@Format </span><span style="color:blue;">CHAR</span><span style="color:gray;">(</span>1<span style="color:gray;">)         = </span><span style="color:red;">''   </span><span style="color:green;">-- '',+,-,0,#,' '
      </span><span style="color:gray;">, </span><span style="color:teal;">@Width </span><span style="color:blue;">INT              </span><span style="color:gray;">= </span>6    <span style="color:green;">-- display field size
      </span><span style="color:gray;">, </span><span style="color:teal;">@Precision </span><span style="color:blue;">INT          </span><span style="color:gray;">= </span>3    <span style="color:green;">-- characters to display
      </span><span style="color:gray;">, </span><span style="color:teal;">@Type </span><span style="color:blue;">CHAR</span><span style="color:gray;">(</span>1<span style="color:gray;">)           = </span><span style="color:red;">'X'  </span><span style="color:green;">-- s, d, i, u, o, x, X
      </span><span style="color:gray;">, </span><span style="color:teal;">@Binary </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>128<span style="color:gray;">)  = </span>0x1239
      <span style="color:gray;">, </span><span style="color:teal;">@Int </span><span style="color:blue;">INT                </span><span style="color:gray;">= </span>11
      <span style="color:gray;">, </span><span style="color:teal;">@String </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>128<span style="color:gray;">)   = </span><span style="color:red;">N'test'</span><span style="color:gray;">;
</span><span style="color:blue;">DECLARE </span><span style="color:teal;">@$QL </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>256<span style="color:gray;">) = ( </span><span style="color:blue;">SELECT </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(
</span><span style="color:red;">N'SELECT FORMATMESSAGE(''%%s --&gt;%%%s*.*%s&lt;--'', @$QL, %i, %i, %s)'
                      </span><span style="color:gray;">, </span><span style="color:teal;">s</span><span style="color:gray;">.</span><span style="color:teal;">Flag
                      </span><span style="color:gray;">, </span><span style="color:teal;">f</span><span style="color:gray;">.</span><span style="color:blue;">Type
                      </span><span style="color:gray;">, </span><span style="color:teal;">@Width
                      </span><span style="color:gray;">, </span><span style="color:teal;">@Precision
                      </span><span style="color:gray;">, </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'s'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'''%s'''</span><span style="color:gray;">, </span><span style="color:teal;">@String</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'d'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%d'</span><span style="color:gray;">, </span><span style="color:teal;">@Int</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'i'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%i'</span><span style="color:gray;">, </span><span style="color:teal;">@Int</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'u'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%u'</span><span style="color:gray;">, </span><span style="color:teal;">@Int</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'o'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%o'</span><span style="color:gray;">, </span><span style="color:teal;">@Int</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'x'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%x'</span><span style="color:gray;">, </span><span style="color:teal;">@Binary</span><span style="color:gray;">)
                             </span><span style="color:blue;">WHEN </span><span style="color:teal;">@Type </span><span style="color:gray;">= </span><span style="color:red;">'X'
                             </span><span style="color:blue;">THEN </span><span style="color:magenta;">FORMATMESSAGE</span><span style="color:gray;">(</span><span style="color:red;">'%X'</span><span style="color:gray;">, </span><span style="color:teal;">@Binary</span><span style="color:gray;">)
                             </span><span style="color:blue;">END </span><span style="color:gray;">)
   </span><span style="color:blue;">FROM </span><span style="color:gray;">(</span><span style="color:blue;">SELECT           </span><span style="color:gray;">(</span><span style="color:red;">''</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:teal;">Flag
         </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'+'</span><span style="color:gray;">)
         </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'-'</span><span style="color:gray;">)
         </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'0'</span><span style="color:gray;">)
         </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'#'</span><span style="color:gray;">)
         </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">' '</span><span style="color:gray;">) ) </span><span style="color:blue;">AS </span><span style="color:teal;">s
   </span><span style="color:gray;">CROSS JOIN (</span><span style="color:blue;">SELECT           </span><span style="color:gray;">(</span><span style="color:red;">'s'</span><span style="color:gray;">) </span><span style="color:blue;">AS Type
               UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'d'</span><span style="color:gray;">)
               </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'i'</span><span style="color:gray;">)
               </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'u'</span><span style="color:gray;">)
               </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:red;">'o'</span><span style="color:gray;">)
               </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:magenta;">LOWER</span><span style="color:gray;">(</span><span style="color:red;">'x'</span><span style="color:gray;">))
               </span><span style="color:blue;">UNION </span><span style="color:gray;">ALL </span><span style="color:blue;">SELECT </span><span style="color:gray;">(</span><span style="color:magenta;">UPPER</span><span style="color:gray;">(</span><span style="color:red;">'X'</span><span style="color:gray;">)) ) </span><span style="color:blue;">as </span><span style="color:teal;">f
   </span><span style="color:blue;">WHERE </span><span style="color:magenta;">CHARINDEX</span><span style="color:gray;">(</span><span style="color:teal;">@Format</span><span style="color:gray;">,</span><span style="color:teal;">s</span><span style="color:gray;">.</span><span style="color:teal;">Flag</span><span style="color:gray;">) &gt; </span>0
   <span style="color:gray;">AND </span><span style="color:magenta;">ASCII</span><span style="color:gray;">(</span><span style="color:teal;">f</span><span style="color:gray;">.</span><span style="color:blue;">Type</span><span style="color:gray;">) = </span><span style="color:magenta;">ASCII</span><span style="color:gray;">(</span><span style="color:teal;">@Type</span><span style="color:gray;">) );
</span><span style="color:blue;">EXEC </span><span style="color:maroon;">sp_executesql </span><span style="color:teal;">@$QL</span><span style="color:gray;">, </span><span style="color:red;">N'@$QL NVARCHAR(256)'</span><span style="color:gray;">, </span><span style="color:teal;">@$QL</span><span style="color:gray;">;</span></pre>
<p align="left">You get the statement generated and the result as output. A few of samples:</p>
<ul>
<li><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;% *.*X&lt;&#8211;&#8217;, @$QL, 6, 3, 1239)&nbsp;&nbsp; &#8211;&gt;&nbsp;&nbsp; 4D7&lt;&#8211;</font>
<li><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;%#*.*x&lt;&#8211;&#8217;, @$QL, 10, 6, 1239)&nbsp; &#8211;&gt;&nbsp; 0x0004d7&lt;&#8211;</font>
<li>
<div align="left"><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;%-*.*o&lt;&#8211;&#8217;, @$QL, 6, 3, 13)&nbsp;&nbsp;&nbsp;&nbsp; &#8211;&gt;015&nbsp;&nbsp; &lt;&#8211;</font></div>
<li>
<div align="left"><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;%0*.*d&lt;&#8211;&#8217;, @$QL, 10, 6, 11)&nbsp;&nbsp;&nbsp; &#8211;&gt;&nbsp;&nbsp;&nbsp; 000011&lt;&#8211;</font></div>
<li>
<div align="left"><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;% *.*d&lt;&#8211;&#8217;, @$QL, 3, 6, 11)&nbsp;&nbsp;&nbsp;&nbsp; &#8211;&gt; 000011&lt;&#8211;</font></div>
<li>
<div align="left"><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;%+*.*i&lt;&#8211;&#8217;, @$QL, 4, 7, 11)&nbsp;&nbsp;&nbsp;&nbsp; &#8211;&gt;+0000011&lt;&#8211;</font></div>
<li>
<div align="left"><font size="2" face="Lucida Console">SELECT FORMATMESSAGE(&#8216;%s &#8211;&gt;%+*.*s&lt;&#8211;&#8217;, @$QL, 6, 3, &#8216;test&#8217;) &#8211;&gt;&nbsp;&nbsp; tes&lt;&#8211;</font></div>
</li>
</ul>
<p align="left">You can paste the result into a query window, change @$QL to <em>blank</em> or &#8216;test&#8217; and try similar scenarios to fine tune or develop into more complex FORMATMESSAGE statements.</p>
<p align="left">Too bad the script doesn&#8217;t work in SQL Server 2008&#8230;</p>
<p align="left">Here is a script that generates a BACKUP CERTIFICATE statement. The point would be to store passwords and other sensitive values as ciphered-text yet be able to use them when needed, e.g. you&#8217;d want to be able to recall the passwords in the event a forward recovery from a corrupted certificate is needed.</p>
<pre style="width:593px;height:2296px;" class="code"><font size="2"><span style="color:green;">--------------------------------------------------------------------------
-- Using FORMATMESSAGE to generate BACKUP CERTIFICATE STATEMENT
--------------------------------------------------------------------------
-- user defined table type for encrypted name/value pair
</span><span style="color:blue;">IF </span><span style="color:magenta;">TYPE_ID</span><span style="color:gray;">(</span><span style="color:red;">'NAMEVALUETYPE'</span></font><font size="2"><span style="color:gray;">) IS NULL
  </span><span style="color:blue;">CREATE TYPE </span><span style="color:teal;">NAMEVALUETYPE </span></font><font size="2"><span style="color:blue;">AS TABLE
      </span><span style="color:gray;">( </span><span style="color:teal;">Name </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000</font><font size="2"><span style="color:gray;">) NOT NULL
      , </span><span style="color:teal;">Value </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000</font><span style="color:gray;"><font size="2">) NOT NULL );
</font></span><span style="color:blue;"><font size="2">GO
</font></span><font size="2"><span style="color:green;">--temp key available to session only until session is closed
--not useful for persisted data unless source,identity &amp; phrase persisted
</span><span style="color:blue;">IF </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span></font><font size="2"><span style="color:gray;">) is NULL
  </span><span style="color:blue;">CREATE SYMMETRIC KEY </span></font><font size="2"><span style="color:teal;">#TestKey
  </span><span style="color:blue;">WITH ALGORITHM </span><span style="color:gray;">= </span></font><font size="2"><span style="color:blue;">AES_256
     </span><span style="color:gray;">, </span><span style="color:blue;">KEY_SOURCE </span><span style="color:gray;">= </span></font><font size="2"><span style="color:red;">'testing 1,2,3'
     </span><span style="color:gray;">, </span><span style="color:blue;">IDENTITY_VALUE </span><span style="color:gray;">= </span></font><font size="2"><span style="color:red;">'This is only a test'
  </span><span style="color:blue;">ENCRYPTION BY PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'test'</span></font><font size="2"><span style="color:gray;">;
</span><span style="color:blue;">OPEN SYMMETRIC KEY </span><span style="color:teal;">#TestKey </span><span style="color:blue;">DECRYPTION BY PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'test'</span></font><span style="color:gray;"><font size="2">;
</font></span><span style="color:blue;"><font size="2">GO
</font></span><font size="2"><span style="color:green;">-- setup the required inputs
</span><span style="color:blue;">DECLARE </span><span style="color:teal;">@CertificateName </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>128<span style="color:gray;">) = </span></font><font size="2"><span style="color:red;">'CertificateName'
      </span><span style="color:gray;">, </span><span style="color:teal;">@CipherType </span><span style="color:blue;">NCHAR</span><span style="color:gray;">(</span>2<span style="color:gray;">) = </span><span style="color:red;">'MK' </span></font><font size="2"><span style="color:green;">-- 'NA' (EKM), 'MK' , 'PW'
      </span><span style="color:gray;">, </span><span style="color:teal;">@DbName </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>128<span style="color:gray;">) = </span></font><font size="2"><span style="color:red;">'DbName'
      </span><span style="color:gray;">, </span><span style="color:teal;">@BackupName </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000<span style="color:gray;">) = </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span></font><font size="2"><span style="color:gray;">)
                                                      , </span><span style="color:red;">N'BackupName'</span></font><font size="2"><span style="color:gray;">)
      , </span><span style="color:teal;">@DMKPhraseName </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000<span style="color:gray;">) = </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span></font><font size="2"><span style="color:gray;">)
                                                      , </span><span style="color:red;">N'DMKPhraseName'</span></font><font size="2"><span style="color:gray;">)
      , </span><span style="color:teal;">@KeyPhraseName </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000<span style="color:gray;">) = </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span></font><font size="2"><span style="color:gray;">)
                                                      , </span><span style="color:red;">N'KeyPhraseName'</span></font><font size="2"><span style="color:gray;">)
      , </span><span style="color:teal;">@PublicKeyFileExt </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>10<span style="color:gray;">)  = </span></font><font size="2"><span style="color:red;">'.cer'
      </span><span style="color:gray;">, </span><span style="color:teal;">@PrivateKeyFileExt </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>10<span style="color:gray;">) = </span></font><font size="2"><span style="color:red;">'.prv'
      </span><span style="color:gray;">, </span><span style="color:teal;">@UseHash </span><span style="color:blue;">BIT                    </span><span style="color:gray;">= </span>1
      <span style="color:gray;">, </span><span style="color:teal;">@BackupNameBucket </span></font><font size="2"><span style="color:blue;">INT
      </span><span style="color:gray;">, </span><span style="color:teal;">@BackupPath </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>8000</font><span style="color:gray;"><font size="2">)
      , </font></span><font size="2"><span style="color:teal;">@Backuptvp NAMEVALUETYPE
      </span><span style="color:gray;">, </span></font><font size="2"><span style="color:teal;">@DMKtvp NAMEVALUETYPE
      </span><span style="color:gray;">, </span><span style="color:teal;">@Keytvp NAMEVALUETYPE</span></font><span style="color:gray;"><font size="2">;
</font></span><font size="2"><span style="color:green;">-- checksum truncation of the random lambda
</span><span style="color:blue;">SET </span><span style="color:teal;">@BackupNameBucket </span><span style="color:gray;">= </span><span style="color:magenta;">ABS</span><span style="color:gray;">(</span><span style="color:magenta;">CHECKSUM</span><span style="color:gray;">(</span><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">(</span></font><font size="2"><span style="color:red;">'SHA2_256'
    </span><span style="color:gray;">, RIGHT(</span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:teal;">@BackupName</span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">))
    , </span><span style="color:magenta;">FLOOR</span><span style="color:gray;">(</span><span style="color:magenta;">LEN</span><span style="color:gray;">(</span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:teal;">@BackupName</span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448<span style="color:gray;">)))/</span>2</font><font size="2"><span style="color:gray;">)))));
</span><span style="color:blue;">SET </span><span style="color:teal;">@BackupPath </span><span style="color:gray;">= </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span></font><font size="2"><span style="color:gray;">)
                              , </span><span style="color:red;">N'Z:\BackupPath\'</span><span style="color:gray;">, </span>1<span style="color:gray;">, </span><span style="color:teal;">@DbName</span></font><font size="2"><span style="color:gray;">);
</span><span style="color:blue;">INSERT </span><span style="color:teal;">@Backuptvp </span><span style="color:gray;">(</span><span style="color:teal;">Name</span><span style="color:gray;">, </span><span style="color:teal;">Value</span></font><font size="2"><span style="color:gray;">)
</span><span style="color:blue;">VALUES </span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">@BackupName
       </span><span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span><span style="color:gray;">), </span><span style="color:red;">N'@Backuptvp.Value'</span><span style="color:gray;">, </span>1
                     <span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:teal;">@BackupName</span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">))));
</span><span style="color:blue;">IF </span><span style="color:teal;">@DMKPhraseName </span></font><font size="2"><span style="color:gray;">IS NOT NULL
  </span><span style="color:blue;">INSERT </span><span style="color:teal;">@DMKtvp </span><span style="color:gray;">(</span><span style="color:teal;">Name</span><span style="color:gray;">, </span><span style="color:teal;">Value</span></font><font size="2"><span style="color:gray;">)
  </span><span style="color:blue;">VALUES </span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">@DMKPhraseName
         </span><span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span><span style="color:gray;">), </span><span style="color:red;">N'@DMKtvp.Value'</span><span style="color:gray;">, </span>1
                 <span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:teal;">@DMKPhraseName</span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">))));
</span><span style="color:blue;">IF </span><span style="color:teal;">@KeyPhraseName </span><span style="color:gray;">IS NOT NULL AND </span><span style="color:teal;">@CipherType </span><span style="color:gray;">= </span></font><font size="2"><span style="color:red;">'PW'
  </span><span style="color:blue;">INSERT </span><span style="color:teal;">@Keytvp </span><span style="color:gray;">(</span><span style="color:teal;">Name</span><span style="color:gray;">, </span><span style="color:teal;">Value</span></font><font size="2"><span style="color:gray;">)
  </span><span style="color:blue;">VALUES </span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">@KeyPhraseName
         </span><span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">key_guid</span><span style="color:gray;">(</span><span style="color:red;">'#TestKey'</span><span style="color:gray;">), </span><span style="color:red;">N'@Keytvp.Value'</span><span style="color:gray;">, </span>1
                 <span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">(</span><span style="color:teal;">@KeyPhraseName</span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><span style="color:gray;"><font size="2">))));
</font></span><font size="2"><span style="color:green;">--------------------------------------------------------------------------
-- decryption with FORMATMESSAGE
</span><span style="color:blue;">SELECT </span></font><font size="2"><span style="color:magenta;">FORMATMESSAGE
        </span><span style="color:gray;">( </span></font><font size="2"><span style="color:red;">'USE %s;%sBACKUP CERTIFICATE TO FILE = ''%s%s%s'' %s;%s'
        </span><span style="color:gray;">, </span></font><font size="2"><span style="color:teal;">@DbName
        </span><span style="color:gray;">, </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@DMKPhraseName </span><span style="color:gray;">IS NOT NULL </span></font><font size="2"><span style="color:green;">-- need to open master key
              </span><span style="color:blue;">THEN </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span></font><font size="2"><span style="color:magenta;">FORMATMESSAGE
                      </span><span style="color:gray;">( </span></font><font size="2"><span style="color:red;">'OPEN MASTER KEY DECRYPTION BY PASSWORD = ''%s'';'
                      </span><span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">Value
                          </span><span style="color:gray;">, </span>1
                          <span style="color:gray;">, </span><span style="color:magenta;">CAST </span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:teal;">Name </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">) )
                          ) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>128</font><font size="2"><span style="color:gray;">) ) )
                    </span><span style="color:blue;">FROM </span><span style="color:teal;">@DMKtvp </span></font><font size="2"><span style="color:gray;">)
              </span><span style="color:blue;">ELSE </span><span style="color:red;">'' </span></font><font size="2"><span style="color:blue;">END
        </span><span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:teal;">@BackupPath</span><span style="color:gray;">, </span>1<span style="color:gray;">, </span><span style="color:teal;">@DbName </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>1024</font><font size="2"><span style="color:gray;">) )
        , </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@UseHash </span><span style="color:gray;">= </span>1
                <span style="color:blue;">THEN </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:teal;">@BackupNameBucket </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">) )
                </span><span style="color:blue;">ELSE </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">DecryptByKey</span><span style="color:gray;">( </span><span style="color:teal;">@BackupName </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><span style="color:gray;"><font size="2">) )
                </font></span><font size="2"><span style="color:blue;">END
      </span><span style="color:gray;">, </span></font><font size="2"><span style="color:teal;">@PublicKeyFileExt
      </span><span style="color:gray;">, </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@CipherType </span><span style="color:gray;">&lt;&gt; </span></font><span style="color:red;"><font size="2">'NA'
             </font></span><span style="color:blue;"><font size="2">THEN
</font></span><font size="2"><span style="color:magenta;">FORMATMESSAGE
</span><span style="color:gray;">(</span></font><font size="2"><span style="color:red;">'WITH PRIVATE KEY ( FILE=''%s%s%s'', ENCRYPTION BY PASSWORD=''%s'' %s)'
      </span><span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">(</span><span style="color:magenta;">DecryptByKey</span><span style="color:gray;">(</span><span style="color:teal;">@BackupPath</span><span style="color:gray;">, </span>1<span style="color:gray;">, </span><span style="color:teal;">@DbName </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>1024</font><font size="2"><span style="color:gray;">))
      , </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@UseHash </span><span style="color:gray;">= </span>1
              <span style="color:blue;">THEN </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:teal;">@BackupNameBucket </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">) )
              </span><span style="color:blue;">ELSE </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">DecryptByKey</span><span style="color:gray;">( </span><span style="color:teal;">@BackupName </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><span style="color:gray;"><font size="2">) )
              </font></span><font size="2"><span style="color:blue;">END
      </span><span style="color:gray;">, </span></font><font size="2"><span style="color:teal;">@PrivateKeyFileExt
      </span><span style="color:gray;">, ( </span><span style="color:blue;">SELECT </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">Value
                           </span><span style="color:gray;">, </span>1
                           <span style="color:gray;">, </span><span style="color:magenta;">CAST </span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:teal;">Name </span><span style="color:gray;">) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">) )
                           ) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>128</font><font size="2"><span style="color:gray;">) )
          </span><span style="color:blue;">FROM </span><span style="color:teal;">@BackupTvp </span></font><font size="2"><span style="color:gray;">)
      , </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@CipherType </span><span style="color:gray;">= </span></font><font size="2"><span style="color:red;">'PW'
              </span><span style="color:blue;">THEN </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span></font><font size="2"><span style="color:magenta;">FORMATMESSAGE
                            </span><span style="color:gray;">( </span></font><font size="2"><span style="color:red;">', DECRYPTION BY PASSWORD = ''%s'''
                            </span><span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span></font><font size="2"><span style="color:teal;">Value
                                       </span><span style="color:gray;">, </span>1
                                       <span style="color:gray;">, </span><span style="color:magenta;">CAST </span><span style="color:gray;">( </span><span style="color:magenta;">DECRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:teal;">Name </span></font><font size="2"><span style="color:gray;">)
                                                  </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>448</font><font size="2"><span style="color:gray;">) )
                                       ) </span><span style="color:blue;">AS NVARCHAR</span><span style="color:gray;">(</span>128</font><font size="2"><span style="color:gray;">) ) )
                    </span><span style="color:blue;">FROM </span><span style="color:teal;">@KeyTvp </span></font><font size="2"><span style="color:gray;">)
              </span><span style="color:blue;">ELSE </span><span style="color:red;">'' </span><span style="color:blue;">END </span></font><font size="2"><span style="color:gray;">)
            </span><span style="color:blue;">ELSE </span><span style="color:red;">'' </span></font><font size="2"><span style="color:blue;">END

        </span><span style="color:gray;">, </span><span style="color:blue;">CASE WHEN </span><span style="color:teal;">@DMKPhraseName </span><span style="color:gray;">IS NOT NULL </span></font><font size="2"><span style="color:green;">-- open master key
                </span><span style="color:blue;">THEN </span></font><font size="2"><span style="color:red;">'CLOSE MASTER KEY;'
                </span><span style="color:blue;">ELSE </span><span style="color:red;">'' </span><span style="color:blue;">END </span></font><font size="2"><span style="color:gray;">);
</span><span style="color:blue;">GO</span></font></pre>
<p>Some sample output for the three different @CipherType values&nbsp; (after pasting from the results window to the query window and adding a few CR-LFs):</p>
<pre class="code"><span style="color:green;">-- @CipherType = 'NA', @DMKPhraseName = NULL, @UseHash = 0
</span><span style="color:blue;">USE </span><span style="color:teal;">DbName</span><span style="color:gray;">;
</span><span style="color:blue;">BACKUP CERTIFICATE TO FILE </span><span style="color:gray;">= </span><span style="color:red;">'Z:\BackupPath\BackupName.cer' </span><span style="color:gray;">;

</span><span style="color:green;">-- @CipherType = 'PW', @DMKPhraseName = NULL, @UseHash = 1
</span><span style="color:blue;">USE </span><span style="color:teal;">DbName</span><span style="color:gray;">;
</span><span style="color:blue;">BACKUP CERTIFICATE TO FILE </span><span style="color:gray;">= </span><span style="color:red;">'Z:\BackupPath\116889000.cer'
</span><span style="color:blue;">WITH PRIVATE KEY </span><span style="color:gray;">( </span><span style="color:blue;">FILE</span><span style="color:gray;">=</span><span style="color:red;">'Z:\BackupPath\116889000.prv'
                 </span><span style="color:gray;">, </span><span style="color:blue;">ENCRYPTION BY PASSWORD</span><span style="color:gray;">=</span><span style="color:red;">'@Backuptvp.Value' </span><span style="color:gray;">);

</span><span style="color:green;">-- @CipherType = 'MK', @DMKPhraseName = 'phrase', @UseHash = 1
</span><span style="color:blue;">USE </span><span style="color:teal;">DbName</span><span style="color:gray;">;
</span><span style="color:blue;">OPEN MASTER KEY DECRYPTION BY PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'@DMKtvp.Value'</span><span style="color:gray;">;
</span><span style="color:blue;">BACKUP CERTIFICATE TO FILE </span><span style="color:gray;">= </span><span style="color:red;">'Z:\BackupPath\116889000.cer'
</span><span style="color:blue;">WITH PRIVATE KEY </span><span style="color:gray;">( </span><span style="color:blue;">FILE</span><span style="color:gray;">=</span><span style="color:red;">'Z:\BackupPath\116889000.prv'
                 </span><span style="color:gray;">, </span><span style="color:blue;">ENCRYPTION BY PASSWORD</span><span style="color:gray;">=</span><span style="color:red;">'@Backuptvp.Value' </span><span style="color:gray;">);
</span><span style="color:blue;">CLOSE MASTER KEY</span><span style="color:gray;">;

</span></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/313/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/313/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/313/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=313&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/11/16/throw-formatmessage-in-the-sql-server-2012-tool-bag/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>Encrypting XML Typed Data in SQL Server</title>
		<link>http://bwunder.wordpress.com/2011/10/31/encrypting-xml-typed-data-in-sql-server/</link>
		<comments>http://bwunder.wordpress.com/2011/10/31/encrypting-xml-typed-data-in-sql-server/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 13:40:49 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[cell encryption]]></category>
		<category><![CDATA[Cipher Block Chaining]]></category>
		<category><![CDATA[EncrypyByKey]]></category>
		<category><![CDATA[T-SQL Error Handler]]></category>
		<category><![CDATA[XML Encryption]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/10/31/encrypting-xml-typed-data-in-sql-server/</guid>
		<description><![CDATA[Two issues: W3C XML Encryption is broken by most accounts. SQL Server encryption functions cannot digest XML (pun intended). A double whammy! The first issue is a bigger deal. If you are encrypting sensitive data with a web service &#8211; &#8230; <a href="http://bwunder.wordpress.com/2011/10/31/encrypting-xml-typed-data-in-sql-server/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=300&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Two issues:</p>
<ol>
<li>W3C XML Encryption is <a href="http://www.informationweek.com/news/security/vulnerabilities/231901532">broken by most accounts</a>.
<li>SQL Server encryption functions cannot digest XML (pun intended).</li>
</ol>
<p><em><a href="http://www.phrases.org.uk/meanings/119750.html">A double whammy!</a></em></p>
<p>The first issue is a bigger deal. If you are encrypting sensitive data with a web service &#8211; and you probably are &#8211; then your data is vulnerable. If that data is personally identifiable information about individuals your are doing business with then it is your duty and responsibility to stop using those solutions until the XML Encryption standard is corrected. Not until the vendors roll out their fixes and the application is appropriately updated should the application be re-enabled. To knowingly continue to <em>rely</em> upon the broken encryption is a criminal activity in my opinion. </p>
<p>Here&#8217;s why. In 2003 the Federal Trade Commission (FTC) <a href="http://www.ftc.gov/opa/2003/09/idtheft.shtm">reported</a> that over 27 million Americans were &#8220;victims of identity theft&#8221;. In 2007 ars Technica <a href="http://arstechnica.com/security/news/2007/08/159-million-users-affected-by-data-breaches-in-under-three-years.ars">reported</a> that 159 million people were &#8220;affected by data breaches&#8221; between 2005 and 2007. The Privacy Rights Clearing House <a href="https://www.privacyrights.org/data-breach">reports</a> 542,355,201 records breached from 2747 data breaches between 2005 and 2011. According to the New York Daily News Facebook alone is attacked <a href="http://www.nydailynews.com/news/national/facebook-hack-attacks-strike-600-000-times-day-security-firm-reports-article-1.968681?localLinksEnabled=false">600,000 times a day</a>. Almost all Facebook has to offer is your person information . The trend is much more than obvious. At the same time Reuters reports that <a href="http://ca.reuters.com/article/businessNews/idCATRE7A131K20111102">MasterCard hits an all-time high</a> on the stock market, &#8220;MasterCard Inc shares jumped 7.4 percent to $359.12 after the credit card processor reported its quarterly profit easily beat estimates on double-digit increases in volumes.&#8221;</p>
<p>The Information Commissioner of the UK, Christopher Graham <a href="http://www.telegraph.co.uk/technology/news/8841025/Data-breaches-up-58.html">told the Telegraph the other day</a> that database breaches are up 58% in the UK in the last year. FWIW, the commissioner can levy fines up to £500,000 under the Kingdom&#8217;s Data Protection Act (DPA). Sounds like they have the possibility to agree with my sentiment regarding the undeniable responsibility to protect other people&#8217;s information. Sadly, I don&#8217;t think the penalty has been leveraged much &#8211; if at all &#8211; judging by the obvious parallel trend in the USA and the UK. </p>
<p>The broken status quo of capitalism that places profit above human decency, human dignity and often even human rights is rampant and unraveling around the world regardless of corporate hegemony and political corruption. Infosys co-chair <a href="http://www.reuters.com/video/2011/11/13/the-consumption-model-cannot-be-sustaine?videoId=224724092&amp;videoChannel=1">Kris Gopalakrishnan</a> seems to agree with that appraisal &#8211; calling out a systemic income imbalance that advantages the wealthiest 3%-5% in western <em>and</em> emerging economies. Infosys is the largest IT organization in the world. He also states that the middle class in the west is already being diminished in reciprocation to the rise of the middle class in the emerging economies and that the decline in the west is needed to achieve sustainability for the world population. Another double whammy for IT workers in the US, where the distribution of income grows ever more skewed and the downward spiral of the middle class is at least on the edge if not fully out of control. The wealthiest amass more wealth while the middle class has now lost the collateral it blew to Reagan Up: consume to help the economy, and now we have nothing to do but wait for some corporation to pee its record profits down on us. And wait. And wait. How much more obvious does it need to be for intelligent people to understand that the wealth that continues to accumulate in the accounts of a few &#8211; that have no practical purpose for more wealth &#8211; is coming not from vapor but out of the pockets of workers that too often don&#8217;t quite have enough and deserve better?&nbsp;&nbsp; </p>
<p>In the USA the worst that can happen to an entity that carelessly exposes other&#8217;s private and/or personal information is a bit of hate mail and perhaps a few underfunded civil suits by folks who&#8217;s lives have been ruined and accounts depleted as a direct result of corporate negligence and stonewalling. There are rumblings about accountability measures from the government. What ever the government does, it will not be adequate: too many politicians are in the pockets of the people that would make a bundle from that unsecure data. Enough is enough!. Anytime someone can waltz in and steal other people&#8217;s personally identifiable information from a data center or business network, the&nbsp; systems owners and administrators were carelessly negligent. If the theft recurs or is ongoing that negligence has gone beyond the point of criminal culpability. For effective deterrence, the penalty must match the crime. That&#8217;s all I&#8217;m saying. </p>
<p>If the next 5 businesses that failed to protect personally identifiable details that had been demanded from customers were shut down for even a week by the government the landscape would be changed significantly for the better for as long as the threat of meeting a similar fate for similar negligence might endure. This is what the government used to do in the mines in Wyoming where I worked in the 70s when safety would get too far out of hand in the push to produce, but even then someone often had to die to get the attention of the government inspectors.&nbsp; An equitable solution would be to require the leaker to appropriately compensate the folks that were violated but such fairness will not find its way into the legal system in my lifetime I am sure. The leaker, of course, could pursue the attacker to recover costs.&nbsp; The essential ingredient in a solution is unavoidable accountability. effective regulation could create accountability were the bureaucracy not so corrupt. Even the DOJs National Institute for Justice cannot uncover the <a href="http://www.nij.gov/topics/crime/id-theft/cost.htm">real cost of identity theft</a> noting, &#8220;A serious lack of data on these issues inhibits research into possible intervention strategies that could reduce the harm.&#8221; Until the effective costs to corporations is established as more than the cost to <em>not</em> protect data as it to do the right thing and protect our information, the necessary change is unlikely as long as the effective costs for corporations can be avoided. According to Mike Vizard, as he lays out a a survey based accounting in &#8220;The Cost of Insecurity&#8221; (<a href="http://www.ctoedge.com/content/cost-insecurity">CTOEdge</a>, DEC 2010), &#8220;&#8230; the majority of the IT organizations surveyed by [IT security vendor] Lumension have yet to deploy any of these security technologies, even as their operational security costs continue to rise.&#8221; Follow the article link ink to see the secure computing adoption rate charts by technology and 12 other mind blowing charts built from a survey of IT shops. </p>
<p>The simple fact is, the technologies needed to protect data and prevent the vast majority of hacker access to information is at hand. Sure it is more costly to implement those technologies than to skip them, but how can it be negative for the profit motive of a corporation when that corporation takes genuine and necessary steps to increase the customer/consumer confidence in that corporation with a comparatively small incremental rise in development costs? The payoff for a corporation that takes the high road is insufficient in today&#8217;s capitalism. It just simply isn&#8217;t done. I would argue that it is a perversion of the profit motive that we have ever allowed contrivance and deception to drive profit. Profit is not inherently bad. Dishonesty is bad. To profit from dishonesty is perverse. Corporations know they cut corners on data security. That is one of the main reasons they are corporations. So the individuals calling the shots can hide from personal responsibility. Customers/consumers know that corporations cut corners on data security. Government knows that corners are being cut on data security. Nothing changes. That is sick. And inadequate data security in corporate data centers is a primary reason people&#8217;s information is exposed and can subsequently be used to do harm to that person. </p>
<p>I am certainly not saying all that is necessary is to punish violations vigorously in this post to solve the worlds data security problems. Secure data solutions will be more complex with extensive defense-in-depth and well worth the effort and cost. They will probably always be under attack as well, requiring on-going hardening. The goal I advocate is to simply do what is right. There is no gray area around what of your personal information I have the right to be careless with, let alone negligently so&#8230;</p>
<p>Update January 13, 2012:</p>
<p>Consumer Reports story today on Yahoo indicates that the financial industry has found a way to profit from the fear over identity theft: <a href="http://finance.yahoo.com/news/debunking-hype-over-id-theft-080000873.html">http://finance.yahoo.com/news/debunking-hype-over-id-theft-080000873.html</a> </p>
<p>The&nbsp; story also breaks down some identity theft data for 2010. Highlights:</p>
<ul>
<li>50 million Americans paid $120 -$300 a year (that&#8217;s $6-$15 billion) for identity theft protection in 2010 &#8211; for liability protection the banks already <em>must</em> provide</li>
<li>Identity fraud was down 27% in 2010 to a mere 8.1 million victims</li>
<li>Personal identity theft &#8211; &#8220;in which someone uses your name, birth date, and Social Security number to open new credit accounts, tap your health insurance, earn taxable income, or commit crimes in your name&#8221; was at 765,000 households in 2010 </li>
</ul>
<hr />
<p>On the second issue, the incompatibility of SQL Server &#8216;s encryption functions (ENCRYPTBYASYMKEY, ENCRYPTBYCERT, ENCRYPTBYKEY, ENCRYPTBYPASSPHRASE) and the XML data type is not such a big deal. Even before SQL Server had the XML type, XML has been stored in the database as VARCHAR. That conversion between the XML type and the VARCHAR type is really all that is necessary to encrypt XML at the database. From there the door is open to sending encrypted oData or XML document that may or may not rely upon XML Encryption. That&#8217;s right! You could actually work around the XML Encryption vulnerability now without breaking the web services in many case by encrypting the XML at the database and decrypting only where needed.</p>
<p>In addition to missing XML &#8211; and UNIQUEIDENTIFIER, and CLR types btw &#8211; compatibility, SQL Server encryption functions are also limited to VARBINARY(8000) output in length. That is not a problem for the error handler but may be for many XML documents. Large XML documents are where much of the pain of the broken XML encryption will be felt.&nbsp; To work around this limitation consider encrypting only sensitive XML attributes at the database and then providing public decryption keys in a secure manner. only to those that must decrypt that data. This is more or less how <a href="http://www.w3.org/TR/xmlenc-core/">W3C XML Encryption</a> goes after the problem. One risk in a piecemeal roll-ur-own XML document encryption like I&#8217;m suggesting is that the XML attributes not encrypted may still reveal enough information for a successful attack that eventually breaks the encryption. It is of utmost importance that XML encryption is &#8216;fixed&#8217; ASAP. Using SQL Server or another work-around to plug the hole should not even pretend to replace XML Encryption. SQL Server should be considered only as an augmenting and/or interim solution until the better suited technology is made trustworthy.&nbsp; </p>
<p>When data originates in the application, SQL Server is almost always a less desirable place for encryption. In part this is because the data must move to the database unprotected.&nbsp; However, there are many SOA scenarios where the data enters the distributed environment via the database. (i.e. peer to peer transfers, XML feeds, performance data, database errors, etc.) When the database is a <em>de facto</em> gateway for the data into the SOA then the database is a great place for the encryption. </p>
<p>To see how this might work to relieve the XML Encryption woes, consider the following error handler that writes errors to a SPARSE XML column of a logging table. This is data that absolutely originates at the database so is very clearly the best place to encrypt any sensitive data in the error&#8217;s message. An encrypted error message is also an effective way to combat <a href="http://blog.gdssecurity.com/labs/2010/9/14/automated-padding-oracle-attacks-with-padbuster.html">padding oracle attacks</a> where-in the messages returned from unsuccessful decryption attempts are mined and analyzed to eventually crack the encryption. The padding oracle attack is proving especially effective against cipher-block chained (CBC) digests such as is used in the XML Encryption . SQL Server also uses CBC digest, yet is malleable to a more resistant and somewhat slower hash based digest. (see <a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation">http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation</a> for an overview of block cipher modes. See the post <a href="https://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/">https://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/</a> for some of my thoughts on hash based digests.) </p>
<p>I don&#8217;t mean to exclude streaming modes in the possibilities here, there just isn&#8217;t any support for that possibility in SQL Server. At some level streaming encryption makes sense for XML, especially for humongous documents. In that scenario, a streaming resume-able &#8211; possibly even transactional but that may be only wishful thinking &#8211; encryption would be ideal. </p>
<p>The following example is based loosely on the error handler modeled in the TRY-CATCH topic of Books On-Line.&nbsp; The example is intended to be extend such that the error event is persisted to a SPARSE XML column in an activity logging table. Once encrypted, the column becomes be a SPARSE VABINARY(8000) column.&nbsp;&nbsp;&nbsp; </p>
<pre class="code"><span style="color:blue;">DECLARE </span><span style="color:teal;">@Id </span><span style="color:blue;">NCHAR</span><span style="color:gray;">(</span>36<span style="color:gray;">);
</span><span style="color:blue;">SET </span><span style="color:teal;">@Id </span><span style="color:gray;">= </span><span style="color:magenta;">NEWID</span><span style="color:gray;">();
</span><span style="color:blue;">BEGIN TRY
  RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'test'</span><span style="color:gray;">, </span>16<span style="color:gray;">, </span>1<span style="color:gray;">);
</span><span style="color:blue;">END TRY
BEGIN CATCH

  SELECT </span><span style="color:magenta;">ERROR_NUMBER</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorNumber
       </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_SEVERITY</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorSeverity
       </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_STATE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorState
       </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_PROCEDURE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorProcedure
       </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_LINE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorLine
       </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_MESSAGE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorMessage </span><span style="color:blue;">FOR XML RAW</span><span style="color:gray;">;

  </span><span style="color:blue;">OPEN SYMMETRIC KEY </span><span style="color:teal;">ErrorKey
  </span><span style="color:blue;">DECRYPTION BY CERTIFICATE </span><span style="color:teal;">ErrorCertificate
  </span><span style="color:blue;">WITH password </span><span style="color:gray;">= </span><span style="color:red;">'Au&amp;6Gf% 3Fe14CQAN@wcf?'</span><span style="color:gray;">;
    </span><span style="color:blue;">SELECT </span><span style="color:magenta;">ENCRYPTBYKEY </span><span style="color:gray;">( </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">( </span><span style="color:red;">'ErrorKey' </span><span style="color:gray;">)
            , ( </span><span style="color:blue;">SELECT </span><span style="color:magenta;">ERROR_NUMBER</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorNumber
                      </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_SEVERITY</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorSeverity
                      </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_STATE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorState
                      </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_PROCEDURE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorProcedure
                      </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_LINE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorLine
                      </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_MESSAGE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorMessage
                </span><span style="color:blue;">FOR XML RAW </span><span style="color:gray;">)
            , </span>1
            <span style="color:gray;">, </span><span style="color:teal;">@Id </span><span style="color:gray;">);

    </span><span style="color:blue;">SELECT </span><span style="color:magenta;">ERROR_NUMBER</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorNumber
         </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_SEVERITY</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorSeverity
         </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_STATE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorState
         </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_PROCEDURE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorProcedure
         </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_LINE</span><span style="color:gray;">() </span><span style="color:blue;">as </span><span style="color:teal;">ErrorLine
         </span><span style="color:gray;">, </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:teal;">fn_varbintohexstr</span><span style="color:gray;">(
              </span><span style="color:magenta;">ENCRYPTBYKEY </span><span style="color:gray;">( </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">( </span><span style="color:red;">'ErrorKey' </span><span style="color:gray;">)
                           , </span><span style="color:magenta;">ERROR_MESSAGE</span><span style="color:gray;">()
                           , </span>1
                           <span style="color:gray;">, </span><span style="color:teal;">@Id </span><span style="color:gray;">) ) </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorMessage
    </span><span style="color:blue;">FOR XML RAW</span><span style="color:gray;">;

  </span><span style="color:blue;">CLOSE SYMMETRIC KEY </span><span style="color:teal;">ErrorKey</span><span style="color:gray;">;
</span><span style="color:blue;">END CATCH

</span></pre>
<p>The resulting&nbsp; XML from the first of the three error message formats is clear text:</p>
<pre class="code"><span style="color:blue;">&lt;</span><span style="color:#a31515;">row </span><span style="color:red;">ErrorNumber</span><span style="color:blue;">=</span>"<span style="color:blue;">50000</span>"
     <span style="color:red;">ErrorSeverity</span><span style="color:blue;">=</span>"<span style="color:blue;">16</span>"
     <span style="color:red;">ErrorState</span><span style="color:blue;">=</span>"<span style="color:blue;">1</span>"
     <span style="color:red;">ErrorLine</span><span style="color:blue;">=</span>"<span style="color:blue;">5</span>"
     <span style="color:red;">ErrorMessage</span><span style="color:blue;">=</span>"<span style="color:blue;">test</span>" <span style="color:blue;">/&gt;
</span></pre>
<p>The second is completely encrypted (I added line feeds for display rendering):</p>
<blockquote>
<p align="left"><font color="#0000ff" size="2" face="Courier New">0x00335906BE45EA4AB8BF0D94BFB6FC9D010000005E2DAA7F20DA4D827612ECFF<br />506ABBCBB7BF182711576E4E71E6B3C019123A88E2A7BD47F14A9EA45FB3F55BCB<br />642B25CF3A5BD9B44C0F58024113774D582C77F3D87D5816E877D643C19230CFDC<br />70D6A8FDE3269CF136A7111C362E6CB934800DA4D28FEE3E7425F53E14330816E7<br />C0407E798006FC3B434EC127BD05FCA61597E66150A5E2D8F4616070711CB2C27F<br />A2B51D7FE242E8F9A6ABB58C6697B6A4AF5B1CFC423E5927E983E4E1D7F0B8571D<br />7DDCC70184016F4B7EC0D823D4DF615F30ABC5B114738D373FDC0D973DB20EB977<br />E5CC8246CA7F3CF2E487456DA6C1BC95851BC60890C9FD290DFBAC46B8B2</font></p>
</blockquote>
<p>And the third is a hybrid that encrypts only one sensitive XML attribute (again I added the CR+LFs so you could see the result):</p>
<pre class="code"><span style="color:blue;">&lt;</span><span style="color:#a31515;">row </span><span style="color:red;">ErrorNumber</span><span style="color:blue;">=</span>"<span style="color:blue;">50000</span>"
     <span style="color:red;">ErrorSeverity</span><span style="color:blue;">=</span>"<span style="color:blue;">16</span>"
     <span style="color:red;">ErrorState</span><span style="color:blue;">=</span>"<span style="color:blue;">1</span>"
     <span style="color:red;">ErrorLine</span><span style="color:blue;">=</span>"<span style="color:blue;">5</span>"
     <span style="color:red;">ErrorMessage</span><span style="color:blue;">=</span>"<span style="color:blue;">0x00335906be45ea4ab8bf0d94bfb6fc9d010000
       00537a48339b1669c2de290be82c0895acca90a74f19011a4d00
       6b09adb0930d49b116993af0a3be9e23172b5d0cd9855b379ce8
       85a510e3ca46556ef5bf15fcf2</span>" <span style="color:blue;">/&gt;
</span></pre>
<p>The third option represents a middle ground between encryption and storage requirements. This demonstrates the &#8216;divide and conquer&#8217; tactic that may be necessary to apply the available tools to a workable solution. Chunking for SQL Server&#8217;s VARBINARY(8000) encryption result limitation may be necessary.&nbsp; </p>
<p>(And of course in the example it is important to persist that @Id to the logging table as well if you ever want to decrypt the value. In the solution I lifted the example from the procedure name is captured by the row so instead of keeping it here as redundant encrypted data, ErrorProcedure() is not captured in the XML column.)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/300/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/300/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/300/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=300&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/10/31/encrypting-xml-typed-data-in-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>Considering Cryptography in SQL Server Database Architectures</title>
		<link>http://bwunder.wordpress.com/2011/10/17/considering-cryptography-in-sql-server-database-architectures/</link>
		<comments>http://bwunder.wordpress.com/2011/10/17/considering-cryptography-in-sql-server-database-architectures/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 03:15:55 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[authenticity]]></category>
		<category><![CDATA[cell encryption]]></category>
		<category><![CDATA[container scoped encryption]]></category>
		<category><![CDATA[encrypted disk]]></category>
		<category><![CDATA[HASHBYTES()]]></category>
		<category><![CDATA[message signatures]]></category>
		<category><![CDATA[object signing]]></category>
		<category><![CDATA[TDE]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/10/17/considering-cryptography-in-sql-server-database-architectures/</guid>
		<description><![CDATA[It is useful to have a &#8216;big picture&#8217; understanding of the possible layers of encryption available for data-at-rest in a data-centric application. A visual that conveys those layers is challenging due to the number of dimensions that must be considered. &#8230; <a href="http://bwunder.wordpress.com/2011/10/17/considering-cryptography-in-sql-server-database-architectures/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=282&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It is useful to have a &#8216;big picture&#8217; understanding of the possible layers of encryption available for data-at-rest in a data-centric application. A visual that conveys those layers is challenging due to the number of dimensions that must be considered. Here is my best shot at the visual &#8211; for today anyway. If you find it easy to understand the diagram at a glance there is probably nothing of interest in what follows (and there is a jar in the Smithsonian with your brain&#8217;s name on it):</p>
<p><a href="http://bwunder.files.wordpress.com/2011/10/encryptionindepth.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionInDepth" border="0" alt="EncryptionInDepth" src="http://bwunder.files.wordpress.com/2011/10/encryptionindepth_thumb.png?w=645&#038;h=516" width="645" height="516"></a></p>
<p>On the other hand, if your are like me it may look confusing and way too busy. Makes me want another cup of coffee.&nbsp; Nonetheless, I happen to know it will make perfect sense to all once broken down into 3&nbsp; coherent parts.&nbsp; </p>
<p>I will begin with the middle part. You may notice that a user database with a data file group and a FILESTREAM file group &#8211; dangling precariously off to the side of the database -is depicted. Along side the user database are the four system databases. The only piece of this picture that may be unfamiliar to some is the FILESTREAM file group that is part of the database but actually lives outside of the database. This is intended to represent a typical FILESTREAM enabled configuration. Nothing special.</p>
<p>&nbsp; <a href="http://bwunder.files.wordpress.com/2011/10/encryptionindepthdb.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionInDepthDb" border="0" alt="EncryptionInDepthDb" src="http://bwunder.files.wordpress.com/2011/10/encryptionindepthdb_thumb.png?w=240&#038;h=162" width="240" height="162"></a>generic db (select to view full size)</p>
<p>The databases are enveloped in various cryptographic building blocks:</p>
<p><img src="http://t2.gstatic.com/images?q=tbn:ANd9GcS3GaC24DYgTRQbSFC53yWXmoaDJ98LOfd25tNxnYFJZXIfmRUb4QROD56eHw"></p>
<p>Behind, architecturally underlying the databases are SQL Server&#8217;s Transparent Data Encryption (TDE), a file encryption container that is less than the physical volume in size (e.g. an encrypted file that is able to present a VHD) and also a fully encrypted system (e.g a drive, storage array, or complete file system).&nbsp; These encryption layers are designed to encrypt everything placed in storage in the background. No application change is supposed to be required. Also, the encryption protection cannot be avoided or forgotten in development. In fact, implementation is a configuration issue and should be done by the database&#8217;s Administrator.</p>
<p><a href="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcontainers.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionInDepthContainers" border="0" alt="EncryptionInDepthContainers" src="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcontainers_thumb.png?w=210&#038;h=240" width="210" height="240"></a>container scoped encryption layers</p>
<p>The main thing to notice here is that I have stretched and skewed the building blocks to cover as many scenarios as possible in the diagram. With 3 blocks 9 dimensional states can be represented: state 1 being no encryption and at the other end state 9 &#8211; the darkest pinkest rectangle toward the center in the image above &#8211; being TDE of database pages into an encrypted file exposed as a VHD on top of an encrypted file system. In between are all the combinations visible as overlap of the blocks in the image. </p>
<p>Perhaps of interest, these container scoped layers are not available to a SQL Azure database. </p>
<p>In front of, or structurally within the database are several useful database object and column level cryptographic layers. These layers scramble data, verify that nothing has changed, protect intellectual property, protect personally identifiable information,&nbsp; determine authenticity and extend the usability of data &#8211; primarily by creating HASHBYTES() or other checksum lookup surrogates. These layers are generally implemented by the application developer. They are also the most important layers in terms of the strength of data protection and therefore deserve consideration for integration at the the application layer. In almost all cases, if there is an option, cell value encryption at the application with key storage external to the database server will yield a more secure and scalable implementation (all other things being equal).&nbsp;&nbsp; </p>
<p><a href="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcells.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionInDepthCells" border="0" alt="EncryptionInDepthCells" src="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcells_thumb.png?w=240&#038;h=56" width="240" height="56"></a>cell scoped encryption layers</p>
<p>With the exception of HASHBYTES(), SQL Server <a href="https://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/">cryptographic functions are not available in SQL Azure</a>. Certainly designs that rely upon equivalent client side methods are able to store encrypted values in a properly typed column in SQL Azure, but good to keep in mind that the server-side approach to protecting data in SQL Azure inadequate at this time. </p>
<p>There are an undetermined number of ways to successfully implement cell or column encryption. To my way of thinking this is good. If everyone does it a bit different, all the more difficult to get past for the malicious attacker: a little obscurity actually can improve a good layered defense but cannot be a replacement. There are a wide assortment of cell and column encryption schemes in the introductory <a href="https://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/">Encryption Hierarchy Administration template</a> post and even more in the hardened Encryption Hierarchy Administration 2.0 template. </p>
<p>In this post the goal is to create a visual that shows the possibilities. For that purpose I overlay the three explained images to arrive at that diagram that started this post. The difference is that now the many ways that the cryptographic elements can be used together to build various depths of encryption should jump right out at you. Completely demystified as promised. Toward the center of the diagram are solutions where all encryption layers might be in play. Toward the periphery of the diagram, the layers fall away leaving only clear text and unprotected storage. Performance and usability are examples of the hard to control centrifugal forces pushing application designs to the periphery, while security, authenticity and compliance are core drivers to concentrate applications toward the center.&nbsp; The size, shape and location of the encryption dimensions allow a two dimensional view of the architectural possibilities.&nbsp; </p>
<p>This is not a diagram of a dynamic and configurable run time environment mind you. Instead, this is a visual aid to explore adequately robust cryptographic solutions when designing and developing a data application with encryption requirements. The divisions and overlaps in the diagram indicate what is possible to create in all the combinations and permutations not what must be created in all scenarios. The application defines the requirements not the encryption technology. This is a tool to help define the environment needed to support the requirements.</p>
<p>Spend a moment contemplating the diagram now that you have some background of the diagrams structure and purpose. I expect that you will find your mind exploring some highly secure possibilities. Better yet, the next time you are working on a project with high data protection requirements take a few minutes to contemplate the diagram at that time in the context of your requirements. I am equally confident the diagram can help identify strong defense-in-depth strategies quickly and with ease when used for that purpose.&nbsp; </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/282/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/282/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/282/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=282&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/10/17/considering-cryptography-in-sql-server-database-architectures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/10/encryptionindepth_thumb.png" medium="image">
			<media:title type="html">EncryptionInDepth</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/10/encryptionindepthdb_thumb.png" medium="image">
			<media:title type="html">EncryptionInDepthDb</media:title>
		</media:content>

		<media:content url="http://t2.gstatic.com/images?q=tbn:ANd9GcS3GaC24DYgTRQbSFC53yWXmoaDJ98LOfd25tNxnYFJZXIfmRUb4QROD56eHw" medium="image" />

		<media:content url="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcontainers_thumb.png" medium="image">
			<media:title type="html">EncryptionInDepthContainers</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/10/encryptionindepthcells_thumb.png" medium="image">
			<media:title type="html">EncryptionInDepthCells</media:title>
		</media:content>
	</item>
		<item>
		<title>Repel Dictionary Attacks With Checksum Truncation of The Random lambda</title>
		<link>http://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/</link>
		<comments>http://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 16:11:00 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[Authenticator]]></category>
		<category><![CDATA[CBC-MAC]]></category>
		<category><![CDATA[CHECKSUM]]></category>
		<category><![CDATA[Cipher Block Chaining]]></category>
		<category><![CDATA[Dictionary Attack]]></category>
		<category><![CDATA[HASHBYTES()]]></category>
		<category><![CDATA[HMAC]]></category>
		<category><![CDATA[MAC]]></category>
		<category><![CDATA[Message Authentication Code]]></category>
		<category><![CDATA[Salt]]></category>
		<category><![CDATA[SIGNBYCERT()]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/</guid>
		<description><![CDATA[One brute force attack is an all out assault that tries every possibility to guess the content of a cell. One brute force target is a &#8216;word&#8217; stored in a hashed cell. A cell in SQL Server cell-level encryption is &#8230; <a href="http://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=265&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>One brute force attack is an all out assault that tries every possibility to guess the content of a cell. One brute force target is a &#8216;word&#8217; stored in a hashed cell. A cell in SQL Server cell-level encryption is generally taken as a column.&nbsp; A dictionary attack is a digital commando raid: a smaller more coordinated attack; and very likely to be more effective than brute force.&nbsp; Both can target hash values stored in SQL Server whether SQL Server did the hashing (HASHBYTES) or the application generated the values. The dictionary attacker assembles the most likely phrases or keys &#8211; the dictionary, then &#8216;joins&#8217; the dictionary to the values to be hacked to identify the key or phrase used to generate the hash. The dictionaries can be built off-line and before-hand to create a swift and powerful attack. The more information exposed to the attacker <em>a priori</em>, the more precise the possible attack. The brute force attacker uses every possible key or phrase so is <em>usually</em> slower.&nbsp; </p>
<p>Dictionary attacking seems to be a popular past-time judging by the number of freely downloadable dictionary attacking applications available. There does not appear to be reliable research to be certain of the prevalence of brute force and dictionary attacks against hashed values in SQL server. My sense is that there may be a disturbing number of attacks that go completely undetected and/or unreported. And as more applications necessarily wade into the cryptographic swamp, attacks will surely increase. </p>
<p>It is important to mention that without encryption attackers have a cake walk. Information is lost the instant the attacker makes that first connection. No need to build a dictionary or try even a single possibility of brute force. Poor data governance will reduce or eliminate the number of brute force and dictionary attacks on your systems! </p>
<p>A simple hash of a value is particularly vulnerable to a dictionary attack. A simple hash being one that simply applies the encryption algorithm to the value. </p>
<pre class="code"><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'</span><span style="color:gray;">, </span><span style="color:teal;">@Value </span><span style="color:gray;">);</span></pre>
<p>Salting a value before hashing helps to confound the dictionary attacker essentially by injecting nonsense into the value. If you can use it, the more salt the better. A salt of comparable size to the value being hashed is recommended.</p>
<pre class="code"><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'</span><span style="color:gray;">, </span><span style="color:teal;">@Value </span><span style="color:gray;">+ </span><span style="color:teal;">@Salt</span><span style="color:gray;">);</span></pre>
<p>With salt, the dictionary attack is useless provided the attacker does not have access to the salt. The salt must be carefully protected. A brute force attack may still succeed though may take significantly longer to complete than without salt. Salt exposed as clear text in another column of the table or in another table or even hard coded creates vulnerability to the dictionary attack once discovered by the attacker. </p>
<p>This underscores the relentless high-stakes battle being waged between data application owners and hackers over hashing and encryption. If a reasonably skilled hacker is determined to crack your encryption, they can eventually do so. <em>SQL Server is particularly vulnerable because the encryption keys are stored with the data.</em> Good defense from dictionary and brute force attacks include: </p>
<ul>
<li>strong, well tested, multi-dimensional security (defense-in-depth)
<li>strongest encryption possible (security above performance)
<li>anonymous lookups &#8211; using salted HASHBYTES()&nbsp; (decrypt only when needed)
<li>securely store and backup all salt &#8211; (store local and remote copies)&nbsp;
<li>securely share public keys (never expose private keys)</p>
<li>encrypt data at rest and all data backups (TDE, file system encryption)&nbsp;
<li>backup encryption keys (store local and remote copies)</p>
<li>securely backup all encryption passphrases (store local and remote copies)&nbsp;
<li>rotate encryption keys and passphrases (force brute force attack restarts) </p>
<li>encryption by combination of keys and passphrases (separation of responsibilities)&nbsp;
<li>very strong passphrase strength </p>
<li>stringent access approval requirements (separation of responsibilities)
<li>continuously test and update roll-back and roll-forward recovery plans </li>
</ul>
<p>Dynamic key management can get messy and/or expensive real quick in recovery scenarios. However, every time you rotate in a new key most attacks reset to square one. The benefit of having a known good backup when you need it is priceless. The headache of sound key management is worth the benefit. Rotate keys faster than the secrets can be guessed and you should be good. How big that window is depends on the strength of the security, strength of the encryption algorithm, strength of the salt as well as the general level of interest in the data and the sophistication of the attacker.&nbsp; </p>
<p>Hashing only part of the value is a common way to further explode the attacker&#8217;s dictionary. This approach includes some unknown part of the value &#8211; of length lambda &#8211; in the hash. The excluded part of the value in the hash &#8211; along with the salt &#8211; makes it that much more difficult for the attacker to assemble the dictionaries.&nbsp; </p>
<pre class="code"><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'
         </span><span style="color:gray;">, LEFT( </span><span style="color:teal;">@Value
               </span><span style="color:gray;">, </span><span style="color:magenta;">FLOOR</span><span style="color:gray;">( </span><span style="color:magenta;">LEN</span><span style="color:gray;">( </span><span style="color:teal;">@Value </span><span style="color:gray;">) / </span>2.0 <span style="color:gray;">)  + </span><span style="color:teal;">@Salt</span><span style="color:gray;">)</span></pre>
<p align="left">Hashing also increases the risk that two rows with <em>different </em>values will produce the same hash. It is a small possibility but that risk is always there with HASHBYTES() or any function that tries to uniquely identify a value using a type with a domain too narrow to uniquely identify all possible values. 15 years ago DATETIME columns with a 1/3 mille-second minimum resolution granularity were being used to uniquely identify rows with some success. Few would even consider a DATETIME as a candidate key today. In less than 15 years the same will be true for HASHBYTES.&nbsp; It is not safe in T-SQL to presume a hash absolutely and uniquely identifies the value represented by the hashed value unless the hash is defined as a unique constraint or unique index of the table where the encrypted value is stored. When the uniqueness of the hash is enforced by DRI, it is also a good idea to always handle the duplicate key error. It is more likely that other columns must be evaluated to determine if a match on the hash is in fact a match on the value. Often &#8211; sometimes even intentionally &#8211; another column is available to resolve the query; others time &#8211; and again sometimes even intentionally &#8211; an encrypted value may need to be unencrypted to complete the join. Having to un-encrypt to fully identify the row can cause application pain if queries must decrypt large sets, but nicely reduces the vulnerability to attack. It is possible in almost all cases to first get the rows that match a specified hash value into a derived table and then to decrypt only the few resulting rows to find the one requested by a query that knows more about the value it wants than <em>just</em> the hash. The bigger the encrypted blobs, the more the encryption of a few resulting rows can become a significant effort for both process and database server. In this regard it is essential to attenuate the hash processing to the application. Probably a good idea to do a sanity check about the value of the hash for a large cell. In general, it is more likely that full-text query processing is needed than an exact match on a 1GB blob.</p>
<p>In light of this unmitigated <em>potential for conflict a </em>de-duplication external to the hashing operation is needed. Never treat a hash of a value as unique unless you put a constraint on the value that it must be unique in the set. I&#8217;m thinking, if the hash cannot be considered unique anyway and the logic must deal with possibility of a duplicate and the data I intend to encrypt is huge (&lt; million rows of customer info is not huge) or under exceptionally heavy load (&lt;5 short running concurrent batches per second is not a heavy load for my laptop), it seems reasonable to me to reduce the hash one step further and define a <em>bucket</em> of hashes that can be represented by the same BINARY_CHECKSUM of the hash. It is not necessary to explicitly put any values into the buckets. That will (may) happen by itself as the hashed value is persisted to the database. In most of my use cases the chance of a duplicate even at the integer level of narrowing is somewhere close to the chance of moon falling out of the sky. The important aspect to recognize is that the buckets do not<em> necessarily</em> represent a single hash just as the hash does not necessarily represent as single value; and then to assure that when duplicates are found in the bucket there is enough information in the query or schema to resolved which of the multiple matches is the one desired. Narrowing the type of the hash to an integer will result in an easier number to work with for the developer, a reduced execution context footprint and reduced read-ahead requirements. </p>
<p>The narrowing method used here also opens the door to randomly generating row identity values at the INT level &#8211; or why not SMALLINT or BIGINT or NUMERIC(7,5) or any primitive SQL type? &#8211; so that the sequence of creation is not revealed in the surrogate key.</p>
<p>Raul Garcia blogged a hash like Message Authentication Code (MAC) scheme that protected against dictionary attacks a while back. In <a href="http://blogs.msdn.com/b/raulga/archive/2006/03/11/549754.aspx">Mr Garcia&#8217;s example</a> the salt appended to the value is the hash of an encrypted NEWID(). As he points out, the encryption of the NEWID produces a non-deterministic value that is a much better random number generator than the SQL Server NEWID() or RAND() functions.&nbsp; The statement he uses to compute a MAC is:</p>
<pre class="code"><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'
         </span><span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">( </span><span style="color:red;">N'ValueKey' </span><span style="color:gray;">)
                                 , </span><span style="color:magenta;">CONVERT</span><span style="color:gray;">( </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>100<span style="color:gray;">)
                                          , </span><span style="color:magenta;">NEWID</span><span style="color:gray;">() ) ) )
</span></pre>
<p>The new GUID is cast to a VARBINARY because SQL Server encryption functions&nbsp; do not have the UNIQUEIDENTIFIER in its vocabulary. The GUID cast as VARBINARY is encrypted to produce a nondeterministic and therefore random value. The encryption function returns a random VARBINARY(8000) that is subsequently hashed with the SHA1 algorithm to produce a VARBINARY(20) digest that represents the encrypted new GUID in a way that has no means to be reverse-engineered. The result is non-deterministic so may be interesting as an unordered identity column &#8211; but there remains always that chance of a duplicate hash value. </p>
<p>CRYPT_GEN_RANDOM can also be used but the <em>name</em> I would have to give the technique is not near as fun. Instead of &#8220;checksum truncation of the random lambda&#8221; we get &#8220;VARBINARY truncation of the random random.&#8221; My guess is this might not scale quite as well either due to the overhead of encryption functions versus hashing functions &#8211; but I have not test that, just guessing&#8230;</p>
<pre class="code"><span style="color:magenta;">CAST</span><span style="color:gray;">(
  </span><span style="color:teal;">CRYPT_GEN_RANDOM
       </span><span style="color:gray;">( </span>4
       <span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">(</span><span style="color:red;">'ValueKey'</span><span style="color:gray;">)
                     , </span><span style="color:red;">N'type align with NEWID cast'
                     </span><span style="color:gray;">, </span>1
                     <span style="color:gray;">, </span><span style="color:magenta;">CAST</span><span style="color:gray;">( </span><span style="color:magenta;">NEWID</span><span style="color:gray;">() </span><span style="color:blue;">AS NCHAR</span><span style="color:gray;">(</span>36<span style="color:gray;">) ) )
        ) </span><span style="color:blue;">AS INT </span><span style="color:gray;">);
</span></pre>
<p>Instead of substring truncation as described above I now propose in most scenarios to use a BINARY_CHECKSUM of the hash to capture an integer representation of the original GUID (Correct me if I am wrong but is not that still deterministic truncation akin SUBSTRING, but in a way that considers the complete underlying value to reduce the probability of any brute force guess being correct instead of throwing part of the values unique identity on the floor?). An index of 4 bytes INT values will fit on 1/10th the number of pages as would an index of the same number of rows with about 40 bytes per row in a VARBINARY(8000). Integers will get you to about the same place in terms of selectivity of the hash value with a significantly reduced total scan length requiring&nbsp; less read-ahead and therefore less memory pressure. Data keyed on whole numbers&nbsp; is endlessly easier to humanly work with than data keyed on a large binary value.</p>
<p>For the MAC that looks something like: </p>
<pre style="width:611px;height:96px;" class="code"><span style="color:magenta;">BINARY_CHECKSUM</span><span style="color:gray;">( </span><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'
                          </span><span style="color:gray;">, </span><span style="color:magenta;">ENCRYPTBYKEY</span><span style="color:gray;">( </span><span style="color:magenta;">KEY_GUID</span><span style="color:gray;">( </span><span style="color:red;">N'ValueKey' </span><span style="color:gray;">)
                                         , </span><span style="color:magenta;">CONVERT</span><span style="color:gray;">( </span><span style="color:blue;">VARBINARY</span><span style="color:gray;">(</span>100<span style="color:gray;">)
                                                  , </span><span style="color:magenta;">NEWID</span><span style="color:gray;">() ) ) ) )</span></pre>
<p>And for a deterministic hashed matching value more like:</p>
<pre class="code"><span style="color:magenta;">BINARY_CHECKSUM</span><span style="color:gray;">(
        </span><span style="color:magenta;">HASHBYTES</span><span style="color:gray;">( </span><span style="color:red;">N'SHA1'
                 </span><span style="color:gray;">, LEFT( </span><span style="color:teal;">@Value
                       </span><span style="color:gray;">, </span><span style="color:magenta;">FLOOR</span><span style="color:gray;">( </span><span style="color:magenta;">LEN</span><span style="color:gray;">( </span><span style="color:teal;">@Value </span><span style="color:gray;">) / </span>2.0 <span style="color:gray;">) + </span><span style="color:teal;">@Salt</span><span style="color:gray;">) )
</span></pre>
<blockquote>
<p>;where @SALT is a well protected static value, perhaps generated as a MAC akin to Raul Garcia&#8217;s original proposal?</p>
</blockquote>
<p>The per row storage advantage of the INT returned by BINARY_CHECKSUM over the VARBINARY(20) returned by HASHBYTES using the &#8216;SHA1&#8242; algorithm is tiny. But it will add-up in a table with millions and millions of rows. Plus, the overhead difference between the INT and the VARBINARY is significant in other ways. As already mentioned, indexes and therefore scan lengths will be somewhat shorter. Sorting will be slightly faster. Development and testing are also marginally easier with the INT type. I&#8217;m spending too much time here to be certain that any performance benefit of INT of VARBINARY is not exaggerated &#8211; if it even exists.&nbsp;&nbsp;&nbsp;&nbsp; <font color="#808080" face="Courier New">&nbsp;</font></p>
<p>It may also be controversial to claim CHECKSUM as a truncation method. CHECKSUM bucketing is a well established and accepted practice however the de facto truncation method at this time is based upon the left most (higher order) bits of the value.&nbsp; The NIST publication <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/draftSP800-133_July2011.pdf">SP-800-133</a>, &#8220;Recommendation for Cryptographic Key Generation&#8221; seems to at least <em>allow</em> for some flexibility in truncation of the hash (I highlighted a few spots in <font color="#ff0000">red</font>):</p>
<blockquote>
<p>Let K be the directly-generated key or the seed to be used to generate a key. K is a bit string value of the following form:<br />K = U ⊕ V, (1)<br />where<br />• U and V are of the same length as K,<br />• U and V are independent of each other, and<br />• U is derived from the output of an approved Random Bit Generator (RBG)<br />within the key-generating module that is generating K; <span style="color:#ff0000;">the output of the RBG may have been transformed by an approved post-processing method</span> (see Section 5.2) to obtain U.</p>
</blockquote>
<p><a href="http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf">FIPS 198-1</a>, &#8220;Keyed-hash Message Authentication Code (HMAC)&#8221; specification &#8211; the more recent NIST darling over the classic Cipher Block Chaining MAC (CBC-MAC) that SQL Server uses &#8211; has something to say about truncation as well:</p>
<blockquote>
<p>A well-known practice with MACs is to truncate their outputs (i.e., the length of the MACs used is less than the length of the output of the HMAC function L). Applications of this standard may truncate the outputs of the HMAC. <span style="color:#ff0000;">When truncation is used, the λ leftmost bits of the output of the HMAC function shall be used as the MAC.</span> For information about the choice of λ and the security implications of using truncated outputs of the HMAC function, see SP 800-107</p>
</blockquote>
<p>Note that in the HMAC specification, the bits to use are stated as an option-less directive! (&#8220;<em>&#8230;shall be used.</em>&#8220;) <a href="http://csrc.nist.gov/publications/nistpubs/800-107/NIST-SP-800-107.pdf">SP-800-107</a>, &#8220;Recommendation for Applications Using Approved Hash Algorithms&#8221;&nbsp; seems pretty clear that the standard truncation method for a hash is only a recommendation for the readers convenience. (Is this really how standards are born? One person writes down an example to try to be helpful. Later someone needs to borrow the captured helpful thought. <em>e viola!</em>&nbsp; In the process of the borrow, the <em>convenience</em> morphs into an edict. Right or wrong, a standard is born.)</p>
<p>SP-800-107 says:</p>
<blockquote>
<p><strong><span style="font-size:medium;"><font size="4">5&nbsp; Cryptographic Hash Function Usage<br /></font></span>5.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Truncated Message Digest</strong><br />Some applications may require a message digest that is shorter than the (full-length) message digest provided by an approved cryptographic hash function specified in [FIPS 180-3]. In such cases, it may be appropriate to use a subset of the bits produced by the cryptographic hash function as the (shortened) message digest.<br />For application interoperability, <span style="color:#ff0000;">a standard method for truncating cryptographic hash function outputs (i.e., message digests) is provided strictly as a convenience</span> for implementers and application developers. The proper use of a truncated message digest is an application-level issue.<br />Let the shortened message digest be called a truncated message digest, and let λ be its desired length in bits. A truncated message digest may be used if the following requirements are met:<br />1. If collision resistance is required, λ shall be at least twice the required collision resistance strength s (in bits) for the truncated message digest (i.e., λ ≥ 2s).<br />2. The length of the output block of the approved cryptographic hash function to be used shall be greater than λ (i.e., L &gt;&nbsp; λ).<br />3. The λ left-most bits of the full-length message digest shall be selected as the truncated message digest</p>
</blockquote>
<p>In Raul Garcia&#8217;s MAC the lambda &#8211; the length of bits being hashed- is not exploited to forge the authentication code. It is based on a new GUID at its core, cast to VARBINARY(100) &#8211; somewhat arbitrarily using that type and size &#8211; because the UNIQUEIDENTIFIER type cannot be used in the hashing function.</p>
<p>In the NIST SP-800-133 sample method the left-most lambda bytes of the value the code authenticates are used. The protection from dictionary attacks is about as perfect as it gets in Mr. Garcia&#8217;s example, however the NIST method can be reproduced as needed in&nbsp; hashed password authentication schemes. Raul&#8217;s method may be better for use in queries where the MAC&#8217;s value is always part of the question (e.g. DRI, joins and indexes). The NIST recommended method is the only option of the two that could correctly be used in a uniqueness test that reproduces the hash and searches for a match in the data set &#8211; or at least a pre-test to get it down to one <em>bucket</em> of MACs that must be cracked open to finally determine the desired row.</p>
<p>In all cases, the only way to assure that a hash or hash-bucket collision in T-SQL does not crash or corrupt the application it to <em>code for collisions</em>. The duplicate hash value collision&nbsp; is a fundamental keyed set dilemma comparable to the old school design mistake of using a DATETIME as a unique key. When a data type cannot describe all the unique values that it are assigned in the set that type can be described as <em>narrowing</em>. Hashed values are narrowing columns for clear text values, buckets are narrowing columns for hashes. A collision occurs when a duplicate value is actually placed in a narrowing column. When a narrowing column is a candidate key an additional piece or two of uniquely identifiable information must be included to resolve the collision. The same hash value must be usable to describe two or more unique values or the application must be open to spurious duplicate key errors. Specifically, a table with a narrowing column must include additional columns in any unique index or key to assure uniqueness. A narrowing column requires query and indexing that do not presume uniqueness of hash or bucket columns along with DRI that can correctly disambiguate a collision.</p>
<p>Whether and how a collision resolver deals with duplicates at the VARBINARY(20) bucket size or the INT (4 bytes) bucket size is not meaningfully different. The beauty of using BINARY_CHECKSUM&nbsp; as a truncation method is that instead of using a fixed subset of bytes from the value as the original value, a subset of each byte is used. With the NIST substring method, the hacker can still perpetrate a dictionary attack on the hash, but is left with the task of mapping the part of the original value not reached by the lambda. That could take a while. With Raul&#8217;s random method, a dictionary attack using his MAC is not possible. The only relationship they have is that the MAC was created because the value already existed.</p>
<p>Using CHECKSUM instead of BINARY_CHECKSUM will reduce the number of buckets as will removing the sign (ABS()). </p>
<p>Interestingly, RSA defines MAC as synonymous with checksum: <a href="http://www.rsa.com/rsalabs/node.asp?id=2177">http://www.rsa.com/rsalabs/node.asp?id=2177</a></p>
<p>Until convinced otherwise, I plan to make use of checksum truncation for bucketing of lookups in my encrypted data where I can. </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/265/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/265/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/265/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=265&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/10/07/repel-dictionary-attacks-with-checksum-truncation-of-the-random-lambda/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Authenticity, Signing, Nesting in T-SQL to Protect Sensitive Data from (even) Highly Privileged Users</title>
		<link>http://bwunder.wordpress.com/2011/10/05/using-authenticity-signing-nesting-in-t-sql-to-protect-sensitive-data-from-even-highly-privileged-users/</link>
		<comments>http://bwunder.wordpress.com/2011/10/05/using-authenticity-signing-nesting-in-t-sql-to-protect-sensitive-data-from-even-highly-privileged-users/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 15:27:34 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[@@NESTLEVEL]]></category>
		<category><![CDATA[ADD SIGNATURE]]></category>
		<category><![CDATA[DDL Triggers]]></category>
		<category><![CDATA[EVENT NOTIFICATIONS]]></category>
		<category><![CDATA[IS_OBJECTSIGNED()]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/10/05/using-authenticity-signing-nesting-in-t-sql-to-protect-sensitive-data-from-even-highly-privileged-users/</guid>
		<description><![CDATA[Digital Non-Repudiation is about distributed communication authenticity. Non-repudiation in the digital security context is a proactive design concept intended to simulate the authentication of a hand written authorization. Evidence that this is a hard problem is found in the still &#8230; <a href="http://bwunder.wordpress.com/2011/10/05/using-authenticity-signing-nesting-in-t-sql-to-protect-sensitive-data-from-even-highly-privileged-users/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=264&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Digital <a href="http://firstmonday.org/htbin/cgiwrap/bin/ojs/index.php/fm/article/view/778/687">Non-Repudiation</a> is about distributed communication authenticity. Non-repudiation in the digital security context is a proactive design concept intended to simulate the authentication of a hand written authorization. Evidence that this is a hard problem is found in the still widespread requirements for notarized hand written signatures in the year 2011. </p>
<p>Non-repudiation as a data layer design element has been widely rejected as unnecessary and invalid because the database is implicitly a trusted internal resource: why would anyone want to verify their own signature and what real use could it serve? Most argue that protecting the endpoint <em>is</em> protecting the data layer. While there is some short term profitability in that position,&nbsp; the breakdown in data layer authenticity is rife with nightmare stories. It would be silly to ignore the risk just because non-repudiation alone does not solve it yet that seems to be the status quo. </p>
<p>Elevation of authority attacks are wide spread. Furthermore, the sophistication of attack as well as identified vectors of attack are expanding. </p>
<p>One major authenticity risk area is forgery or fakery of referenced objects.&nbsp;&nbsp; Even in a change controlled SQL Server database, objects and configuration can be modified in a ways that are not reflected in the current version in the source control system. It is common for shops that develop T-SQL to require periodic re-synchronization between the &#8220;current&#8221; source control &#8220;version&#8221; and the actual objects on a SQL Server. It is essential to eliminate this drift. No matter how astute the data access monitoring tools (DAM), if you do not have the T-SQL source truly under control you don&#8217;t have much in the way of authenticity. </p>
<p><strong>Modes of Authenticity </strong></p>
<p>To combat forgery and fakery a method to determine the authenticity of the other &#8216;players&#8217; in a given communication. Players in a database communication could include client applications, users, SQL Server instances, databases, tables,stored procedures, functions, triggers, queues, etc. Unless your DAM can do this you are not doing enough. Consider this table that lists several ways that are used to determine when a communication is authentic:</p>
<table border="0" cellspacing="2" cellpadding="2" width="461">
<tbody>
<tr>
<td valign="top" width="100"><strong><font>authority</font></strong></td>
<td valign="top" width="100"><strong><font>authenticator</font></strong></td>
<td valign="top" width="130"><strong><font>weakness</font></strong></td>
<td valign="top" width="119"><strong><font>strength</font></strong></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#c0504d">verbal </font></td>
<td valign="top" width="100"><font color="#c0504d">trust</font></td>
<td valign="top" width="130"><font color="#c0504d">deniable</font></td>
<td valign="top" width="119"><font color="#c0504d">convenient</font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#c0504d">signature </font></td>
<td valign="top" width="100"><font color="#c0504d">trust </font></td>
<td valign="top" width="130"><font color="#c0504d">deniable </font></td>
<td valign="top" width="119"><font color="#c0504d">durable </font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#c0504d">signed in triplicate</font></td>
<td valign="top" width="100"><font color="#c0504d">signed copy</font></td>
<td valign="top" width="130"><font color="#c0504d">deniable signature </font></td>
<td valign="top" width="119"><font color="#c0504d">durable</font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#c0504d">signed and notarized</font></td>
<td valign="top" width="100"><font color="#c0504d">Public Notary</font></td>
<td valign="top" width="130"><font color="#c0504d">inconvenient</font></td>
<td valign="top" width="119"><font color="#c0504d">+ trusted authenticator<br /></font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#0000ff">network communication</font></td>
<td valign="top" width="100"><font color="#0000ff">trust </font></td>
<td valign="top" width="130"><font color="#0000ff">deniable </font></td>
<td valign="top" width="119"><font color="#0000ff">convenient</font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#0000ff">signed network communication</font></td>
<td valign="top" width="100"><font color="#0000ff">trust broker</font></td>
<td valign="top" width="130"><font color="#0000ff">posers &amp; rogues</font></td>
<td valign="top" width="119"><font color="#0000ff">non-repudiation</font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#0000ff">data access</font></td>
<td valign="top" width="100"><font color="#0000ff">SQL principal hierarchy<br /></font></td>
<td valign="top" width="130"><font color="#0000ff">posers &amp; rogues</font></td>
<td valign="top" width="119"><font color="#0000ff">KERBEROS&nbsp; </font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#0000ff">DML objects</font></td>
<td valign="top" width="100"><font color="#0000ff">SQL catalog</font></td>
<td valign="top" width="130"><font color="#0000ff">posers &amp; rogues</font></td>
<td valign="top" width="119"><font color="#0000ff">principal of least privilege</font></td>
</tr>
<tr>
<td valign="top" width="100"><font color="#0000ff">signed DML objects</font></td>
<td valign="top" width="100"><font color="#0000ff">SQL encryption hierarchy</font></td>
<td valign="top" width="130"><font color="#0000ff">rogues</font></td>
<td valign="top" width="119"><font color="#0000ff">schema authenticity</font></td>
</tr>
</tbody>
</table>
<p>Whether schema authenticity at the data layer is non-repudiation at the network layer is unimportant provided there is some acceptance for using the strengths and weaknesses listed in identifying relative value of authenticity in various architectural styles of communication and at various structural layers to the degree that looking at non-repudiation helps provide a stronger conceptual basis to establish adequate strong authenticity at the data layer.&nbsp; </p>
<p><em>Given: </em></p>
<blockquote><p>that a T-SQL attacker that obtains an ability to connect with elevated sysadmin or dbo credentials is unstoppable from carrying out their will</p>
<p>and,</p>
<p>that users with dbo database credentials &#8211; including the sysadmin server role members that are automatically made dbo when they enter any database, have implicit permissions to change <strong>all</strong> database configuration and object definitions in ways that will alter results returned to the application yet go undetected by the application or by internal database signature validation of the objects directly involved in legitimate database operations</p>
<p>and,</p>
<p>that it is always a plausible scenario that a currently trusted user with elevated authority can unexpectedly become an attacker using sysadmin or dbo authority</p>
</blockquote>
<p>&nbsp; <em>then,</em></p>
<blockquote><p>signature based non-repudiated protocols alone cannot assure the authenticity of the simplest of database operations.&nbsp; </p>
</blockquote>
<p>In non-repudiation, about all that is required is common access of the <u>two</u> parties to a public/private key pair (CREATE CERTIFICATE) to certify the communication. The objective of non-repudiation is mostly to assure that everyone gets the message at a pragmatic level. Non-repudiation doesn&#8217;t care what the two parties do after the communication or if the information exchange was useful; only that both parties are who they say they are and perhaps the content of &#8211; or altered state resulting from &#8211; the communication.</p>
<blockquote><p>&#8220;Non-repudiation protocols are designed for verifying that, when two parties exchange information over a network, neither one nor the other can deny having participated to this communication.&#8221;&nbsp; (<a href="http://www.avantssar.eu/pdf/publications/paperKV-FAST08.pdf">Klay &amp; Vigneron</a>)</p>
</blockquote>
<p>Obviously, the &#8216;parties&#8217; in a database operation that runs completely within the SQL Server&#8217;s memory space do not normally exchange information over a network; but they <em>can</em> if someone wants that functionality &#8212; or injects that functionality. Likewise, there should be no argument that the &#8216;two parties&#8217; in a database operation are really two software components of a common host most of time and in fact are more likely to be three or more components than the always dyadic constraint of communication between so called network endpoint . The party can grow quite large when you start looking at tall the database objects that are involved &#8211; and so can be manipulated maliciously &#8211; in a database operation. Limiting the communication at the database to two parties is beyond unrealistic. This goes to the very important to a point I wish to clearly establish above all else: a malicious user with elevated authority in the database can easily modify the unprotected database in ways that can significantly alter the database and/or the data returned. </p>
<p>At the <a href="http://www.pinnaclesports.com">sports book</a> where I did a little DBA work one clever syndicate (organized group of thieves and crooks) figured out how to flip their bets to the winner on the over and under at just the moment between the end of a game and when the business layer automation could settled the wagers for the event. As far as I know it was never possible to say they were actually caught&#8230; It is nothing short of astonishing that this could have been done without insider assistance. If you saw the complexity of what they had done to manipulate wagers and the thoroughness used to cover the tracks you would likely agree. Yet &#8220;it was outsiders&#8221; seems to be the conclusion they (the management team mostly but Interpol and even Scotland Yard were involved somehow) reached in the investigation. This all even before the crooks started to get an idea anyone was on to them, but nabbing international attackers is not such an easy thing to do; to some (large?) extent due to corruption. Another part of this particular scam involved playing poker with the dishonest winnings against another syndicate member and losing intentionally to launder the ill-gotten winnings from the tainted account where the bit had been flipped into an account not directly tied to the hack. (Probably a good table to sitting at for the honest gambler too!) I was never really in on the skinny but did hear a few of the details: investigators somehow decided that there was no insider involved. I even saw a drivers license photo of the top guy in the syndicate from the other side of the world. I also finally got the permission I had been so far hopelessly seeking to reduce the permissions on some of the legacy application level SQL Logins. Still could not get them to budge on switching to Windows Authentication because they could not get their act together to move away from the 1 ginormous database connected directly to scads of web servers in the DMZ architecture. No idea how it ended with the attackers.&nbsp; It was the sort of thing that went on continuously in that industry but these guys were a little more insidious and a little more successful than most. </p>
<p>I predict that the state of siege that the on-line sports book has been under for the last 10 years is a precursor to what will be common in the near future.&nbsp;&nbsp; </p>
<p>It is the rare application that is able to detect let alone respond to the morphing or injection of database objects and the resulting bogus operations at run time. Pretty sure that statement can be applied to all flavors of SQL. For T-SQL application DML to be aware of the integrity of the data layer I know to be both quite possible and almost never done. The accepted practice instead is an <a href="http://plato.stanford.edu/entries/existentialism/">existential presumption of authenticity</a> of referenced database objects. (e.g. tables, stored procedures, functions, triggers, views, permissions, users, roles, certificates, etc.)? For the most part, this presumption relies upon the intrinsic hierarchical role based security model and absolute confidence in the integrity of the system(s). This is most realistic when only a trusted few are able to access the database from a role at the top of the hierarchy and at the lower rungs of the hierarchy the power to make change is highly restricted or revoked. </p>
<p>I&#8217;m thinking that is backward. It is obviously necessary to vigilantly assure that all relevant schema objects and configuration settings have not changed. Especially when changed in such a way that the result of database operation are altered? Only when there is certainty about the integrity all relevant schema objects would it be possible to certify the authenticity of the database operation. I need an example to even feel like I am explaining my premise adequately.&nbsp; </p>
<p><strong>A Facetious, Fictitious, Farcical Far Too Likely to be True Example</strong></p>
<p>Consider this schema that inserts a Boolean value using a stored procedure. There is no other functionality. Period.</p>
<pre class="code"><span style="color:blue;">create table </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
  </span><span style="color:gray;">( </span><span style="color:teal;">id </span><span style="color:blue;">int identity</span><span style="color:gray;">(</span>1<span style="color:gray;">,</span>1<span style="color:gray;">) PRIMARY KEY
  , </span><span style="color:teal;">user_choice </span><span style="color:blue;">BIT </span><span style="color:gray;">);
</span><span style="color:blue;">go
create proc </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice
  </span><span style="color:gray;">( </span><span style="color:teal;">@choice </span><span style="color:blue;">BIT </span><span style="color:gray;">)
</span><span style="color:blue;">as
  insert </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally </span><span style="color:gray;">(</span><span style="color:teal;">user_choice</span><span style="color:gray;">)
  </span><span style="color:blue;">values </span><span style="color:gray;">(</span><span style="color:teal;">@choice</span><span style="color:gray;">);
</span><span style="color:blue;">go</span></pre>
<p>Let&#8217;s say this is a temporary polling station set up in a location restricted to only employees yet openly accessible to all employees of a business. The poll&nbsp; promises an anonymous result yet with a stated request (rule of trust) that everyone only vote once and assurance of an anonymous result: there is no way to tell who placed any vote. The kitchen user&#8217;s are asked if they would like to discontinue the currently catered snacks and lunches in the kitchen in response to a widespread outcry after a recent outbreak of food born illness among workers when the potato salad was left out over the weekend. A polling station is a laptop placed on the end of the kitchen counter by the toaster with text instructions for the one question survey loaded into Notepad telling kitchen users how to open the SSMS query tool, connect to the correct database and place a vote by executing a stored procedure from an SSMS query connection. Examples of the exact syntax for yes and no that can be copied from notepad and pasted to SSMS are included as is a request for &#8220;each user to PLEASE! vote only once&#8221; and the query that will be used to determine the result. Not a second thought is given to security or user interface due to the high confidence that only trusted users could access the location. </p>
<pre class="code"><span style="color:green;">-- YES - paste this to query window and execute to vote yes
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>1<span style="color:gray;">;
</span><span style="color:green;">-- NO - paste this to query window and execute to vote no
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:green;">-- this query will determine the winner
</span><span style="color:blue;">select TOP</span><span style="color:gray;">(</span>1<span style="color:gray;">) </span><span style="color:teal;">user_choice </span><span style="color:blue;">as </span><span style="color:teal;">[winner]
     </span><span style="color:gray;">, </span><span style="color:magenta;">count</span><span style="color:gray;">(*) </span><span style="color:blue;">AS </span><span style="color:teal;">votes
</span><span style="color:blue;">from </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;">group by </span><span style="color:teal;">user_choice
</span><span style="color:blue;">order by </span><span style="color:teal;">votes </span><span style="color:blue;">desc<span style="color:gray;">; </span></span></pre>
<p>Drop in an few votes an see how things look:</p>
<pre class="code"><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>1<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">select TOP</span><span style="color:gray;">(</span>1<span style="color:gray;">) </span><span style="color:teal;">user_choice </span><span style="color:blue;">as </span><span style="color:teal;">[winner]
     </span><span style="color:gray;">, </span><span style="color:magenta;">count</span><span style="color:gray;">(*) </span><span style="color:blue;">AS </span><span style="color:teal;">votes
</span><span style="color:blue;">from </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;">group by </span><span style="color:teal;">user_choice
</span><span style="color:blue;">order by </span><span style="color:teal;">votes </span><span style="color:blue;">desc</span><span style="color:gray;">;
</span></pre>
<p>The result is</p>
<pre class="code">winner votes
------ -----------
0      3</pre>
<p>That looks right to me.</p>
<p>What no one could have known is that a militant raw vegan PETA loony colleague &#8211; a web developer with adequate SQL skills and exceptional attitude that actually did not use the kitchen much because of her now 4 year running raw vegan &#8216;fad&#8217; diet &#8211; would be one of the first to enter the kitchen after the voting begins. This person&#8217;s naked agenda is the abolition of meat and meat by products from the human diet by all non-violent means possible. She pops open the connection to the database as described in the note and needs only a few seconds to understand the schema and the stored procedure, a moment to think and a few keystrokes to add a trigger that would assure the outcome yet risk minimal additional scrutiny that might be caused by a completely outlandish results. </p>
<pre class="code">

<span style="color:blue;">create trigger </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">MSIndexMaintenance
</span><span style="color:blue;">on </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;"><span style="color:blue;">with encryption </span></span>

<span style="color:blue;"><span style="color:blue;"></span></span><span style="color:blue;">instead of insert   </span>

<span style="color:blue;">as
set nocount on</span><span style="color:gray;">;
</span><span style="color:blue;">insert </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally </span><span style="color:gray;">(</span><span style="color:teal;">user_choice</span><span style="color:gray;">)
</span><span style="color:blue;">select case when </span><span style="color:gray;">( </span><span style="color:teal;">t</span><span style="color:gray;">.</span><span style="color:blue;">now </span><span style="color:gray;">&lt; </span>.55 <span style="color:gray;">)
            </span><span style="color:blue;">then </span>1 <span style="color:blue;">else </span><span style="color:teal;">i</span><span style="color:gray;">.</span><span style="color:teal;">user_choice </span><span style="color:blue;">end
from </span><span style="color:teal;">inserted </span><span style="color:blue;">as </span><span style="color:teal;">i
</span><span style="color:gray;">cross join
  (</span><span style="color:blue;">select </span><span style="color:magenta;">sum</span><span style="color:gray;">(</span><span style="color:magenta;">cast</span><span style="color:gray;">(</span><span style="color:teal;">user_choice </span><span style="color:blue;">as float</span><span style="color:gray;">))/</span><span style="color:magenta;">count</span><span style="color:gray;">(*) </span><span style="color:blue;">as now
   from </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally </span><span style="color:gray;">) </span><span style="color:blue;">as </span><span style="color:teal;">t</span><span style="color:gray;">;</span>
</pre>
<p>after running the exact same set of inserts again (remember the other 4 votes are already there) </p>
<pre class="code"><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>1<span style="color:gray;">;
</span><span style="color:blue;">exec </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice </span>0<span style="color:gray;">;
</span><span style="color:blue;">select TOP</span><span style="color:gray;">(</span>1<span style="color:gray;">) </span><span style="color:teal;">user_choice </span><span style="color:blue;">as </span><span style="color:teal;">[winner]
     </span><span style="color:gray;">, </span><span style="color:magenta;">count</span><span style="color:gray;">(*) </span><span style="color:blue;">AS </span><span style="color:teal;">votes
</span><span style="color:blue;">from </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;">group by </span><span style="color:teal;">user_choice
</span><span style="color:blue;">order by </span><span style="color:teal;">votes </span><span style="color:blue;">desc</span><span style="color:gray;">;
</span></pre>
<p>There are now 8 rows in the table. Two (2) rows should hold the value zero (0). The other six (6) should be 1. Right? The result from the summary query is now:</p>
<pre class="code">winner votes
------ -----------
1      4</pre>
<p>Oops&#8230;</p>
<p>This may explain why so many corporate kitchens have gone vegan! What&#8217;s worse (better?), signature checking of the compiled objects to establish a non-repudiated communication would not have helped the bottom line of a single feedlot or hot dog factory. The signature of a SQL Server table is unaffected by the addition, modification or removal of a trigger or a permission placed on that table. </p>
<p>Adding a trigger is not the only hi-jinx possible. A Synonym pointing to a Linked Server location that replaces the table is another possibility for &#8216;stealing&#8217; votes. Or how about simply adding the trigger logic to the stored procedure? Other possibilities may occur to the reader. Many exist. </p>
<p>The example shows the ease and stealth with which the T-SQL outcome can be manipulated. The result is made invalid and any claim of authenticity left looking foolish by the facts after a hack if steps are not taken to assure schema authenticity. This hole in the signature seems like the utility company allowing you an electrical outlet that does not go through the meter (guess where I plug everything in). One thing is for sure: the hackers will continue to bang away at Microsoft implementations in search of vulnerabilities as long as Windows is a leader in the server space. And if there is a problem it will continue to become known before too many people get stomped on. I can only hope it does not become known with my data&#8230; Notice I mentioned only Windows and not SQL Server. That is because an elevation of authority attack will most likely occur before the stolen highly privileged user credentials are use to gain database access. The only other real possibilities are an insider attack or SQL Injection combined with patience.&nbsp; </p>
<p>Of course the base farcical &#8216;mistake&#8217; in the example application is reliance upon the honesty of people. Almost every application makes this mistake of foolish trust to one degree or another, it is admittedly presented as self portrait in caricature in the example. In computer applications trust is used as an acceptable calculate risk in the interest of efficiency and supportability. On the Internet, even that friend, loved one, colleague or boss can be convincingly spoofed. The only rule you need to stay digitally safe, especially when the Internet is in the picture is, &#8220;trust no-one&#8221;. Most of us step over that boundary far to often and don&#8217;t even realize it. We forget that computers are not people. </p>
<p>And there are many other errors in design in the made up example. Some even intentional. For example, the presumption that the data is safe because it is in a secure physical location is not only fallacious but proved to be an invalid assumption based solely on hope. Speculative design is not likely to produce authentic results. </p>
<p>The status quo is that database operations do no need to meet the test of non-repudiation. OK, fine. What I cannot agree with though is the unspoken consequential decision to simply not worry about authenticity at the data layer. It makes my head spin to think too long about all the ways the integrity of a database operation can be maliciously corrupted or compromised. Although non-repudiation sets a pretty low bar for authenticity because it presumes that communication is dyadic and because it has no interest in the process, only the participants. </p>
<p>Simplistic shared secret verification <em>a la</em> non-repudiation is inadequate to assure communication authenticity in SQL Server. Many changes to an object&#8217;s component attributes (indexes, triggers, permissions, etc.) and dependencies (called modules and referenced tables) are not encapsulated by an object&#8217;s signature when signed using T-SQLs <a href="http://msdn.microsoft.com/en-us/library/ms181700.aspx">ADD SIGNATURE</a> statement. For example, object signing alone on a table does not see any CREATE/ALTER/DROP of triggers or indexes on the table or any GRANT/DENY/REVOKE permission applied to that table. Likewise changing the table in a way that <em>does</em> invalidate the signature would do nothing to the T-SQL signature of a stored procedure that references the table or a trigger attached to the table. </p>
<p><strong>Toward Authenticity at the Data Layer</strong></p>
<p>Actions to gain confidence in the authenticity of database operation include:</p>
<ul>
<li><strong>Control Change. </strong>Allow <em>only</em> schedule, reviewed and well tested changes. Be unequivocal about this. Shoot for only <em>planned</em> change too, but be willing to schedule the occasional one-off as long as it meets the established review and testing standards. Be willing to adjust the standard to improve results.
<li><strong>Limit change.</strong> Limit the number of individuals that can apply changes to the environment and limit the the number of changes any individual can make to those needed to do what they do. Always align the permissions of the database user with the access required by the user as precisely as practical (principle of least privilege).&nbsp;&nbsp;
<li><strong>Digitally sign all objects in the schema at creation.</strong> Use a carefully guarded key and then &#8216;continuously&#8217; verify that the signature of self and all legitimately referenced objects are in tact at run-time. The private key of a certificate can be removed from the SQL Server when not needed. Object signatures can be verified using T-SQLs IS_OBJECTSIGNED() function without the private key yet a signature cannot be reapplied until the private key is restored.&nbsp; Consider a password signed certificate with a <a href="http://en.wikipedia.org/wiki/Password_strength">very strong password</a> when security requirements granularity for the key is not aligned with the role/principal hierarchy.&nbsp;&nbsp;&nbsp;
<li>
<div align="left"><strong>Silently monitor for changes.</strong> An asynchronous process that captures all change is essential for monitoring and forensics. One method is to use <a href="http://msdn.microsoft.com/en-us/library/ms182602.aspx">EVENT NOTIFICATIONS</a> that include all DDL_DATABASE_LEVEL_EVENTS. Log and protect the log from unauthorized access. Maintain high confidence that not only the message but also the message delivery system is not compromised. Any process able to leverage <em>dbo</em> or <em>sysadmin</em> authority can compromise any SQL Server change control system; including event notifications.&nbsp;&nbsp; </div>
<li><strong>Proactively prevent unauthorized change.</strong>&nbsp; The intersections of authority for a role based provisioning model and the permissions based access model can create threat holes. Some users end up with more access than they need. The most likely suspect is when an group from the domain or tree is plopped into a role in SQL Server. Most never know it. The easiest way to become convinced is to try to plug that hole. A <a href="http://msdn.microsoft.com/en-us/library/ms190989.aspx">DDL trigger</a> that rolls back all DDL_DATABASE_LEVEL_EVENTS. stop all change by all users. And it does except for one change for any user with ALTER ANY DATABASE DDL TRIGGER permission can make: DROP TRIGGER on that DDL trigger. ALTER ANY DATABASE DDL TRIGGER&nbsp;&nbsp; If you add another identical triggers it is not possible to drop either trigger without first disabling the other trigger. That is not very much defense since the user that can ALTER a trigger can also disable the trigger and there is no event available to the trigger that can detect the disable trigger event. SQL Trace can see DISABLE TRIGGER events. An alert from a custom trace event watching for the text &#8220;DISABLE TRIGGER&#8221; could be configured to protect against DISABLE TRIGGER. This actually could be effective in restricting a <em>dbo</em> authorized attacker in some scenarios but would be just another trivial obstacle for a <em>sysadmin</em> authorized attacker.&nbsp;
<li><strong>Encrypt Sensitive Data.</strong> Use SQL Server encryption hierarchy(ies) that require strong password(s) or encryption based on keys not available to other database users. It is recommended that secure on-site and off-site backups of all keys be maintained at all times. Restrict key management to a very small group of trusted users.&nbsp;
<li><strong>Verify schema integrity at run time.</strong> The most straightforward verification would be to compare the object tree in the schema to a hardcoded static list encapsulated in an encrypted executable object. The object cannot be changed by other users without the loss of the signature as the object is changed. Other users cannot reapply the well protected signature thus reducing the check for change to an inexpensive IF EXISTS&nbsp; on the catalog view of encrypted objects filtered by the key/cert of your signature. In other scenarios it my provide more confidence to include signed data value validation between executable database objects a la non-repudiation &#8211; especially for critical operations. Complementary to object signing, there should be some assurance that the object signature or key used are not compromised. Also the verification must include all reference objects &#8211; expected or unexpected. Consider signing a parameter or introducing signatures based on a different well protected key than the one used to sign the objects between called database objects to build greater confidence in the objects authenticity. The key of the data signature gives you an additional common shared local resource that is expected to be difficult to compromise for cross-validation of the objects&#8217; authenticity. </p>
<li><strong>Use system encryption for all objects (WITH ENCRYPTION).</strong> This helps prevent the uninvited from following along and provides the added benefit of protecting strong and long secrets that can be compiled into encrypted objects without risk of exposure as clear text. The combination of DML object Encryption and SQL Trace&#8217;s built-in encryption statement masking are key to effective run-time secret protection <em>at this time</em>. (Windows Debugger attackers may still be able to steal secrets from buffers where they might be placed in clear text. It should be possible to make sure live systems do not have the necessary debugger symbols.) As a DBA there is nothing more frustrating than trying to support a 3rd party database with encrypted objects. I concur and will do what I can to avoid that thankless task. Encrypting yourself is not so painful because you can unencrypt in development to debug. Wipe that unencrypted database clean when done debugging and protect it extra carefully while it is visible.&nbsp;
<li><strong>Disable data<em>base-chaining</em> and <em>trustworthy </em>database options.</strong> This will reduce the exposure to cross database elevation of authority attacks. </p>
<li><strong>Don&#8217;t help hackers with error details.</strong> Watch the @@NESTLEVEL value in CATCH block and always use try-catch error handling. When @@NESTLEVEL = 0 then the error is on the command line and should not be displayed. WHEN the NESTLEVEL = 1 then the caller is a command line and any error information should not be returned to the command line call. When @@NESTLEVEL &gt; 1 then return just enough information to the caller for locating the logged error.&nbsp; </li>
</ul>
<p>This is a listing of the minimum necessary to be confident in the authenticity at the data layer.&nbsp; Without meeting all of these measure in combination, database data is not safe from posers ( including elevation of authority attackers, brute force password attackers, SQL Injection attackers, etc.) &#8211; and the rogue insiders. There is more that could be done. For example in highly secured settings it may be worthwhile to sign object interactions by using a technique that looks a lot like non-repudiation.&nbsp; Eventually even strong security must succumb to the law of diminishing returns and the level of perceived risk. I think it sufficient to acknowledge that perfect security is not attainable but must remain always the objective.&nbsp; </p>
<p>A revised application with much higher assurance of object authenticity based upon that insert into a bit column would look a bit different. The example revision explodes the original applications 10 lines script to create the database objects&nbsp; to over 200 lines of T-SQL.&nbsp; </p>
<pre style="width:588px;height:645px;" class="code"><span style="background:silver;">:SETVAR SIGNATURE_PASSWORD "a_$1LLY-n-str0nG_fraze"
</span><span style="color:blue;">CREATE DATABASE </span><span style="color:teal;">test</span><span style="color:gray;">;
</span><span style="color:blue;">ALTER DATABASE </span><span style="color:teal;">test </span><span style="color:blue;">SET TRUSTWORTHY OFF</span><span style="color:gray;">;
</span><span style="color:blue;">ALTER DATABASE </span><span style="color:teal;">test </span><span style="color:blue;">SET DB_CHAINING OFF</span><span style="color:gray;">;
</span><span style="color:blue;">GO
USE </span><span style="color:teal;">test</span><span style="color:gray;">;
</span><span style="color:green;">-- silent monitor
</span><span style="color:blue;">CREATE QUEUE </span><span style="color:teal;">DDLChangesQueue </span><span style="color:blue;">WITH RETENTION </span><span style="color:gray;">= </span><span style="color:blue;">ON</span><span style="color:gray;">;
</span><span style="color:blue;">CREATE SERVICE </span><span style="color:teal;">DDLChangesService
</span><span style="color:blue;">ON QUEUE </span><span style="color:teal;">DDLChangesQueue
  </span><span style="color:gray;">( </span><span style="color:teal;">[http://schemas.microsoft.com/SQL/Notifications/PostEventNotification] </span><span style="color:gray;">);
</span><span style="color:blue;">CREATE EVENT NOTIFICATION </span><span style="color:teal;">DDLChanges
</span><span style="color:blue;">ON DATABASE
FOR </span><span style="color:teal;">DDL_DATABASE_LEVEL_EVENTS
</span><span style="color:blue;">TO SERVICE </span><span style="color:red;">'DDLChangesService'</span><span style="color:gray;">, </span><span style="color:red;">'current database' </span><span style="color:gray;">;
</span><span style="color:blue;">GO
ALTER AUTHORIZATION ON DATABASE</span><span style="color:gray;">::</span><span style="color:teal;">test </span><span style="color:blue;">TO </span><span style="color:teal;">sa</span><span style="color:gray;">;
</span><span style="color:blue;">GO
CREATE ROLE </span><span style="color:teal;">testAdministrator</span><span style="color:gray;">;
</span><span style="color:green;">-- add current user to role
</span><span style="color:blue;">DECLARE </span><span style="color:teal;">@CreateUserDDL </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>512<span style="color:gray;">);
</span><span style="color:blue;">SET </span><span style="color:teal;">@CreateUserDDL </span><span style="color:gray;">= </span><span style="color:red;">N'CREATE USER [' </span><span style="color:gray;">+ </span><span style="color:magenta;">ORIGINAL_LOGIN</span><span style="color:gray;">()
                   + </span><span style="color:red;">N']; EXEC sp_addrolemember ''testAdministrator'', '''
                   </span><span style="color:gray;">+ </span><span style="color:magenta;">ORIGINAL_LOGIN</span><span style="color:gray;">() + </span><span style="color:red;">N'''' </span><span style="color:gray;">;
</span><span style="color:blue;">EXEC </span><span style="color:maroon;">sp_executesql </span><span style="color:teal;">@CreateUserDDL</span><span style="color:gray;">;
</span><span style="color:blue;">GO
</span><span style="color:green;">-- cert encrypted by DMK
</span><span style="color:blue;">CREATE CERTIFICATE </span><span style="color:teal;">SigCert
</span><span style="color:blue;">ENCRYPTION BY PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'$(SIGNATURE_PASSWORD)'
</span><span style="color:blue;">WITH SUBJECT </span><span style="color:gray;">= </span><span style="color:red;">'object signatures' </span><span style="color:gray;">;
</span><span style="color:blue;">GO
CREATE TABLE </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
  </span><span style="color:gray;">( </span><span style="color:teal;">Id </span><span style="color:blue;">UNIQUEIDENTIFIER </span><span style="color:gray;">NOT NULL </span><span style="color:green;">-- int identity(1,1)
  </span><span style="color:gray;">, </span><span style="color:teal;">User_choice </span><span style="color:blue;">BIT </span><span style="color:gray;">);
</span><span style="color:blue;">GO
ADD SIGNATURE TO </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;">BY CERTIFICATE </span><span style="color:teal;">SigCert
</span><span style="color:blue;">WITH PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'$(SIGNATURE_PASSWORD)'</span><span style="color:gray;">;
</span><span style="color:blue;">GO
</span><span style="color:green;">-- does not affect signature of table
</span><span style="color:blue;">CREATE CLUSTERED INDEX </span><span style="color:teal;">ixc_tally </span><span style="color:blue;">ON </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally</span><span style="color:gray;">(</span><span style="color:teal;">user_choice</span><span style="color:gray;">);
</span><span style="color:blue;">GO
CREATE PROC </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice
  </span><span style="color:gray;">( </span><span style="color:teal;">@choice </span><span style="color:blue;">BIT </span><span style="color:gray;">)
</span><span style="color:blue;">AS
BEGIN
  BEGIN TRY
    IF </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">IS_OBJECTSIGNED</span><span style="color:gray;">(</span><span style="color:red;">'OBJECT'
                              </span><span style="color:gray;">, </span><span style="color:magenta;">@@PROCID
                              </span><span style="color:gray;">, </span><span style="color:red;">'CERTIFICATE'
                              </span><span style="color:gray;">, </span><span style="color:teal;">thumbprint </span><span style="color:gray;">)
             + </span><span style="color:magenta;">IS_OBJECTSIGNED</span><span style="color:gray;">(</span><span style="color:red;">'OBJECT'
                              </span><span style="color:gray;">, </span><span style="color:magenta;">OBJECT_ID</span><span style="color:gray;">( </span><span style="color:red;">'dbo.tally'</span><span style="color:gray;">, </span><span style="color:red;">'U' </span><span style="color:gray;">)
                              , </span><span style="color:red;">'CERTIFICATE'
                              </span><span style="color:gray;">, </span><span style="color:teal;">thumbprint </span><span style="color:gray;">)
             + </span><span style="color:magenta;">IS_OBJECTSIGNED</span><span style="color:gray;">(</span><span style="color:red;">'OBJECT'
                              </span><span style="color:gray;">, </span><span style="color:magenta;">OBJECT_ID</span><span style="color:gray;">( </span><span style="color:red;">'dbo.trg_tally'</span><span style="color:gray;">, </span><span style="color:red;">'TR' </span><span style="color:gray;">)
                              , </span><span style="color:red;">'CERTIFICATE'
                              </span><span style="color:gray;">, </span><span style="color:teal;">thumbprint </span><span style="color:gray;">)
             +  ( </span><span style="color:blue;">SELECT </span><span style="color:magenta;">COUNT</span><span style="color:gray;">(*) </span><span style="color:blue;">AS </span><span style="color:teal;">[NbrTriggers]
                  </span><span style="color:blue;">FROM </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">triggers
                  </span><span style="color:blue;">WHERE </span><span style="color:teal;">parent_id </span><span style="color:gray;">= </span><span style="color:magenta;">OBJECT_ID</span><span style="color:gray;">( </span><span style="color:red;">'dbo.tally'</span><span style="color:gray;">, </span><span style="color:red;">'U' </span><span style="color:gray;">)
                  AND </span><span style="color:magenta;">object_id </span><span style="color:gray;">&lt;&gt; </span><span style="color:magenta;">OBJECT_ID</span><span style="color:gray;">( </span><span style="color:red;">'dbo.trg_tally'</span><span style="color:gray;">, </span><span style="color:red;">'TR' </span><span style="color:gray;">) )
        </span><span style="color:blue;">FROM </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">certificates
        </span><span style="color:blue;">WHERE </span><span style="color:teal;">name </span><span style="color:gray;">= </span><span style="color:red;">'SigCert'
        </span><span style="color:gray;">AND </span><span style="color:magenta;">object_name</span><span style="color:gray;">(</span><span style="color:magenta;">@@PROCID</span><span style="color:gray;">) = </span><span style="color:red;">'submit_choice' </span><span style="color:gray;">) &lt;&gt; </span>3
      <span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'unable to verify object signatures'</span><span style="color:gray;">,</span>16<span style="color:gray;">,</span>1<span style="color:gray;">);
    </span><span style="color:blue;">INSERT </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally </span><span style="color:gray;">(</span><span style="color:teal;">user_choice</span><span style="color:gray;">)
    </span><span style="color:blue;">VALUES </span><span style="color:gray;">(</span><span style="color:teal;">@choice</span><span style="color:gray;">);
  </span><span style="color:blue;">END TRY
  BEGIN CATCH
    SELECT  </span><span style="color:magenta;">ERROR_NUMBER</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorNumber
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_SEVERITY</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorSeverity
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_STATE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorState
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_PROCEDURE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorProcedure
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_LINE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorLine
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_MESSAGE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorMessage</span><span style="color:gray;">;
  </span><span style="color:blue;">END CATCH
END
GO
ADD SIGNATURE to </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">submit_choice
</span><span style="color:blue;">BY CERTIFICATE </span><span style="color:teal;">SigCert
</span><span style="color:blue;">WITH PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'$(SIGNATURE_PASSWORD)'</span><span style="color:gray;">;
</span><span style="color:blue;">GO
CREATE PROC </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">get_results
</span><span style="color:blue;">AS
  SELECT </span><span style="color:teal;">user_choice </span><span style="color:blue;">as </span><span style="color:teal;">choice
        </span><span style="color:gray;">, </span><span style="color:magenta;">rank</span><span style="color:gray;">() </span><span style="color:blue;">OVER
          </span><span style="color:gray;">(</span><span style="color:blue;">ORDER BY </span><span style="color:magenta;">COUNT</span><span style="color:gray;">(*) </span><span style="color:blue;">DESC</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:magenta;">rank
        </span><span style="color:gray;">, </span><span style="color:magenta;">count</span><span style="color:gray;">(*) </span><span style="color:blue;">AS </span><span style="color:teal;">votes
  </span><span style="color:blue;">FROM </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
  </span><span style="color:blue;">GROUP BY </span><span style="color:teal;">user_choice
  </span><span style="color:blue;">ORDER BY </span><span style="color:magenta;">rank </span><span style="color:blue;">DESC</span><span style="color:gray;">;
</span><span style="color:blue;">GO
ADD SIGNATURE to </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">get_results
</span><span style="color:blue;">BY CERTIFICATE </span><span style="color:teal;">SigCert
</span><span style="color:blue;">WITH PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'$(SIGNATURE_PASSWORD)'</span><span style="color:gray;">;
</span><span style="color:blue;">GO
</span><span style="color:green;">-- instead trigger fires BEFORE constraints
-- constraints are applied before after triggers
</span><span style="color:blue;">CREATE TRIGGER </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">trg_tally
</span><span style="color:blue;">ON </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally
</span><span style="color:blue;">INSTEAD OF INSERT</span><span style="color:gray;">, </span><span style="color:blue;">UPDATE</span><span style="color:gray;">, </span><span style="color:blue;">DELETE
AS
BEGIN
  BEGIN TRY
    </span><span style="color:green;">-- only inserts, only 1 row at a time
    </span><span style="color:blue;">IF </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">COUNT</span><span style="color:gray;">(*) </span><span style="color:blue;">FROM </span><span style="color:teal;">inserted</span><span style="color:gray;">) &gt; </span>1
      <span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'no multi-row'</span><span style="color:gray;">, </span>16<span style="color:gray;">, </span>1<span style="color:gray;">);
    </span><span style="color:blue;">IF </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">COUNT</span><span style="color:gray;">(*) </span><span style="color:blue;">FROM </span><span style="color:teal;">deleted </span><span style="color:gray;">) &gt; </span>0
      <span style="color:blue;">IF </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">COUNT</span><span style="color:gray;">(*) </span><span style="color:blue;">FROM </span><span style="color:teal;">inserted</span><span style="color:gray;">) = </span>1
        <span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'no update'</span><span style="color:gray;">, </span>16<span style="color:gray;">, </span>1<span style="color:gray;">);
      </span><span style="color:blue;">ELSE
        RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'no delete'</span><span style="color:gray;">, </span>16<span style="color:gray;">, </span>1<span style="color:gray;">);
    </span><span style="color:blue;">INSERT </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">tally  </span><span style="color:gray;">(</span><span style="color:teal;">id</span><span style="color:gray;">, </span><span style="color:teal;">user_choice</span><span style="color:gray;">)
    </span><span style="color:blue;">SELECT </span><span style="color:magenta;">NEWID</span><span style="color:gray;">(), </span><span style="color:teal;">user_choice </span><span style="color:blue;">FROM </span><span style="color:teal;">inserted</span><span style="color:gray;">;
  </span><span style="color:blue;">END TRY
  BEGIN CATCH
    SELECT  </span><span style="color:magenta;">ERROR_NUMBER</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorNumber
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_SEVERITY</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorSeverity
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_STATE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorState
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_PROCEDURE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorProcedure
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_LINE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorLine
          </span><span style="color:gray;">, </span><span style="color:magenta;">ERROR_MESSAGE</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">ErrorMessage</span><span style="color:gray;">;
  </span><span style="color:blue;">END CATCH
END
GO
ADD SIGNATURE to </span><span style="color:teal;">dbo</span><span style="color:gray;">.</span><span style="color:teal;">trg_tally
</span><span style="color:blue;">BY CERTIFICATE </span><span style="color:teal;">SigCert
</span><span style="color:blue;">WITH PASSWORD </span><span style="color:gray;">= </span><span style="color:red;">'$(SIGNATURE_PASSWORD)'</span><span style="color:gray;">;
</span><span style="color:blue;">GO
CREATE TRIGGER </span><span style="color:teal;">trg_ddlChanges1
</span><span style="color:blue;">ON DATABASE
WITH ENCRYPTION
FOR </span><span style="color:teal;">DDL_DATABASE_LEVEL_EVENTS
</span><span style="color:blue;">AS
BEGIN
DECLARE </span><span style="color:teal;">@User </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>128<span style="color:gray;">);
  </span><span style="color:blue;">BEGIN TRY
    SET </span><span style="color:teal;">@User </span><span style="color:gray;">= </span><span style="color:magenta;">USER_NAME</span><span style="color:gray;">();
    </span><span style="color:green;">-- error if user making the change is not DataAdministrator
    -- even though IS_MEMBER('DataAdministrator') would be false
    </span><span style="color:blue;">IF </span><span style="color:gray;">NOT EXISTS
      ( </span><span style="color:blue;">SELECT </span><span style="color:gray;">*
        </span><span style="color:blue;">FROM </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:teal;">ddl</span><span style="color:gray;">.</span><span style="color:blue;">event</span><span style="color:gray;">.</span><span style="color:teal;">value</span><span style="color:gray;">(</span><span style="color:red;">'LoginName[1]'
                                 </span><span style="color:gray;">, </span><span style="color:red;">'NVARCHAR(128)'</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:teal;">LoginName
              </span><span style="color:blue;">FROM
                </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">EVENTDATA</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">change</span><span style="color:gray;">) </span><span style="color:teal;">this
              </span><span style="color:gray;">CROSS APPLY
                </span><span style="color:teal;">change</span><span style="color:gray;">.</span><span style="color:teal;">nodes</span><span style="color:gray;">(</span><span style="color:red;">'/EVENT_INSTANCE'</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:teal;">ddl</span><span style="color:gray;">(</span><span style="color:blue;">event</span><span style="color:gray;">) ) </span><span style="color:teal;">q
        </span><span style="color:gray;">JOIN </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">database_role_members </span><span style="color:teal;">r
        </span><span style="color:blue;">ON </span><span style="color:teal;">q</span><span style="color:gray;">.</span><span style="color:teal;">LoginName </span><span style="color:gray;">= </span><span style="color:magenta;">USER_NAME</span><span style="color:gray;">(</span><span style="color:teal;">r</span><span style="color:gray;">.</span><span style="color:teal;">member_principal_id</span><span style="color:gray;">)
        </span><span style="color:blue;">WHERE </span><span style="color:teal;">r</span><span style="color:gray;">.</span><span style="color:teal;">role_principal_id </span><span style="color:gray;">= </span><span style="color:magenta;">USER_ID</span><span style="color:gray;">(</span><span style="color:red;">'DataAdministrator'</span><span style="color:gray;">) )
    AND </span><span style="color:teal;">@User </span><span style="color:gray;">&lt;&gt; </span><span style="color:red;">'cdc'
      </span><span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'Invalid User %s'</span><span style="color:gray;">,</span>16<span style="color:gray;">,</span>1<span style="color:gray;">,</span><span style="color:teal;">@User</span><span style="color:gray;">) </span><span style="color:blue;">WITH </span><span style="color:magenta;">LOG</span><span style="color:gray;">;
  </span><span style="color:blue;">END TRY
  BEGIN CATCH
    ROLLBACK</span><span style="color:gray;">;
    </span><span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'fatal error'</span><span style="color:gray;">,</span>20<span style="color:gray;">,</span>1<span style="color:gray;">, </span><span style="color:teal;">@User</span><span style="color:gray;">) </span><span style="color:blue;">WITH </span><span style="color:magenta;">LOG</span><span style="color:gray;">;
  </span><span style="color:blue;">END CATCH
END
GO
DISABLE TRIGGER </span><span style="color:gray;">ALL </span><span style="color:blue;">ON DATABASE
GO
CREATE TRIGGER </span><span style="color:teal;">trg_ddlChanges2
</span><span style="color:blue;">ON DATABASE
WITH ENCRYPTION
FOR </span><span style="color:teal;">DDL_DATABASE_LEVEL_EVENTS
</span><span style="color:blue;">AS
BEGIN
DECLARE </span><span style="color:teal;">@User </span><span style="color:blue;">NVARCHAR</span><span style="color:gray;">(</span>128<span style="color:gray;">);
  </span><span style="color:blue;">BEGIN TRY
    SET </span><span style="color:teal;">@User </span><span style="color:gray;">= </span><span style="color:magenta;">USER_NAME</span><span style="color:gray;">();
    </span><span style="color:green;">-- error if user making the change is not DataAdministrator
    -- even though IS_MEMBER('DataAdministrator') would be false
    </span><span style="color:blue;">IF </span><span style="color:gray;">NOT EXISTS
      ( </span><span style="color:blue;">SELECT </span><span style="color:gray;">*
        </span><span style="color:blue;">FROM </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:teal;">ddl</span><span style="color:gray;">.</span><span style="color:blue;">event</span><span style="color:gray;">.</span><span style="color:teal;">value</span><span style="color:gray;">(</span><span style="color:red;">'LoginName[1]'
                                 </span><span style="color:gray;">, </span><span style="color:red;">'NVARCHAR(128)'</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:teal;">LoginName
              </span><span style="color:blue;">FROM
                </span><span style="color:gray;">(</span><span style="color:blue;">SELECT </span><span style="color:magenta;">EVENTDATA</span><span style="color:gray;">() </span><span style="color:blue;">AS </span><span style="color:teal;">change</span><span style="color:gray;">) </span><span style="color:teal;">this
              </span><span style="color:gray;">CROSS APPLY
                </span><span style="color:teal;">change</span><span style="color:gray;">.</span><span style="color:teal;">nodes</span><span style="color:gray;">(</span><span style="color:red;">'/EVENT_INSTANCE'</span><span style="color:gray;">) </span><span style="color:blue;">AS </span><span style="color:teal;">ddl</span><span style="color:gray;">(</span><span style="color:blue;">event</span><span style="color:gray;">) ) </span><span style="color:teal;">q
        </span><span style="color:gray;">JOIN </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">database_role_members </span><span style="color:teal;">r
        </span><span style="color:blue;">ON </span><span style="color:teal;">q</span><span style="color:gray;">.</span><span style="color:teal;">LoginName </span><span style="color:gray;">= </span><span style="color:magenta;">USER_NAME</span><span style="color:gray;">(</span><span style="color:teal;">r</span><span style="color:gray;">.</span><span style="color:teal;">member_principal_id</span><span style="color:gray;">)
        </span><span style="color:blue;">WHERE </span><span style="color:teal;">r</span><span style="color:gray;">.</span><span style="color:teal;">role_principal_id </span><span style="color:gray;">= </span><span style="color:magenta;">USER_ID</span><span style="color:gray;">(</span><span style="color:red;">'DataAdministrator'</span><span style="color:gray;">) )
    AND </span><span style="color:teal;">@User </span><span style="color:gray;">&lt;&gt; </span><span style="color:red;">'cdc'
      </span><span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'Invalid User %s'</span><span style="color:gray;">,</span>16<span style="color:gray;">,</span>1<span style="color:gray;">,</span><span style="color:teal;">@User</span><span style="color:gray;">) </span><span style="color:blue;">WITH </span><span style="color:magenta;">LOG</span><span style="color:gray;">;
  </span><span style="color:blue;">END TRY
  BEGIN CATCH
    ROLLBACK</span><span style="color:gray;">;
    </span><span style="color:blue;">RAISERROR</span><span style="color:gray;">(</span><span style="color:red;">'fatal error'</span><span style="color:gray;">,</span>20<span style="color:gray;">,</span>1<span style="color:gray;">, </span><span style="color:teal;">@User</span><span style="color:gray;">) </span><span style="color:blue;">WITH </span><span style="color:magenta;">LOG</span><span style="color:gray;">;
  </span><span style="color:blue;">END CATCH
END
GO
GO
ENABLE TRIGGER </span><span style="color:gray;">ALL </span><span style="color:blue;">ON DATABASE
GO
SELECT </span><span style="color:teal;">O</span><span style="color:gray;">.</span><span style="color:teal;">NAME
     </span><span style="color:gray;">, </span><span style="color:magenta;">ISNULL</span><span style="color:gray;">(</span><span style="color:magenta;">IS_OBJECTSIGNED</span><span style="color:gray;">( </span><span style="color:red;">'OBJECT'
                             </span><span style="color:gray;">, </span><span style="color:teal;">o</span><span style="color:gray;">.</span><span style="color:magenta;">object_id
                             </span><span style="color:gray;">, </span><span style="color:red;">'CERTIFICATE'
                             </span><span style="color:gray;">, </span><span style="color:teal;">c</span><span style="color:gray;">.</span><span style="color:teal;">thumbprint </span><span style="color:gray;">), </span>0<span style="color:gray;">) </span><span style="color:blue;">as </span><span style="color:teal;">[IsSigned]
     </span><span style="color:gray;">, </span><span style="color:teal;">c</span><span style="color:gray;">.</span><span style="color:teal;">name
</span><span style="color:blue;">FROM </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">objects </span><span style="color:teal;">o
</span><span style="color:gray;">LEFT JOIN </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">crypt_properties </span><span style="color:teal;">cp
</span><span style="color:blue;">ON </span><span style="color:teal;">o</span><span style="color:gray;">.</span><span style="color:magenta;">object_id </span><span style="color:gray;">= </span><span style="color:teal;">cp</span><span style="color:gray;">.</span><span style="color:teal;">major_id
</span><span style="color:gray;">LEFT JOIN </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">triggers </span><span style="color:teal;">t
</span><span style="color:blue;">ON </span><span style="color:teal;">o</span><span style="color:gray;">.</span><span style="color:magenta;">object_id </span><span style="color:gray;">= </span><span style="color:teal;">t</span><span style="color:gray;">.</span><span style="color:magenta;">object_id
</span><span style="color:gray;">LEFT JOIN </span><span style="color:green;">sys</span><span style="color:gray;">.</span><span style="color:green;">certificates </span><span style="color:teal;">c
</span><span style="color:blue;">on </span><span style="color:teal;">cp</span><span style="color:gray;">.</span><span style="color:teal;">thumbprint </span><span style="color:gray;">= </span><span style="color:teal;">cp</span><span style="color:gray;">.</span><span style="color:teal;">thumbprint
</span><span style="color:blue;">WHERE </span><span style="color:teal;">o</span><span style="color:gray;">.</span><span style="color:teal;">is_ms_shipped </span><span style="color:gray;">= </span>0
<span style="color:blue;">GO

</span></pre>
<p>&nbsp;</p>
<p>The best prevention for unauthorized <em>sysadmin</em> level access to the database is to keep anyone and anything that should not be doing admin level work from connecting with admin level credentials. Limiting the number of <em>sysadmins</em> is also nice, but the reality is pretty much anyone that can set another users password or access the local system running SQL Server as a local Windows Administrator can find a way to connect to a SQL Server with <em>sysadmin</em> access. Once a connection to a SQL Server is established using valid credentials, there are no permissions, privileges, rights or roles that cannot be overridden by that sysadmin empowered connection. At this time only the <em>protection from compromise</em> of sensitive data by unauthorized <em>sysadmin</em> members looks possible. Any <em>sysadmin</em> can delete complete data rows, drop tables and even drop databases or corrupt the data: no matter what is done to prevent data compromise. It is only possible to prevent the <em>sysadmin</em> from knowing the meaning of encrypted data. A mildly determined malicious user with <em>sysadmin</em> authority and the intent to destroy data cannot be stopped from that goal. They can be delayed and &#8211; in most cases &#8211; identified after the fact. Delaying features are also useful to help show intent during Forensic . The best protections against the malicious insider are to hire trustworthy employees and&nbsp; to collect adequate forensic data into user protected containers. Ideally, an audit trail that cannot be modified by a sysadmin privileged user is needed.</p>
<p>The information protection of encryption/signing is durable provided the private key is safe. Encryption scrambles data with a public key that can later be unscrambled with a private key. In contrast, signing scrambles data with the private key of a key pair and later unscrambles the signature with the public key to verify the data. In either case, the encryption keys &#8211; especially the private key &#8211; must be&nbsp; safeguarded. </p>
<p>The simple act of successfully sharing a well protected key to sign and verify a signature is often considered adequate to establish non-repudiation. A weakness in this approach is the ease with which T-SQL can be manipulated without violating the signature. It is also necessary to verify that all other relevant schema elements continue to sport their signatures, that unsigned objects have not been introduces, and that none of the expected signed objects are missing. </p>
<p>A digital object that is expected to check its own signature is fatally flawed. This would be like airport security using the &#8216;honor system&#8217; or nuclear power regulators deferring to the plant operators to establish safety levels or airline pilots left to judge their own soberness before flight.&nbsp; <em>A</em>s we now know &#8211; self-policing strategies are effective in well over 99% of cases. And very cost effective&#8230; until there is an event that falls into the range of that other way less than 1 percent. A significantly more reliable and consistent outcome results when the signature is always verified by a trusty outsider. (Ultimately this is the reason that outside accounting firms are needed to count the votes in an awards show, there are observers at ballot locations, &#8220;fact checking&#8221; has become a political pastime and neighbors are nosey: simply to bear witness to the obvious and expose &#8211; or get mysteriously wealthy &#8211; over occasional anomalies.)&nbsp; </p>
<p><em>A higher assurance that any entity is what it claims it is is will come from a reliable source external and independent from that entity than from that entity itself. </em>This is why auditors are in great demand and the words &#8220;Fact Checking&#8221; garner such attention in the title of an article or news story.&#8221;<em>&nbsp;</em>This external check could be done &#8211; in our scenario &#8211; by: </p>
<ol>
<li>introducing a trigger behind the table
<li>via a called module &#8211; a stored procedure &#8211; placed between the external request and the table operation
<li>as a check constraint or default value. </li>
</ol>
<p>Also, to be able to claim the current process as the scope for verification of trust, the validity of each called module and referenced object needs to be verified before use and the signature of each calling module ought to be verified by the caller before returning control. That leaves defaults and constraints less useful since they may not occur with every process that uses the data.&nbsp;&nbsp; </p>
<p>A called stored procedure or a trigger will do. A view cannot be signed.&nbsp; It may be a little less confounding for the developer not to have to create two stored procedures to do one thing.&nbsp; Using a trigger also allows a division of responsibility and prevents everyone from having to know every business rule to succeed. Perhaps the DBA takes ownership of the triggers or called procedure(s) that verify authenticity of the participants allowing the developers to continue to code<em> mostly</em> unaffected by and unaware of the signature trigger logic and other defensive layers enveloping the application logic. All in all, a trigger is probably a better way to impose corroboration than the addition of a second stored procedure IMHO, but not by much. One of the few scenarios when triggers are in fact appropriate: to assure the encryption complexity does not get in the way of progress!&nbsp; On the other hand, if the database supports abstraction layers (ORM, OOP)&nbsp; that will suffer serious side effects or degradation from a trigger an additional stored procedure or view introduced into this now obviously secondary secure application is mandated to assure the authenticity of the communication. </p>
<p>If you are looking for this level of assurance of authenticity through your ORM &#8211; fagetaboutit. Man-in-the-middle protection at the ORM data access layer is essential but must be done well outside the bounds of the data layer. You still want to do everything described to protect and monitor at the database server. In addition, it is necessary to apply similar protection at the ORM layer.&nbsp; </p>
<p>FWIW: the original hack, tacking on an instead trigger no longer works due to the one instead trigger per action limitation. The legitimate trigger uses up the one allowed trigger on all three actions. </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/264/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/264/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/264/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=264&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/10/05/using-authenticity-signing-nesting-in-t-sql-to-protect-sensitive-data-from-even-highly-privileged-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>Encryption Hierarchy Administration &#8211; a T-SQL Template</title>
		<link>http://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/</link>
		<comments>http://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/#comments</comments>
		<pubDate>Fri, 01 Jul 2011 16:28:41 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[ADD SIGNATURE]]></category>
		<category><![CDATA[ALTER MASTER KEY]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[BACKUP CERTIFICATE]]></category>
		<category><![CDATA[BACKUP MASTER KEY]]></category>
		<category><![CDATA[EVENT NOTIFICATIONS]]></category>
		<category><![CDATA[HASHBYTES()]]></category>
		<category><![CDATA[IS_OBJECTSIGNED()]]></category>
		<category><![CDATA[RESTORE MASTER KEY]]></category>
		<category><![CDATA[Restoring a certificate or key from backup]]></category>
		<category><![CDATA[SQLCMD Mode]]></category>
		<category><![CDATA[SSMS templates]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/</guid>
		<description><![CDATA[This is a SQL Server template to standardize and track backup and&#160; restore of SQL Server 2005/2008 Encryption Hierarchy (EH) Master Keys and Certificates. Unlike most templates, this one creates a complete utility with several interdependent database objects &#8211; including &#8230; <a href="http://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=234&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a SQL Server template to standardize and track backup and&nbsp; restore of SQL Server 2005/2008 Encryption Hierarchy (EH) Master Keys and Certificates. Unlike most templates, this one creates a complete utility with several interdependent database objects &#8211; including the database if it does not already exist. Any existing user database can be used as long as the consequences of executing a script from this template are understood and acceptable.</p>
<blockquote><p>January 25, 2012 Update &#8211; A nicely hardened version of the Encryption Hierarchy Administrator is now available. I would still strongly recommend that you become familiar with the technologies demonstrated in the script posted here if you do not already administer an encryption hierarchy. This script demonstrates the fundamentals required for sound EH administration. The new version adds extensive cryptographic support that will be documented through a few blog posts. </p>
<p><a href="https://github.com/bwunder/EHAdmin">https://github.com/bwunder/EHAdmin</a>.</p>
<p>and now back to our regularly scheduled program&#8230;</p>
</blockquote>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:1703a5d6-8f9d-4283-893b-7064a32927b2" class="wlWriterSmartContent">
<div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:verdana, tahoma, arial, sans-serif;background:#000080;color:#fff;font-size:10pt;border-top:#000080 1px solid;font-weight:bold;border-right:#000080 1px solid;padding:2px 5px;">keyback Administrator.sql</div>
<div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:'Courier New', courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;">
<div style="background:#ddd;max-height:300px;overflow:auto;">
<ol style="white-space:nowrap;background:#ffffff;margin:0 0 0 4em;padding:0 0 0 5px;">
<li><span style="color:#008000;">&#8211; Encryption Hierarchy Administration Template</span>
<li><span style="color:#008000;">&#8211; WARNING! script changes master database and creates a database if it does not already exist&nbsp; </span>
<li><span style="color:#008000;">&#8211; run in SSMS SQLCMD mode or from a sqlcmd command line </span>
<li><span style="color:#008000;">&#8211; best practice is to use SSMS and NEVER save the script once the secrets have been entered. </span>
<li><span style="color:#008000;">&#8211; PASSPHRASE cannot contain any of these symbols or substrings # , . ; : _&nbsp; &#8221; &#8216;</span>
<li><span style="color:#008000;">&#8211; or the words GO DROP CREATE ALTER SELECT INSERT UPDATE DELETE GRANT DBO EXEC USE (regardless of case) </span>
<li><span style="background:#c0c0c0;">:setvar DB_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Db to create or use if exists,SYSNAME,keyback&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar SMK_BACKUP_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for Service Master Key backup file encryption,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221; </span>
<li><span style="color:#008000;">&#8211; if master already has a DMK you must provide the existing encryption passphrase &#8211; don&#8217;t make one up &#8211; it will corrupt keyback</span>
<li><span style="background:#c0c0c0;">:setvar master_DMK_ENCRYPTION_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for master Database Master Key encryption,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar master_DMK_BACKUP_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for master Database Master Key backup file,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar keyback_DMK_ENCRYPTION_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for keyback Database Master Key encryption,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar keyback_DMK_BACKUP_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for keyback Database Master Key backup file,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar TDE_CERTIFICATE_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Name of cert in master for keyback db TDE Encryption Key ,SYSNAME,TDECertificate&gt;&#8221; </span>
<li><span style="background:#c0c0c0;">:setvar TDE_CERTIFICATE_BACKUP_PHRASE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for master db TDE Cert backup file encryption,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221; </span>
<li><span style="background:#c0c0c0;">:setvar VALUE_CERTIFICATE_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Name of cert in keyback db used to encrypt column values,SYSNAME,ValueCertificate&gt;&#8221;</span>
<li><span style="background:#c0c0c0;">:setvar VALUE_CERTIFICATE_ENCRYPTION_PHRASE &#8220;&lt;Secret for keyback db value certificate encryption,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar VALUE_CERTIFICATE_BACKUP_PHRASE&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Secret for keyback db value certificate backup file,PASSPHRASE &#8211; NVARCHAR(128),&gt;&#8221;&nbsp; </span>
<li><span style="color:#008000;">&#8211; http://blogs.msdn.com/b/ace_team/archive/2007/09/07/aes-vs-3des-block-ciphers.aspx : use AES</span>
<li><span style="background:#c0c0c0;">:setvar DEK_ALGORITHM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Database Encryption Key Algorithm,AES_128 | AES_192 | AES_256 | TRIPLE_DES_3KEY,AES_256&gt;&#8221;</span>
<li><span style="background:#c0c0c0;">:setvar COLUMN_ENCRYPTION_ALGORITHM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Symmetric Key Algorithm,AES_128 | AES_192 | AES_256 | TRIPLE_DES_3KEY | Other (most already broken), AES_256&gt;&#8221;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar DB_SYMMETRIC_KEY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Symmetric key used for data value encryption,SYSNAME,ValueKey&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar ROLE_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;Role -membership required to access NameValues,SYSNAME,keybackAdmin&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar MASTER_KEY_BACKUP_EXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;file extension for key backups,FILE_EXTENSION,.keybak&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar PUBLIC_KEY_BACKUP_EXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;file extension for certificate backups,FILE_EXTENTION,.cerbak&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar PRIVATE_KEY_BACKUP_EXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;file extension for certificate private key backups,FILE_EXT,.prvbak&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="background:#c0c0c0;">:setvar SPARSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&lt;SPARSE XML error columns if 2008 otherwise blank,SPARSE | blank,SPARSE&gt;&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
<li><span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Protect all Encryption Hierarchy backup files and maintain a copy in a secure offsite location.&#8217;</span><span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>0<span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">USE</span> [master]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;$(DB_NAME)&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">USE</span> $<span style="color:#808080;">(</span><span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">&lt;&gt;</span> <span style="color:#ff0000;">&#8216;$(DB_NAME)&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Database $(DB_NAME) not found. Script aborted.&#8217;</span><span style="color:#808080;">,</span>20<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span> <span style="color:#0000ff;">WITH</span> <span style="color:#ff00ff;">LOG</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">ALTER</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)] <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">TRUSTWORTHY</span> <span style="color:#0000ff;">OFF</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">ALTER</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)] <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">DB_CHAINING</span> <span style="color:#0000ff;">OFF</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">ALTER</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)] <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">RECOVERY</span> <span style="color:#0000ff;">FULL</span><span style="color:#808080;">;</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">ALTER</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)] <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">READ_COMMITTED_SNAPSHOT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211; db_owner, dbcreator, sysadmin.</span>
<li><span style="color:#0000ff;">ALTER</span> <span style="color:#0000ff;">DATABASE</span> [$(DB_NAME)] <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">RESTRICTED_USER</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">USE</span> [master]<span style="color:#808080;">;</span>
<li><span style="color:#008000;">&#8211; encryption hierarchy backups</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483631<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback info &#8211; database %s certificate %s %s complete.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483632<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback error &#8211; database %s certificate %s %s failed with return_code %d.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483633<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback info &#8211; database %s Master Key %s complete.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483634<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback error &#8211; database %s Master Key %s failed with return_code %d.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483635<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback info &#8211; Service Master Key backup complete.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483636<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;keyback error &#8211; Service Master Key backup failed with return_code %d.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#008000;">&#8211; encrypted name value secrets</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483641<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;namevalue info &#8211; %s complete.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483642<span style="color:#808080;">,</span> 16<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;namevalue error &#8211; %s failed with @return_code = %d.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483643<span style="color:#808080;">,</span> 16<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;namevalue error &#8211; Unable to verify save of secret &#8220;%s&#8221;.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483644<span style="color:#808080;">,</span> 16<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;namevalue error &#8211; Invalid &#8220;%s&#8221;.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_addmessage</span><span style="color:#0000ff;"> </span>2147483645<span style="color:#808080;">,</span>&nbsp; 1<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;namevalue info &#8211; the %s is valid.&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;us_english&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;FALSE&#8217;</span> <span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;replace&#8217;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211; Certificate in master for TDE is encrypted by master Database Master Key </span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> [sys]<span style="color:#808080;">.</span>[symmetric_keys] <span style="color:#0000ff;">WHERE</span> [symmetric_key_id] <span style="color:#808080;">=</span> 101<span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">MASTER</span> <span style="color:#0000ff;">KEY</span> <span style="color:#0000ff;">ENCRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(master_DMK_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211;&nbsp; private key of cert is autogenerated and encrypted by DMK </span>
<li><span style="color:#008000;">&#8211; if no private key specified and no Master Key exists this create will fail</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">certificates</span> <span style="color:#0000ff;">WHERE</span> [name] <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(TDE_CERTIFICATE_NAME)&#8217;</span><span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">CERTIFICATE</span> $<span style="color:#808080;">(</span>TDE_CERTIFICATE_NAME<span style="color:#808080;">)</span> <span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">SUBJECT</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(DB_NAME)_DatabaseEncryptionKey&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">USE</span> $<span style="color:#808080;">(</span><span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">);</span>
<li><span style="color:#008000;">&#8211; move dbo to sa so no conflicts when current user added to role</span>
<li><span style="color:#008000;">&#8211; sa should also be disabled, and could also be renamed </span>
<li><span style="color:#008000;">&#8211; SQL authentication should also be disabled.</span>
<li><span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> owner_sid <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">databases</span> <span style="color:#0000ff;">where</span> name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">())</span> <span style="color:#808080;">&lt;&gt;</span> 0&#215;01
<li><span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_changedbowner</span><span style="color:#0000ff;"> </span><span style="color:#ff0000;">&#8216;sa&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">database_principals</span> <span style="color:#0000ff;">WHERE</span> name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">())</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">DECLARE</span> @CreateUserDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @CreateUserDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;CREATE USER ['</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">'] FROM LOGIN ['</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">'];&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@CreateUserDDL<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">database_principals</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(ROLE_NAME)&#8217;</span><span style="color:#808080;">)</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">DECLARE</span> @CreateRoleDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @CreateRoleDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;CREATE ROLE $(ROLE_NAME) AUTHORIZATION ['</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">'];&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@CreateRoleDDL<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">IS_MEMBER</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;$(ROLE_NAME)&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">&lt;&gt;</span> 1
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">DECLARE</span> @AddToRoleDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @AddToRoleDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;EXEC sp_addrolemember &#8221;$(ROLE_NAME)&#8221;,['</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">']&#8216;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@AddToRoleDDL<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211; sys.dm_database_encryption_keys unknown to 2005 and lesser 2008 SKUs &#8211; if true will skip this</span>
<li><span style="color:#008000;">&#8211; has to spexecuted to avoid failed parse in 2005.</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">PARSENAME</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span> <span style="color:#ff00ff;">CONVERT</span><span style="color:#808080;">(</span><span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">),</span> <span style="color:#ff00ff;">SERVERPROPERTY</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;ProductVersion&#8217;</span><span style="color:#808080;">))</span> <span style="color:#808080;">,</span> 4 <span style="color:#808080;">),</span> 0<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 9
<li><span style="color:#808080;">AND</span> <span style="color:#ff00ff;">SERVERPROPERTY</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Edition&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IN</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Developer Edition&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;Enterprise Edition&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;Enterprise Evaluation Edition&#8217;</span><span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">dm_database_encryption_keys</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> [database_id] <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">()</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(DB_NAME)&#8217;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span><span style="color:#ff0000;">N&#8217;CREATE DATABASE ENCRYPTION KEY</span>
<li><span style="color:#ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WITH ALGORITHM = $(DEK_ALGORITHM)</span>
<li><span style="color:#ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ENCRYPTION BY SERVER CERTIFICATE [$(TDE_CERTIFICATE_NAME)];</span>
<li><span style="color:#ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALTER DATABASE $(DB_NAME)</span>
<li><span style="color:#ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET ENCRYPTION ON;&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> [sys]<span style="color:#808080;">.</span>[symmetric_keys]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> [symmetric_key_id] <span style="color:#808080;">=</span> 101<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">MASTER</span> <span style="color:#0000ff;">KEY</span> <span style="color:#0000ff;">ENCRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(keyback_DMK_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211; certs need not have a password, most probably should not. here password is better because</span>
<li><span style="color:#008000;">&#8211; malicious hackers are prevented from accessing the secrets in an elevation of authority attack&nbsp; </span>
<li><span style="color:#008000;">&#8211; only those able to view the secret can open the key required to view the secrets&nbsp; </span>
<li><span style="color:#008000;">&#8211; the password will be encrypted in the necessary stored procedures so will be required</span>
<li><span style="color:#008000;">&#8211; only when opening the symmetric in ad hoc query</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> [sys]<span style="color:#808080;">.</span>[certificates] <span style="color:#0000ff;">WHERE</span> [name] <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_NAME)&#8217;</span><span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">CERTIFICATE</span> [$(VALUE_CERTIFICATE_NAME)]
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ENCRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">SUBJECT</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;NameValue Column Encryption&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> [sys]<span style="color:#808080;">.</span>[symmetric_keys]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> [name] <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(DB_SYMMETRIC_KEY)&#8217;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">ALGORITHM</span> <span style="color:#808080;">=</span> $<span style="color:#808080;">(</span>COLUMN_ENCRYPTION_ALGORITHM<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ENCRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">CERTIFICATE</span> [$(VALUE_CERTIFICATE_NAME)]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.NameValues&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TABLE</span> [dbo]<span style="color:#808080;">.</span>[NameValues]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">(</span> [Name] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Version] <span style="color:#0000ff;">INT</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> dft_NameValues__Version
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Value] [VARBINARY]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>256<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CreateDT [DATETIME] <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> dft_NameValues__CreateDT
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CreateUser [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> dft_NameValues__CreateUser
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">())</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">CONSTRAINT</span> pk_NameValues__Name__Version
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">PRIMARY</span> <span style="color:#0000ff;">KEY </span><span style="color:#808080;">(</span>[Name]<span style="color:#808080;">,</span> [Version]<span style="color:#808080;">));</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.itrg_NameValues&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">TRIGGER</span> dbo<span style="color:#808080;">.</span>itrg_NameValues
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TRIGGER</span> dbo<span style="color:#808080;">.</span>itrg_NameValues
<li><span style="color:#0000ff;">ON</span>&nbsp; dbo<span style="color:#808080;">.</span>NameValues
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">INSTEAD</span> <span style="color:#0000ff;">OF</span> <span style="color:#0000ff;">UPDATE</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">DELETE</span>
<li>&nbsp; <span style="color:#0000ff;">AS</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> inserted<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> d<span style="color:#808080;">.</span>Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> d<span style="color:#808080;">.</span><span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;UPDATE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;NO-OP&#8217;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> deleted d<span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> d<span style="color:#808080;">.</span>Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> d<span style="color:#808080;">.</span><span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;DELETE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;NO-OP&#8217;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> deleted d<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.NameValueHistory&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TABLE</span> [dbo]<span style="color:#808080;">.</span>[NameValueHistory]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">(</span> [Id] <span style="color:#0000ff;">INT</span> <span style="color:#0000ff;">IDENTITY</span><span style="color:#808080;">(</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Name] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span> <span style="color:#008000;">&#8211; implicit FK</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Version] <span style="color:#0000ff;">INT</span> <span style="color:#808080;">NULL</span> <span style="color:#008000;">&#8211; if add fails there may be no version to insert </span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Action] [VARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>30<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Status] [VARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>30<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [ck_NameValueHistory__Status]
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CHECK </span><span style="color:#808080;">(</span><span style="color:#0000ff;">Status</span> <span style="color:#808080;">IN</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;NO-OP&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Valid&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Invalid&#8217;</span><span style="color:#808080;">))</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [ErrorData] [XML] $<span style="color:#808080;">(</span>SPARSE<span style="color:#808080;">)</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateDT] [DATETIME] <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_NameValueHistory__CreateDT]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateUser] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_NameValueHistory__CreateUser]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">())</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">CONSTRAINT</span> [pk_NameValueHistory__Id]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">PRIMARY</span> <span style="color:#0000ff;">KEY </span><span style="color:#808080;">(</span>[Id]<span style="color:#808080;">));</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.itrg_NameValueHistory&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">TRIGGER</span> dbo<span style="color:#808080;">.</span>itrg_NameValueHistory
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TRIGGER</span> dbo<span style="color:#808080;">.</span>itrg_NameValueHistory
<li><span style="color:#0000ff;">ON</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">INSTEAD</span> <span style="color:#0000ff;">OF</span> <span style="color:#0000ff;">UPDATE</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">DELETE</span>
<li>&nbsp; <span style="color:#0000ff;">AS</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">FROM</span> inserted<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> d<span style="color:#808080;">.</span>Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> d<span style="color:#808080;">.</span><span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;UPDATE of Id &#8216;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">CAST</span><span style="color:#808080;">(</span>Id <span style="color:#0000ff;">as</span> <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>10<span style="color:#808080;">))</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;NO-OP&#8217;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> deleted d
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> d<span style="color:#808080;">.</span>Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> d<span style="color:#808080;">.</span><span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;DELETE of Id &#8216;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">CAST</span><span style="color:#808080;">(</span>Id <span style="color:#0000ff;">as</span> <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>10<span style="color:#808080;">))</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;NO-OP&#8217;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> deleted d
<li>&nbsp; <span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.MasterKeyBackupHistory&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TABLE</span> [dbo]<span style="color:#808080;">.</span>[MasterKeyBackupHistory]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">(</span> [Id] <span style="color:#0000ff;">INT</span> <span style="color:#0000ff;">IDENTITY</span><span style="color:#808080;">(</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [ServerName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_MasterKeyBackupHistory__ServerName]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@SERVERNAME</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [DbName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [KeyName] [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [BackupName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [BackupPath] [NVARCHAR]<span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Action] [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Status] [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>30<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [ck_MasterKeyBackupHistory__Status]
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CHECK </span><span style="color:#808080;">(</span><span style="color:#0000ff;">Status</span> <span style="color:#808080;">IN</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span><span style="color:#808080;">))</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [ErrorData] [XML] $<span style="color:#808080;">(</span>SPARSE<span style="color:#808080;">)</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateDT] [DATETIME] <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_MasterKeyBackupHistory__CreateDT]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateUser] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_MasterKeyBackupHistory__CreateUser]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">())</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">CONSTRAINT</span> [pk_MasterKeyBackupHistory__Id]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">PRIMARY</span> <span style="color:#0000ff;">KEY </span><span style="color:#808080;">(</span>[Id]<span style="color:#808080;">));</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.CertificateBackupHistory&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">TABLE</span> [dbo]<span style="color:#808080;">.</span>[CertificateBackupHistory]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;"></span><span style="color:#808080;">(</span> [Id] <span style="color:#0000ff;">INT</span> <span style="color:#0000ff;">IDENTITY</span><span style="color:#808080;">(</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [ServerName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_CertificateBackupHistory__ServerName]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@SERVERNAME</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [DbName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CertificateName] [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [BackupName] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [BackupPath] [NVARCHAR]<span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Action] [VARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>30<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [Status] [VARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>30<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [ck_CertificateBackupHistory__Status]
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CHECK </span><span style="color:#808080;">(</span><span style="color:#0000ff;">Status</span> <span style="color:#808080;">IN</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span><span style="color:#808080;">))</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> [Thumbprint] [VARBINARY]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>32<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> [PrivateKeyEncryptionType] [CHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>2<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [ck_CertificateBackupHistory__PrivateKeyEncryptionType]
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CHECK </span><span style="color:#808080;">(</span>PrivateKeyEncryptionType <span style="color:#808080;">IN</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;NA&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;MK&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;SK&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;PW&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">))</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [ErrorData] [XML] $<span style="color:#808080;">(</span>SPARSE<span style="color:#808080;">)</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateDT] [DATETIME] <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_CertificateBackupHistory__CreateDT]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> [CreateUser] [NVARCHAR]<span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">CONSTRAINT</span> [dft_CertificateBackupHistory__CreateUser]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DEFAULT </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">())</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">CONSTRAINT</span> [pk_CertificateBackupHistory__Id]
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">PRIMARY</span> <span style="color:#0000ff;">KEY </span><span style="color:#808080;">(</span>[Id]<span style="color:#808080;">));</span>
<li>&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">NONCLUSTERED</span> <span style="color:#0000ff;">INDEX</span> ixn_CertificateBackupHistory__ServerName__DbName__CertificateName
<li>&nbsp; <span style="color:#0000ff;">ON</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory<span style="color:#808080;">(</span>ServerName<span style="color:#808080;">,</span> DbName<span style="color:#808080;">,</span> CertificateName<span style="color:#808080;">)</span> INCLUDE<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">Action</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">NONCLUSTERED</span> <span style="color:#0000ff;">INDEX</span> ixn_CertificateBackupHistory__Thumbprint
<li>&nbsp; <span style="color:#0000ff;">ON</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory<span style="color:#808080;">(</span>Thumbprint<span style="color:#808080;">)</span> INCLUDE<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">Action</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.CheckFile&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>CheckFile
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: make sure nothing flakey about a file name </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>CheckFile
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Name <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">BIT</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">DECLARE</span> @Result <span style="color:#0000ff;">BIT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">UPPER</span><span style="color:#808080;">(</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#008000;">&#8211; SQL Injection prevention</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[#,.;:"'''</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%--%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%*/%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%/*%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%DROP%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%CREATE%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%SELECT%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%INSERT%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%UPDATE%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%DELETE%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%GRANT%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%ALTER%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%AUX%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%CLOCK$%'</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">'%COM[1-8]%&#8217;</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%CON%&#8217;</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%LPT[1-8]%&#8217;</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%NUL%&#8217;</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%PRN%&#8217;</span><span style="color:#808080;">,</span> @Name<span style="color:#808080;">)</span> <span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 1<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 0<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span>@Result<span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.CheckPhrase&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>CheckPhrase
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: see if the unicode Password/Passphrase meets the policy </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>CheckPhrase
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Phrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">BIT</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @Result <span style="color:#0000ff;">BIT</span><span style="color:#808080;">;</span>
<li><span style="color:#008000;">&#8211; dft password policy as described in 2008R2 BOL + SQL Injection prevention</span>
<li><span style="color:#008000;">&#8211; a password can be generated as: SELECT CAST(newid() AS VARCHAR(128));</span>
<li><span style="color:#008000;">&#8211; sp_ and xp_ are covered by the match on underscore</span>
<li><span style="color:#008000;">&#8211; sp_ and xp_ are included by the match on underscore</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">LEN</span><span style="color:#808080;">(</span>@Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#008000;">&#8211; at leaset 8 characters </span>
<li><span style="color:#808080;">AND</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[#,.;:__"'']%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#008000;">&#8211; none of these symbols (added _ &#8216; &#8220;)</span>
<li><span style="color:#808080;">AND</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[A-Z]%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">THEN</span> 1 <span style="color:#0000ff;">ELSE</span> 0 <span style="color:#0000ff;">END</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#008000;">&#8211; at least 3 of 4</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[a-z]%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">THEN</span> 1 <span style="color:#0000ff;">ELSE</span> 0 <span style="color:#0000ff;">END</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#008000;">&#8211; uppercase, lowercase&nbsp; </span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[0-9]%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">THEN</span> 1 <span style="color:#0000ff;">ELSE</span> 0 <span style="color:#0000ff;">END</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#008000;">&#8211; numeric, symbol</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%[^A-Z,^a-z,^0-9]%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">THEN</span> 1 <span style="color:#0000ff;">ELSE</span> 0 <span style="color:#0000ff;">END</span><span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 2
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Phrase <span style="color:#808080;">=</span> <span style="color:#ff00ff;">UPPER</span><span style="color:#808080;">(</span>@Phrase<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%DROP%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%CREATE%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%SELECT%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%INSERT%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%UPDATE%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%DELETE%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%GRANT%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%ALTER%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%&#8211;%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%*/%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">PATINDEX</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;%/*%&#8217;</span><span style="color:#808080;">,</span> @Phrase<span style="color:#808080;">)</span> <span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 1<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 0<span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">END</span>&nbsp;&nbsp;&nbsp;
<li><span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span>@Result<span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.IsAuthorized&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>IsAuthorized
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: deterine if the user is authorize to use the system </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>IsAuthorized<span style="color:#808080;">()</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">BIT</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp; <span style="color:#0000ff;">DECLARE</span> @Result <span style="color:#0000ff;">BIT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#008000;">&#8211; sysadmins will always be dbo in the database</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">USER_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;dbo&#8217;</span>
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">ORIGINAL_LOGIN</span><span style="color:#808080;">()</span> <span style="color:#808080;">=</span> <span style="color:#ff00ff;">SUSER_SNAME</span><span style="color:#808080;">()</span> <span style="color:#008000;">&#8211; SYSTEM_USER</span>
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">IS_SRVROLEMEMBER</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;sysadmin&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 1
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">*</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">database_role_members</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> role_principal_id <span style="color:#808080;">=</span> <span style="color:#ff00ff;">USER_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;$(ROLE_NAME)&#8217;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">USER_NAME</span><span style="color:#808080;">(</span>member_principal_id<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> <span style="color:#ff00ff;">SUSER_SNAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">)</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 1<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Result <span style="color:#808080;">=</span> 0<span style="color:#808080;">;</span>&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span>@Result<span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.NewBackupPath&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewBackupPath
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: get the path where the backups will be stored</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; ASSERT: the backup is stored in same folder as the .mdf of the database</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no ACL changes are required, if the local backup copy is kept here</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the permissions could be locked down further&nbsp;&nbsp; </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewBackupPath<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>@DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">))</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#008000;">&#8211; backup to the .mdf&#8217;s folder,</span>
<li><span style="color:#008000;">&#8211;&nbsp; no ACL change is required &#8211; svc acct writes the files</span>
<li><span style="color:#008000;">&#8211;&nbsp; no dependency on specific local configurations to write file</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">LEFT(</span> physical_name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">LEN</span><span style="color:#808080;">(</span>physical_name<span style="color:#808080;">)</span> <span style="color:#808080;">-</span> <span style="color:#ff00ff;">CHARINDEX</span><span style="color:#808080;">(</span> <span style="color:#ff0000;">&#8216;\&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">REVERSE</span><span style="color:#808080;">(</span>physical_name<span style="color:#808080;">))</span> <span style="color:#808080;">+</span> 1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> <span style="color:#008000;">sys</span><span style="color:#808080;">.</span><span style="color:#008000;">master_files</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> database_id <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">file_id</span> <span style="color:#808080;">=</span> 1
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">type</span> <span style="color:#808080;">=</span> 0<span style="color:#808080;">);&nbsp;&nbsp;&nbsp; </span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.NewCertificateBackupName&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewCertificateBackupName
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: get the name of the file the certificate backup will use</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewCertificateBackupName<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>@DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">),</span> @CertificateName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">))</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@SERVERNAME</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;\&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;$&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__&#8217;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__&#8217;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CONVERT</span><span style="color:#808080;">(</span><span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>20<span style="color:#808080;">),</span> <span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">,</span> 20<span style="color:#808080;">),</span><span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">),</span><span style="color:#ff0000;">&#8216;__&#8217;</span><span style="color:#808080;">),</span><span style="color:#ff0000;">&#8216;:&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;-&#8217;</span><span style="color:#808080;">));&nbsp;&nbsp;&nbsp; </span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.NewMasterKeyBackupName&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewMasterKeyBackupName
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: get the name of the file a service master key backup </span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; or a database master key backup </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">FUNCTION</span> dbo<span style="color:#808080;">.</span>NewMasterKeyBackupName<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>@DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">))</span>
<li><span style="color:#0000ff;">RETURNS</span> <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RETURN </span><span style="color:#808080;">(</span><span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@SERVERNAME</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;\&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;$&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__&#8217;</span> <span style="color:#808080;">+</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> @DbName <span style="color:#808080;">is</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">THEN</span> <span style="color:#ff0000;">&#8216;Server__SMK&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__DMK&#8217;</span> <span style="color:#0000ff;">END</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;__&#8217;</span> <span style="color:#808080;">+</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">REPLACE</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">CONVERT</span><span style="color:#808080;">(</span><span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>20<span style="color:#808080;">),</span> <span style="color:#ff00ff;">CURRENT_TIMESTAMP</span><span style="color:#808080;">,</span> 20<span style="color:#808080;">),</span><span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">),</span><span style="color:#ff0000;">&#8216;__&#8217;</span><span style="color:#808080;">),</span><span style="color:#ff0000;">&#8216;:&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;-&#8217;</span><span style="color:#808080;">));&nbsp;&nbsp;&nbsp; </span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.AddNameValue&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;P&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> [dbo]<span style="color:#808080;">.</span>[AddNameValue]
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: encrypt sensitive data </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> [dbo]<span style="color:#808080;">.</span>[AddNameValue]
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Name [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @Value [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">DECLARE</span> @Version <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">DECLARE</span> @Err <span style="color:#0000ff;">XML</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">OPEN</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]
<li><span style="color:#0000ff;">DECRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">CERTIFICATE</span> [$(VALUE_CERTIFICATE_NAME)]
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>IsAuthorized<span style="color:#808080;">())</span> <span style="color:#808080;">=</span> 0
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;User&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#008000;">&#8211; password policy + SQL Injection prevention</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>CheckPhrase<span style="color:#808080;">(</span>@Value<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRANSACTION</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#008000;">&#8211; negative magnitude means attempt to insert existing value for name</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Version <span style="color:#808080;">=</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> <span style="color:#0000ff;">VERSION</span> <span style="color:#808080;">*</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> <span style="color:#ff00ff;">DecryptByKey</span><span style="color:#808080;">(</span>Value<span style="color:#808080;">,</span> 1<span style="color:#808080;">,</span> Name<span style="color:#808080;">)</span> <span style="color:#808080;">=</span>&nbsp; @Value <span style="color:#0000ff;">THEN</span> <span style="color:#808080;">-</span>1 <span style="color:#0000ff;">ELSE</span> 1 <span style="color:#0000ff;">END</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> [dbo]<span style="color:#808080;">.</span>[NameValues] <span style="color:#008000;">&#8211; WITH(ROWLOCK,XLOCK)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> Name <span style="color:#808080;">=</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">Version</span> <span style="color:#0000ff;">DESC</span><span style="color:#808080;">);</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span> <span style="color:#808080;">&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> [dbo]<span style="color:#808080;">.</span>[NameValues]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>[Name]<span style="color:#808080;">,</span> [Version]<span style="color:#808080;">,</span> [Value]<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @Name<span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">+</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">),</span> <span style="color:#ff00ff;">EncryptByKey</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">Key_GUID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;$(DB_SYMMETRIC_KEY)&#8217;</span><span style="color:#808080;">),</span> @Value<span style="color:#808080;">,</span> 1<span style="color:#808080;">,</span> @Name<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>Name<span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @Name<span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">+</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">),</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">),</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">END</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">COMMIT</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">WHILE</span> <span style="color:#ff00ff;">@@TRANCOUNT</span> <span style="color:#808080;">&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ROLLBACK</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">+</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">CLOSE</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;dbo.GetValueByName&#8217;</span><span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;P&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: fetch encrypted value </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Name [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @Value [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @Version <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">OPEN</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]
<li><span style="color:#0000ff;">DECRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">CERTIFICATE</span> [$(VALUE_CERTIFICATE_NAME)]
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>IsAuthorized<span style="color:#808080;">())</span> <span style="color:#808080;">=</span> 0
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;User&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#008000;">&#8211; password policy + SQL Injection prevention</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>CheckPhrase<span style="color:#808080;">(</span>@Value<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> @Version <span style="color:#808080;">=</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DecryptByKey</span><span style="color:#808080;">(</span> Value<span style="color:#808080;">,</span> 1<span style="color:#808080;">,</span> Name<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">FROM</span> [dbo]<span style="color:#808080;">.</span>[NameValues]
<li>&nbsp; <span style="color:#0000ff;">WHERE</span> [Name] <span style="color:#808080;">=</span> @Name
<li>&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> [Version] <span style="color:#0000ff;">DESC</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Version
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">+</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">CLOSE</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.ValidateNameValue&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>ValidateNameValue
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: validate encrypted value </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>ValidateNameValue
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Name <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">BIT</span> <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">DECLARE</span> @Version <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> 0
<li><span style="color:#0000ff;">OPEN</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]
<li><span style="color:#0000ff;">DECRYPTION</span> <span style="color:#0000ff;">BY</span> <span style="color:#0000ff;">CERTIFICATE</span> [$(VALUE_CERTIFICATE_NAME)]
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">PASSWORD</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>IsAuthorized<span style="color:#808080;">())</span> <span style="color:#808080;">=</span> 0
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;User&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#008000;">&#8211; password policy + SQL Injection prevention</span>
<li>&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>dbo<span style="color:#808080;">.</span>CheckPhrase<span style="color:#808080;">(</span>@Value<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> 0<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> @Version <span style="color:#808080;">=</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @IsValid <span style="color:#808080;">=</span> 1
<li>&nbsp; <span style="color:#0000ff;">FROM</span> [dbo]<span style="color:#808080;">.</span>[NameValues]
<li>&nbsp; <span style="color:#0000ff;">WHERE</span> [Name] <span style="color:#808080;">=</span> @Name
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#ff00ff;">DecryptByKey</span><span style="color:#808080;">(</span> Value<span style="color:#808080;">,</span> 1<span style="color:#808080;">,</span> Name<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> @Value
<li>&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> [Version] <span style="color:#0000ff;">DESC</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Version
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> @IsValid <span style="color:#808080;">=</span> 1 <span style="color:#0000ff;">THEN</span>&nbsp; <span style="color:#ff0000;">&#8216;Valid&#8217;</span> <span style="color:#0000ff;">ELSE</span> <span style="color:#ff0000;">&#8216;Invalid&#8217;</span> <span style="color:#0000ff;">END</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>NameValueHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> Name
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Version</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @Name
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Version<span style="color:#808080;">+</span>1<span style="color:#808080;">,</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">CLOSE</span> <span style="color:#0000ff;">SYMMETRIC</span> <span style="color:#0000ff;">KEY</span> [$(DB_SYMMETRIC_KEY)]<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.BackupServiceMasterKey&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupServiceMasterKey
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: backup the service master key of the SQL Server Instance</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupServiceMasterKey
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @Name <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRANSACTION</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;SMK_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>AddNameValue<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @BackupPhrase<span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupName <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewMasterKeyBackupName<span style="color:#808080;">(NULL);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupPath <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewBackupPath<span style="color:#808080;">(</span><span style="color:#ff0000;">&#8216;master&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE MASTER;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;BACKUP SERVICE MASTER KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;TO FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(MASTER_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;ENCRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8217;;&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@BackupDDL<span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483636<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">,</span>@return_code<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483635<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Service Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">COMMIT</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">@@TRANCOUNT</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">ROLLBACK</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Service Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.RestoreServiceMasterKey&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreServiceMasterKey
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: restore the service master key of the SQL Server Instance from backup</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreServiceMasterKey
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @RestoreDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span><span style="color:#ff0000;">&#8216;SMK_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> @BackupName <span style="color:#808080;">=</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#808080;">=</span> BackupPath
<li>&nbsp; <span style="color:#0000ff;">FROM</span> dbo<span style="color:#808080;">.</span>MasterKeyBackupHistory
<li>&nbsp; <span style="color:#0000ff;">WHERE</span> KeyName <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;Service Master Key&#8217;</span>
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Action</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;BackupServiceMasterKey&#8217;</span>
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> Id <span style="color:#0000ff;">DESC</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">SET</span> @RestoreDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE MASTER;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;RESTORE SERVICE MASTER KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;FROM FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(MASTER_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;DECRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8217;;&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@RestoreDDL<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483636<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">,</span>@return_code<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483635<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Service Master Key&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Service Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.BackupDatabaseMasterKey&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupDatabaseMasterKey
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: backup a database master key</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupDatabaseMasterKey
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @OpenDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>184<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CloseDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>184<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPhraseName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyPhraseName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupPhraseName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">N&#8217;_DMK_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>AddNameValue<span style="color:#0000ff;"> </span>@BackupPhraseName<span style="color:#808080;">,</span> @BackupPhrase<span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupName <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewMasterKeyBackupName<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupPath <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewBackupPath<span style="color:#808080;">(</span>@DbName<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @KeyPhraseName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">N&#8217;_DMK_ENCRYPTION_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> GetValueByName<span style="color:#0000ff;"> </span>@KeyPhraseName<span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE ['</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">'];&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;OPEN MASTER KEY DECRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @KeyPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8217;;&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;BACKUP MASTER KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;TO FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(MASTER_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;ENCRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8217;;&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;CLOSE MASTER KEY;&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@BackupDDL<span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483634<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">,</span> @return_code<span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483633<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Database Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">COMMIT</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">WHILE</span> <span style="color:#ff00ff;">@@TRANCOUNT</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">ROLLBACK</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Database Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupPath<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.RestoreDatabaseMasterKey&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreDatabaseMasterKey
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: restore a database master key from a backup</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreDatabaseMasterKey
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @DMKRestoreDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @BackupValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_DMK_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@BackupValueName<span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @KeyValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_DMK_ENCRYPTION_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@KeyValueName<span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP </span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> @BackupPath <span style="color:#808080;">=</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#808080;">=</span> BackupName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">FROM</span> dbo<span style="color:#808080;">.</span>MasterKeyBackupHistory
<li>&nbsp; <span style="color:#0000ff;">WHERE</span> KeyName <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;Database Master Key&#8217;</span>
<li>&nbsp; <span style="color:#808080;">AND</span> DbNAme <span style="color:#808080;">=</span> @DbName
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Action</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;BackupDatabaseMasterKey&#8217;</span>
<li>&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> Id <span style="color:#0000ff;">DESC</span><span style="color:#808080;">;</span>&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">SET</span> @DMKRestoreDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE &#8216;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;RESTORE MASTER KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;FROM FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(MASTER_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;DECRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#0000ff;">CASE</span> <span style="color:#0000ff;">WHEN</span> @KeyPhrase <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">THEN</span> <span style="color:#ff0000;">&#8221;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span> <span style="color:#ff0000;">&#8216;ENCRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @KeyPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;;&#8217;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@DMKRestoreDDL<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483634<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">,</span> @return_code<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483633<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span><span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Database Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> MasterKeyBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> KeyName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Database Master Key&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupPath<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.BackupCertificate&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupCertificate
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: backup a certificate&nbsp; </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>BackupCertificate
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @CertificateName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span> <span style="color:#008000;">&#8211; use stored value if exists </span>
<li><span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">=</span> <span style="color:#808080;">NULL)</span> <span style="color:#008000;">&#8211; value needed only when type = PW</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @CertificateList <span style="color:#0000ff;">TABLE </span><span style="color:#808080;">(</span>name <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">));</span>
<li><span style="color:#0000ff;">DECLARE</span> @CertificateListDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>165<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @ThumbprintDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Thumbprint <span style="color:#0000ff;">VARBINARY</span><span style="color:#808080;">(</span>32<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @PrivateKeyEncryptionType <span style="color:#0000ff;">CHAR</span><span style="color:#808080;">(</span>2<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">MAX</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRANSACTION</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_&#8217;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_CERTIFICATE_BACKUP_PHRASE&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @BackupPhrase <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@BackupValueName<span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>AddNameValue<span style="color:#0000ff;"> </span>@BackupValueName<span style="color:#808080;">,</span> @BackupPhrase<span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @KeyValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_&#8217;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_CERTIFICATE_ENCRYPTION_PHRASE&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @KeyPhrase <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@KeyValueName<span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>AddNameValue<span style="color:#0000ff;"> </span>@KeyValueName<span style="color:#808080;">,</span> @KeyPhrase<span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp; <span style="color:#008000;">&#8211; verify @DbName and @CertificateName before parsing into any query </span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @CertificateListDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;SELECT name from &#8216;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;.sys.certificates&#8217;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> @CertificateList<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>name<span style="color:#808080;">)</span>&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@CertificateListDDL<span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">END</span>
<li>&nbsp; <span style="color:#008000;">&#8211; @CertificateName is used in the where clause first to complete sql injection prevention</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">EXISTS</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> name <span style="color:#0000ff;">FROM</span> @CertificateList <span style="color:#0000ff;">WHERE</span> name <span style="color:#808080;">=</span> @CertificateName<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;Certificate&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @ThumbprintDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE &#8216;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;SELECT @Thumbprint = Thumbprint&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;&nbsp;&nbsp;&nbsp;&nbsp; , @PrivateKeyEncryptionType = pvt_key_encryption_type&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;FROM sys.certificates&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;WHERE name = @CertificateName&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@ThumbprintDDL
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">N&#8217;@CertificateName NVARCHAR(128), @Thumbprint VARBINARY(32) OUTPUT, @PrivateKeyEncryptionType CHAR(2) OUTPUT&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CertificateName<span style="color:#808080;">,</span> @Thumbprint <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">,</span> @PrivateKeyEncryptionType <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @BackupName <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewCertificateBackupName<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">,</span> @CertificateName<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @BackupPath <span style="color:#808080;">=</span> dbo<span style="color:#808080;">.</span>NewBackupPath<span style="color:#808080;">(</span>@DbName<span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE &#8216;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;;&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;BACKUP CERTIFICATE &#8216;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;TO FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(PUBLIC_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> @PrivateKeyEncryptionType <span style="color:#808080;">&lt;&gt;</span> <span style="color:#ff0000;">&#8216;NA&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> @BackupDDL <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;WITH PRIVATE KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;( FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(PRIVATE_KEY_BACKUP_EXT)&#8221;&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;, ENCRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @PrivateKeyEncryptionType <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;PW&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> @BackupDDL <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;, DECRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @KeyPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupDDL <span style="color:#808080;">=</span> @BackupDDL <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;)&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">END</span>
<li>&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@BackupDDL<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483632<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span>@CertificateName<span style="color:#808080;">,</span>@return_code<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483631<span style="color:#808080;">,</span> 0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span>@CertificateName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;backup&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CertificateName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> Thumbprint
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> PrivateKeyEncryptionType<span style="color:#808080;">)</span>
<li>&nbsp; <span style="color:#0000ff;">SELECT</span> @DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CertificateName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Thumbprint
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @PrivateKeyEncryptionType<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">COMMIT</span> <span style="color:#0000ff;">TRANSACTION</span>
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp; <span style="color:#0000ff;">WHILE</span> <span style="color:#ff00ff;">@@TRANCOUNT</span> <span style="color:#808080;">&gt;</span> 0 <span style="color:#0000ff;">ROLLBACK</span> <span style="color:#0000ff;">TRANSACTION</span><span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> CertificateName
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> Thumbprint
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> PrivateKeyEncryptionType
<li>&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@CertificateName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupPath<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Thumbprint<span style="color:#808080;">,</span>0&#215;0<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@PrivateKeyEncryptionType<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.RestoreCertificate&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreCertificate
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: restore a certificate </span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; ASSERT: the backup is located in same folder as the .mdf of the database</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and that the .mdf is never moved from that folder</span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>RestoreCertificate
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @CertificateName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li><span style="color:#808080;">,</span> @DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">DECLARE</span> @RestoreDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>4000<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @LookupDDL <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>165<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Thumbprint <span style="color:#0000ff;">VARBINARY</span><span style="color:#808080;">(</span>32<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @PrivateKeyEncryptionType <span style="color:#0000ff;">CHAR</span><span style="color:#808080;">(</span>2<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CertificateId <span style="color:#0000ff;">INT</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>1024<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @KeyValueName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @return_code <span style="color:#0000ff;">INT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> <span style="color:#0000ff;">NOCOUNT</span> <span style="color:#0000ff;">ON</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp;&nbsp; <span style="color:#008000;">&#8211; sql injections should blow up here </span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#0000ff;">TOP</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @PrivateKeyEncryptionType <span style="color:#808080;">=</span> PrivateKeyEncryptionType
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Thumbprint <span style="color:#808080;">=</span> Thumbprint
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath <span style="color:#808080;">=</span> BackupPath
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName <span style="color:#808080;">=</span> BackupName
<li>&nbsp;&nbsp; <span style="color:#0000ff;">FROM</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li>&nbsp;&nbsp; <span style="color:#0000ff;">WHERE</span> ServerName <span style="color:#808080;">=</span> <span style="color:#ff00ff;">@@SERVERNAME</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">AND</span> DbName <span style="color:#808080;">=</span> @DbName
<li>&nbsp;&nbsp; <span style="color:#808080;">AND</span> CertificateName <span style="color:#808080;">=</span> @CertificateName
<li>&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Action</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;BackupCertificate&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#808080;">AND</span> <span style="color:#0000ff;">Status</span> <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ORDER</span> <span style="color:#0000ff;">BY</span> Id <span style="color:#0000ff;">DESC</span><span style="color:#808080;">;</span>&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">DB_ID</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483644<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;Database&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @LookupDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;SELECT @CertificateId = certificate_id&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;FROM &#8216;</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;.sys.certificates&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;WHERE name = @CertificateName &#8216;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;AND Thumbprint = @Thumbprint&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@LookupDDL
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">N&#8217;@CertificateName NVARCHAR(128), @Thumbprint VARBINARY(32), @CertificateId INT OUTPUT&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CertificateName<span style="color:#808080;">,</span> @Thumbprint<span style="color:#808080;">,</span> @CertificateId <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF </span><span style="color:#808080;">(</span>@CertificateId <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL)</span> <span style="color:#008000;">&#8211; certificate exist &#8211; cannot restore</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483637<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span>@CertificateName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;cannot restore over existing certificate&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @BackupValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_&#8217;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_CERTIFICATE_BACKUP_PHRASE&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>GetValueByName<span style="color:#0000ff;"> </span>@BackupValueName<span style="color:#808080;">,</span> @BackupPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @KeyValueName <span style="color:#808080;">=</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_&#8217;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_CERTIFICATE_ENCRYPTION_PHRASE&#8217;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>GetValueByName<span style="color:#0000ff;"> </span>@KeyValueName<span style="color:#808080;">,</span> @KeyPhrase <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>&nbsp;&nbsp;
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @RestoreDDL <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;USE ['</span> <span style="color:#808080;">+</span> @DbName <span style="color:#808080;">+</span> <span style="color:#ff0000;">'];&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;CREATE CERTIFICATE &#8216;</span> <span style="color:#808080;">+</span> @CertificateName <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;FROM FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(PUBLIC_KEY_BACKUP_EXT)&#8221;&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @PrivateKeyEncryptionType <span style="color:#808080;">&lt;&gt;</span> <span style="color:#ff0000;">&#8216;NA&#8217;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">BEGIN</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @RestoreDDL&nbsp; <span style="color:#808080;">=</span> @RestoreDDL&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;WITH PRIVATE KEY&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;(FILE = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPath <span style="color:#808080;">+</span> @BackupName <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;$(PRIVATE_KEY_BACKUP_EXT)&#8221;&#8217;</span> <span style="color:#808080;">+</span> <span style="color:#ff00ff;">SPACE</span><span style="color:#808080;">(</span>1<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;, DECRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @BackupPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span> <span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @PrivateKeyEncryptionType <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;PW&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @RestoreDDL <span style="color:#808080;">=</span> @RestoreDDL <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;, ENCRYPTION BY PASSWORD = &#8221;&#8217;</span> <span style="color:#808080;">+</span> @KeyPhrase <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8221;&#8221;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SET</span> @RestoreDDL <span style="color:#808080;">=</span> @RestoreDDL <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;);&#8217;</span><span style="color:#808080;">;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">END</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">EXEC</span> @return_code <span style="color:#808080;">=</span> <span style="color:#800000;">sp_executesql</span><span style="color:#0000ff;"> </span>@RestoreDDL<span style="color:#808080;">;</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">IF</span> @return_code <span style="color:#808080;">&lt;&gt;</span> 0
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483632<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span>@CertificateName<span style="color:#808080;">,</span>@return_code<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">ELSE</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483631<span style="color:#808080;">,</span> 0<span style="color:#808080;">,</span>0<span style="color:#808080;">,</span>@DbName<span style="color:#808080;">,</span>@CertificateName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8216;restore&#8217;</span><span style="color:#808080;">);</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CertificateName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> Thumbprint
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> PrivateKeyEncryptionType<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> @DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @CertificateName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Complete&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Thumbprint
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @PrivateKeyEncryptionType<span style="color:#808080;">;</span>
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">TRY</span>
<li>&nbsp; <span style="color:#0000ff;">BEGIN</span> <span style="color:#0000ff;">CATCH</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">INSERT</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li><span style="color:#0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color:#808080;">(</span> DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CertificateName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> Thumbprint
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> PrivateKeyEncryptionType
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@DbName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@CertificateName<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupName<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@BackupPath<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">OBJECT_NAME</span><span style="color:#808080;">(</span><span style="color:#ff00ff;">@@PROCID</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;Error&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@Thumbprint<span style="color:#808080;">,</span>0&#215;0<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ISNULL</span><span style="color:#808080;">(</span>@PrivateKeyEncryptionType<span style="color:#808080;">,</span><span style="color:#ff0000;">&#8221;</span><span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#0000ff;">SELECT</span> <span style="color:#ff00ff;">ERROR_NUMBER</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorNumber
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_SEVERITY</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">AS</span> ErrorSeverity
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_STATE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorState
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_PROCEDURE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorProcedure
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_LINE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorLine
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#ff00ff;">ERROR_MESSAGE</span><span style="color:#808080;">()</span> <span style="color:#0000ff;">as</span> ErrorMessage <span style="color:#0000ff;">FOR</span> <span style="color:#0000ff;">XML</span> <span style="color:#0000ff;">RAW</span><span style="color:#808080;">);</span>&nbsp;&nbsp;
<li>&nbsp; <span style="color:#0000ff;">END</span> <span style="color:#0000ff;">CATCH</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#0000ff;">IF</span> <span style="color:#ff00ff;">OBJECT_ID</span><span style="color:#0000ff;"> </span><span style="color:#808080;">(</span><span style="color:#ff0000;">N&#8217;dbo.CertificateBackupsByThumbprint&#8217;</span><span style="color:#808080;">)</span> <span style="color:#808080;">IS</span> <span style="color:#808080;">NOT</span> <span style="color:#808080;">NULL</span>
<li>&nbsp;&nbsp; <span style="color:#0000ff;">DROP</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>CertificateBackupsByThumbprint
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/******************************************************************************</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Auth: Bill Wunder</span>
<li><span style="color:#008000;">**&nbsp;&nbsp;&nbsp; Desc: list all certificate backups for the provided thumbprint </span>
<li><span style="color:#008000;">*******************************************************************************/</span>
<li><span style="color:#0000ff;">CREATE</span> <span style="color:#0000ff;">PROCEDURE</span> dbo<span style="color:#808080;">.</span>CertificateBackupsByThumbprint
<li><span style="color:#0000ff;"></span><span style="color:#808080;">(</span> @Thumbprint <span style="color:#0000ff;">VARBINARY</span><span style="color:#808080;">(</span>32<span style="color:#808080;">)</span> <span style="color:#808080;">)</span>
<li><span style="color:#0000ff;">WITH</span> <span style="color:#0000ff;">EXECUTE</span> <span style="color:#0000ff;">AS</span> <span style="color:#0000ff;">CALLER</span><span style="color:#808080;">,</span> <span style="color:#0000ff;">ENCRYPTION</span>
<li><span style="color:#0000ff;">AS</span>
<li><span style="color:#0000ff;">BEGIN</span>
<li><span style="color:#0000ff;">SELECT</span> ServerName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> DbName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> CertificateName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupName
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> BackupPath
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Action</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> <span style="color:#0000ff;">Status</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> Thumbprint
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> PrivateKeyEncryptionType
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> ErrorData
<li><span style="color:#0000ff;">FROM</span> dbo<span style="color:#808080;">.</span>CertificateBackupHistory
<li><span style="color:#0000ff;">WHERE</span> Thumbprint <span style="color:#808080;">=</span> @Thumbprint<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">END</span>
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">&#8211; dogfood certificate encryption secrets to dbo.NameValue </span>
<li><span style="color:#008000;">&#8211; backup the hierearchy, verify the secrets</span>
<li><span style="color:#0000ff;">DECLARE</span> @Name <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value [NVARCHAR]<span style="color:#0000ff;"> </span><span style="color:#808080;">(</span>128<span style="color:#808080;">)</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">BIT</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @DbName <span style="color:#0000ff;">NVARCHAR</span><span style="color:#808080;">(</span>128<span style="color:#808080;">);</span>
<li><span style="color:#0000ff;">SELECT</span> @DbName <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">();</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SELECT</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;SMK_BACKUP_PHRASE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(SMK_BACKUP_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>BackupServiceMasterKey<span style="color:#0000ff;"> </span>@Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SELECT</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;master_DMK_ENCRYPTION_PHRASE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(master_DMK_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[AddNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SELECT</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;master_DMK_BACKUP_PHRASE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(keyback_DMK_BACKUP_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>BackupDatabaseMasterKey<span style="color:#0000ff;"> </span><span style="color:#ff0000;">&#8216;master&#8217;</span><span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SELECT</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_DMK_ENCRYPTION_PHRASE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(keyback_DMK_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[AddNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SELECT</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_DMK_BACKUP_PHRASE&#8217;</span>
<li>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:#808080;">,</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(keyback_DMK_BACKUP_PHRASE)&#8217;</span>
<li><span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>BackupDatabaseMasterKey<span style="color:#0000ff;"> </span>@DbName<span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#008000;">&#8211; Master Key encrypted certs need the back file encryption password </span>
<li><span style="color:#0000ff;">SET</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;master_$(TDE_CERTIFICATE_NAME)_CERTIFICATE_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(TDE_CERTIFICATE_BACKUP_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>BackupCertificate<span style="color:#0000ff;"> </span><span style="color:#ff0000;">&#8216;$(TDE_CERTIFICATE_NAME)&#8217;</span><span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;master&#8217;</span><span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#008000;">&#8211; password encrypted certs also need the private key encryption password at time of export </span>
<li>&nbsp;
<li><span style="color:#0000ff;">SET</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_$(VALUE_CERTIFICATE_NAME)_CERTIFICATE_ENCRYPTION_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[AddNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">SET</span> @Name <span style="color:#808080;">=</span> <span style="color:#ff00ff;">DB_NAME</span><span style="color:#808080;">()</span> <span style="color:#808080;">+</span> <span style="color:#ff0000;">&#8216;_$(VALUE_CERTIFICATE_NAME)_CERTIFICATE_BACKUP_PHRASE&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_BACKUP_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">EXEC</span> dbo<span style="color:#808080;">.</span>BackupCertificate<span style="color:#0000ff;"> </span><span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_NAME)&#8217;</span><span style="color:#808080;">,</span> @DBName<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> <span style="color:#ff0000;">&#8216;$(VALUE_CERTIFICATE_ENCRYPTION_PHRASE)&#8217;</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @Value <span style="color:#808080;">=</span> <span style="color:#808080;">NULL;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[GetValueByName]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value <span style="color:#0000ff;">OUTPUT</span><span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">SET</span> @IsValid <span style="color:#808080;">=</span> <span style="color:#808080;">NULL;</span>
<li><span style="color:#0000ff;">EXEC</span> [dbo]<span style="color:#808080;">.</span>[ValidateNameValue]<span style="color:#0000ff;"> </span>@Name<span style="color:#808080;">,</span> @Value<span style="color:#808080;">,</span> @IsValid <span style="color:#0000ff;">OUTPUT</span> <span style="color:#808080;">;</span>
<li><span style="color:#0000ff;">IF</span> @IsValid <span style="color:#808080;">=</span> 0 <span style="color:#0000ff;">RAISERROR</span><span style="color:#808080;">(</span>2147483643<span style="color:#808080;">,</span>16<span style="color:#808080;">,</span>1<span style="color:#808080;">,</span>@Name<span style="color:#808080;">);</span>
<li>&nbsp;
<li><span style="color:#0000ff;">GO</span>
<li><span style="color:#008000;">/* </span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[MasterKeyBackupHistory];</span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[CertificateBackupHistory];</span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[NameValues];</span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[NameValueHistory];</span>
<li><span style="color:#008000;">SELECT * FROM sys.dm_database_encryption_keys</span>
<li><span style="color:#008000;">*/</span>
<li>&nbsp;
<li><span style="color:#008000;">/* UNINSTALL</span>
<li><span style="color:#008000;">remove any backup files created &#8211; find path + name </span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[MasterKeyBackupHistory];</span>
<li><span style="color:#008000;">SELECT * FROM [dbo].[CertificateBackupHistory];</span>
<li>&nbsp;
<li><span style="color:#008000;">USE keyback;</span>
<li><span style="color:#008000;">ALTER DATABASE keyback SET SINGLE_USER WITH ROLLBACK IMMEDIATE;</span>
<li>&nbsp;
<li><span style="color:#008000;">USE master;</span>
<li><span style="color:#008000;">DROP DATABASE keyback;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483631;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483632;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483633;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483634;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483635;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483636;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483641;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483642;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483643;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483644;</span>
<li><span style="color:#008000;">EXEC sp_dropmessage 2147483645;</span>
<li><span style="color:#008000;">DROP CERTIFICATE TDECertificate;</span>
<li><span style="color:#008000;">DROP MASTER KEY; &#8212; only drop master&#8217;s Master Key if it was added by this script!</span>
<li><span style="color:#008000;">*/</span> </li>
</ol>
</div>
</div>
</div>
<p>(The template can also be downloaded <a href="http://bwunder.com/Documents/keyback%20Administrator.sql">here</a> if you&#8217;d like to check it out but would rather not copy/paste 1000+ lines of T-SQL. An auxiliary test script is <a href="http://bwunder.com/Documents/keyback%20Administrator%20test1.sql">here</a>.)</p>
<p><strong><font size="4">SQL Server Encryption Hierarchy Overview</font></strong></p>
<p>In a basic configuration, a SQL Server&#8217;s Database Master Keys (DMK) are encrypted by the Service Master Key (SMK).&nbsp; Certificates &#8211; always at a database scope &#8211; are encrypted by the DMK of the containing database. The SMK is always encrypted by the SQL Server Service Account user name and password. The EH may also properly include certificates originated externally from Assemblies or Hardware Security Devices HSD &#8211; either by loading certificates from files or using Extensible Key Management (EKM) in more advanced configurations.</p>
<p>
<hr />
<p>If the SQL Server service account is changed, plan for enough time to decrypt and re-encrypt the Service Master Key and everything encrypted from it!&nbsp; Use ALTER SERVICE MASTER KEY to move the key to the new account. When Database Master Keys are changed, plan for adequate time for the encryption hierarchy within the database to refresh using the new key. Use the REGENERATE option of&nbsp; ALTER SERVICE MASTER KEY or ALTER MASTER KEY to begin the refresh of the hierarchy of encrypted data using the changed key.&nbsp; </p>
<p>
<hr />
<p>A password is required to encrypt any Encryption Hierarchy backup file. When backups are done using the stored procedures created from the template, the passwords are encrypted and stored along with the audit history in the selected user database. Members of the keybackAdmin database role can export, import or regenerate master keys at will &#8211; being a <em>sysadmin </em>alone is not enough, you must also be a member of the keybackAdmin role. Carefully restrict the membership. Non keybackAdmin sysadmins can still corrupt the database and they can still backup encryption hierarchy nodes using ad hoc methods, but the ability to recover secrets is far less likely. Consistently storing secrets used to encrypt the encryption hierarchy objects and secrets used to backup the object are both necessary in order to be able to restore using the keyback stored procedures.&nbsp; </p>
<p>BACKUP and RESTORE syntax for the SMK and any DMKs are pretty straight forward. The password or phrase to encrypt the backup is always required. Database Master Keys may also have been encrypted with a password &#8211; instead of &#8211; or in addition to &#8211; the Service Master Key. Certificates&#8217; have even more options to consider. The certificate may have been imported and have no dependency upon the database Master Key. The private key may have been intentionally dropped. </p>
<p>I recommend Master Keys and Certificates are not backed up routinely.&nbsp; There is nothing in the template that should be scheduled to run once a day, week or even month in every database on the server. Instead, Encryption Hierarchy Management should be a part of the software lifecycle change process. Save any passwords/phrases to the encrypted NameValue store at the time the keys and certificates are created or changed.&nbsp; Backup keys and certificates when created or changed, then monitor for unexpected change, get that secure offsite location up and running, and establish a test environment for use to restore and validate your keys held in backup. You may even want to consider detaching the database when not in use. Under TDE or file system encryption this will be more secure than leaving the idle database for window shoppers&#8230;</p>
<p>As you use the template you may find a need to customize it to suit your needs. Go for it. It is a template. As with restores, just be sure to test your changes before you throw them at a live SQL Server or at an existing keyback data set.</p>
<p>Executing a script built from this template will establish an Encryption Hierarchy secret store and logging database &#8211; keyback is the database name I use &#8211; and then dog food backups of the pieces of the Encryption Hierarchy of the master and keyback database that are used by the tool to the same folder as the <em>.mdf</em> for the database. The Encryption Hierarchy is backed up, the secret store is validated, and you get to see the tool in action.</p>
<p><font size="4"><strong>Sugge</strong></font><font size="4"><strong>sted Template Deployment</strong></font></p>
<p>Add the script to the template library of the clients used to work from the Central Management Server for the environment.</p>
<p><a href="http://bwunder.files.wordpress.com/2011/07/add-template.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="Add template" border="0" alt="Add template" src="http://bwunder.files.wordpress.com/2011/07/add-template_thumb.png?w=331&#038;h=308" width="331" height="308"></a></p>
<p>When you load the script into a SQL Server Management Studio query window &#8211; whether or not is has been saved to the template library, hit CTRL+SHFT+M to see the parameters you must provide to complete the template.</p>
<p><a href="http://bwunder.files.wordpress.com/2011/07/keybackadminparameters.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="keybackAdminParameters" border="0" alt="keybackAdminParameters" src="http://bwunder.files.wordpress.com/2011/07/keybackadminparameters_thumb.png?w=621&#038;h=377" width="621" height="377"></a></p>
<p>The values with defaults can be changed or you can use the default, the secrets have no defaults. Enter words or phrases that meet the password strength requirements of the local environment.</p>
<p>Choose any existing database or specify a database name that does not exist and the database will be created.</p>
<p>In addition to creating the database the script will: </p>
<ul>
<li>Backup the Service Master Key
<li>Create &#8211; if necessary &#8211; and backup the Database Master Key for the master
<li>Create and backup a certificate in master for use in TDE of the keyback database
<li>Create and backup the Database Master Key for the keyback database
<li>Create a Database Encryption Key in the keyback database (SQL 2008 Enterprise, DataCenter and Developer editions only) You my want to use file system encryption such as TrueCrypt if your SQL Server instance is not TDE capable. I wrote a bit about that in a <a href="http://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/" target="_blank">previous post</a>. With file system encryption the key or certificate backup is better secured from the moment it is created.
<li>Create and backup a certificate used to encrypt the password/passphrases use in administration of the Encryption Hierarchy.
<li>Encrypt and save all secrets used in the script. This means you do not need (ought never?) to save the script once your secrets are entered into the template. </li>
</ul>
<p>The keyback database also includes some executable objects all of which are encrypted to discourage tourists. You can remove the encryption if you like before you replace the template parameter tokens.</p>
<blockquote><p>Scalar functions to support a standard backup file naming standard</p>
<pre class="code"><span style="color:green;">--returns the path to the .mdf of the Db but not the .mdf file name
</span>dbo<span style="color:gray;">.<font color="#000000">New</font></span>BackupPath @DbName
<span style="color:green;">--returns a string with embedded timestamp to uniquely identify backup files
</span>dbo<span style="color:gray;">.</span><font color="#000000">New</font>CertificateBackupName @DbName<span style="color:gray;">, </span>@CertificateName
<span style="color:green;">--returns a string with embedded timestamp to uniquely identify backup files
</span>dbo<span style="color:gray;">.</span>MasterKeyBackupName @DbName</pre>
<p>&nbsp;</p>
<p>Scalar functions for SQL Injection filtering and elevation of authority attacks. You can flush them out in the template.</p>
<p>Stored procedures for saving and retrieving secrets. You can make the secrets as strong as you like &#8216;em! I limit to NVARCHAR(128) but that can be changed easily if you need more.</p>
</blockquote>
<blockquote><pre class="code"><span style="color:green;">-- every secret needs a name and a value
-- the @Value is stored in an encrypted columns
-- the @Name is always used as the encryption authenticator
</span>dbo<span style="color:gray;">.</span>AddNameValue @Name<span style="color:gray;">, </span>@Value
dbo<span style="color:gray;">.</span>GetValueByName @Name<span style="color:gray;">, </span>@Value <span style="color:blue;">OUTPUT
</span>dbo<span style="color:gray;">.</span>ValidateNameValue @Name<span style="color:gray;">, </span>@Value<span style="color:gray;">, </span>@IsValid <span style="color:blue;">OUTPUT
</span></pre>
<p>&nbsp;</p>
<p>Stored procedures for use in backup up any and all Master Keys and Certificates on the server.</p>
<pre class="code"><span style="color:green;">-- @BackupPhrase encrypts the backup file
-- @KeyPhrase decrypts a certificate's private key before backup
</span>dbo<span style="color:gray;">.</span>BackupCertificate @CertificateName<span style="color:gray;">, </span>@DbName<span style="color:gray;">, </span>@BackupPhrase<span style="color:gray;">, </span>@KeyPhrase<span style="color:gray;">(</span>optional<span style="color:gray;">)
</span>dbo<span style="color:gray;">.</span>BackupDatabaseMasterKey @DbName<span style="color:gray;">, </span>@BackupPhrase<span style="color:gray;">, </span>@KeyPhrase<span style="color:gray;">(</span>optional<span style="color:gray;">)</span>
dbo<span style="color:gray;">.</span>BackupServiceMasterKey @BackupPhrase</pre>
<p>&nbsp;</p>
<p>Stored procedures for use in restoring Master Keys and Certificates that have been previously backed up by the tool . This tool is intended for use only when restoring a backup taken using the tool. Keeping the backups up-to-date is quite important. The thing is, you will never know what day you will need them until the day you need one.</p>
<pre class="code"><span style="color:green;">-- often all the information a message provides about a missing certificate is the thumbprint
</span>dbo<span style="color:gray;">.</span>CertificateBackupsByThumbprint @Thumbprint

<span style="color:green;">  -- these guys are made simple to helpful in an emergency
  -- always gets the most recent backup of an object
</span>  dbo<span style="color:gray;">.</span>RestoreCertificate @CertificateName<span style="color:gray;">, </span>@DbName
  dbo<span style="color:gray;">.</span>RestoreDatabaseMasterKey @DbName
  dbo<span style="color:gray;">.</span>RestoreServiceMasterKey</pre>
</blockquote>
<p>Successful Execution of the script produces output something like this. The warning message (2) is a system generated message that will only be seen when the database Encryption Key is created. If, for example, the key already exists, this message is not seen.</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9c715d66-dbdf-4fcb-b50f-2295e949836b" class="wlWriterSmartContent">
<div style="border-bottom:#000080 1px solid;border-left:#000080 1px solid;font-family:'Courier New', courier, monospace;color:#000;font-size:10pt;border-top:#000080 1px solid;border-right:#000080 1px solid;">
<div style="font-family:verdana, tahoma, arial, sans-serif;background:#000080;color:#fff;font-weight:bold;padding:2px 5px;">Typical Script Output</div>
<div style="background-color:#ffffff;max-height:500px;overflow:auto;padding:2px 5px;">Protect all Encryption Hierarchy backup files and maintain a copy in a secure offsite location. </p>
<p>Warning: The certificate used for encrypting the database encryption key has not been backed up. You should immediately back up the certificate and the private key associated with the certificate. If the certificate ever becomes unavailable or if you must restore or attach the database on another server, you must have backups of both the certificate and the private key or you will not be able to open the database.</p>
<p>keyback info &#8211; Service Master Key backup complete.</p>
<p>keyback info &#8211; database master Master Key backup complete.</p>
<p>keyback info &#8211; database keyback Master Key backup complete.</p>
<p>keyback info &#8211; database master certificate TDECertificate backup complete.</p>
<p>keyback info &#8211; database keyback certificate ValueCertificate backup complete.</p>
</div>
</div>
</div>
<p>&nbsp;</p>
<p>Creates backups of the newly created Encryption Hierarchy:</p>
<p><a href="http://bwunder.files.wordpress.com/2011/07/encryptionhierachybackups.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionHierachyBackups" border="0" alt="EncryptionHierachyBackups" src="http://bwunder.files.wordpress.com/2011/07/encryptionhierachybackups_thumb.png?w=621&#038;h=467" width="621" height="467"></a></p>
<p>And records a complete history of all actions taken or attempted (clicking the image should open it in a bigger view).</p>
<p><a href="http://bwunder.files.wordpress.com/2011/07/encryptionhierarchyadminhistory.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="EncryptionHierarchyAdminHistory" border="0" alt="EncryptionHierarchyAdminHistory" src="http://bwunder.files.wordpress.com/2011/07/encryptionhierarchyadminhistory_thumb.png?w=652&#038;h=398" width="652" height="398"></a></p>
<p>In environments where the sysadmin membership is greater than 2 or 3, the storage location (BackupPath and BackupName) should also be encrypted. The membership in the keybackAdmin role should definitely be limited to 1 individual in all cases. Accountability is essential. Instead of two people sharing one keyback, consider having both establish separate keyback monitoring protocols. Other means to improve security when considered in the context of the local environment where the template is applied should also be considered. The stronger the layers of security around the secret store database, the better.</p>
<p>If you can recreate the TDE and reliably produce the keyback_ValueCertificate_CERTIFICATE_ENCRYPTION_PHRASE when needed, the likelihood that any Encryption Hierarchy Backup in the collection can be reliably restored is quite high. Under normal operation there will be no need to either recreate the TDE or manually enter the ValueCertificates&#8217;s&nbsp; encryption password.</p>
<p>Enjoy!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/234/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/234/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/234/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=234&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/07/01/encryption-hierarchy-administration-a-t-sql-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/07/add-template_thumb.png" medium="image">
			<media:title type="html">Add template</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/07/keybackadminparameters_thumb.png" medium="image">
			<media:title type="html">keybackAdminParameters</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/07/encryptionhierachybackups_thumb.png" medium="image">
			<media:title type="html">EncryptionHierachyBackups</media:title>
		</media:content>

		<media:content url="http://bwunder.files.wordpress.com/2011/07/encryptionhierarchyadminhistory_thumb.png" medium="image">
			<media:title type="html">EncryptionHierarchyAdminHistory</media:title>
		</media:content>
	</item>
		<item>
		<title>The Emperor&#8217;s New Transparent Data Encryption</title>
		<link>http://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/</link>
		<comments>http://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 23:01:55 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[AES-NI]]></category>
		<category><![CDATA[compliance]]></category>
		<category><![CDATA[SQL Server and encrypted disk]]></category>
		<category><![CDATA[TDE]]></category>
		<category><![CDATA[TrueCrypt]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/</guid>
		<description><![CDATA[Translucent Databases&#160; (9780967584416) by Peter Wayner (2002) describes a database environment that reaches for security by separating information from data. Sort of a Hotel SQL Server: the data goes in but the information cannot get out. The result is an &#8230; <a href="http://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=193&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em><a href="http://www.alibris.com/search/books/qwork/-96758441/used/Translucent%20Databases" target="_blank">Translucent Databases&nbsp; (9780967584416)</a></em> by Peter Wayner (2002) describes a database environment that reaches for security by separating information from data. Sort of a <em>Hotel SQL Server</em>: the data goes in but the information cannot get out. The result is an encryption driven environment where no single view inside or outside of the organization exposes all the data in the database in an unencrypted state at one time. The land where only the hash of your password is buffered, passed or persisted. Never the password. (Imagine! You, and of course that dude across the room that can memorize any 50 keystrokes you type from across the room, are the only one(s) that know your passwords! Yes there are such people&#8230;) A place where different parts of the data are encrypted with different keys, and keys belongs to disparate organizational units. Where the DBA sees a customer table with mostly VARBINARY columns and perhaps other somehow index-able values that the various key authorities or application layer indexers have generated as that authority encrypts data. Wayner, in 2002 called it <em>Translucent Data Encryption</em>. Was he way off base since we have not vigorously pursued the mechanisms he postulated? I don&#8217;t think so. Instead, what has happened is the standards we strive for are too weak. Furthermore, organizations fear security strategy that works because they fear the secure environment will be grinding slow and unusable, so they default to <em>compliance</em>. And then the organizations point helplessly to the standards while being hacked mercilessly: giving up <em>our</em> personally identifiable information in the process.</p>
<p>I suspect that RSA and Siemens and Sony and Citi and Sega and all the others were not far out of compliance with current standards yet millions of people have had pieces of their identity stolen recently in the small number of disclosed events. One is left to ponder just how many organizations are dishonest enough not to disclose breaches. (Update February 2, 2012 &#8211; you doubt it? VeriSign admits they were &#8220;<a href="http://www.computerworld.com/s/article/9223936/VeriSign_admits_multiple_hacks_in_2010_keeps_details_under_wraps" target="_blank">successfully hacked several times in 2010</a>&#8221; but saw no need for the admission until today. Wonder when they will get around to telling us about what happened in 2011? There must be some reason they decided to come clean all of the sudden.) Not that big of deal to disclose I suppose. The only recourse we have is whether to save, trash or recycle the sympathy card from the organization that may have just cost a customer a lifetime of financial misery. Why have organizations accepted the weak standards? Why do the organizations now verbalized that that strong security is a pipe dream? hmmm&#8230;.</p>
<p>&#8220;<a href="http://simson.net/ref/2004/csci_e-170/handouts/final/bhattacharya-karyar_paper.pdf" target="_blank">Translucent Databases: A Precursor to Privacy Sensitive Databases (.pdf)</a>&#8220;, a paper I stumbled on recently by students Palaka Bhattacharya and Morteza Karya from an advanced survey of security course at Harvard from 2004 is drawn upon Wayner&#8217;s ideas. Database scenarios for cancer research, rape victims and a suggestion box are thoughtfully and creatively considered in the paper. Several good ideas about extending the Translucent Database to the specific security requirements particular to <a href="http://www.eff.org/deeplinks/2009/09/what-information-personally-identifiable" target="_blank">personally identifiable information</a><em></em> are described. That students in a survey course can so lucidly map a convergence between the real world problems and the concepts from a book says good things about the students to be sure, something about the validity of the concepts in the book, and something about how little real progress we&#8217;ve made in the last decade on data security and in particular the ever-shrinking respect for the privacy of the customer/user.</p>
<p>Here we are many years later:</p>
<ul>
<li>People steadfastly clinging to an obviously false belief that privacy policies are there to safeguard our data and that we are using best of breed solutions on problems that we must ultimately accept as unsolvable. Those privacy policies often do just the opposite. Facebook is a good example of an identity<em> puppy mill. </em>Google is no better. I can&#8217;t prove it from here but I am quite certain I got clobbered with a man-in-the-middle exploit when I linked my WordPress Blog to my Linked-In account. Strangely, the next day my yahoo email contact list was compromised (fixed it with a password change).
<li>Organizations continuing to pretending that compliance &amp; self regulation is as good as security gets. What they really know all it is is as cheap as it gets. Real security infrastructure costs considerably more than the false front we see. Sadly, in too many cases all that is behind the false front is a couple of long wobbly sticks wedged to the ground to prop it up. </li>
</ul>
<p>As a bit of proof that we aren&#8217;t that good at even recognizing good security standards,&nbsp; I offer up the message I receive when I try to upload to the BLOG from the Windows Live Write client when the local Security Policy is checking for FIPS compliance:</p>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">WindowsLiveWriter,1.8800,Fail,00025,22-Jun-2011 16:43:05.969,</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">"System.TypeInitializationException:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"> The type initializer for 'WindowsLive.Writer.CoreServices.HttpRequestHelper' threw an exception.</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"> ---<span style="color:#0000ff;">&gt;</span> System.TypeInitializationException:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">      The type initializer for 'WindowsLive.Writer.CoreServices.WsseAuthenticationModule' threw an exception.</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">      ---<span style="color:#0000ff;">&gt;</span> System.InvalidOperationException:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">      This implementation is not part of the Windows Platform FIPS</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">      validated cryptographic algorithms.</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">at System.Security.Cryptography.SHA1Managed..ctor()</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;">at WindowsLive.Writer.CoreServices.WsseAuthenticationModule..cctor()</pre>
<p>&nbsp;</p>
<p>The fix: disable the FIPS compliance policy to upload to the blog. Not sure if&nbsp; other Microsoft Cloud technology will have this problem, have not tested it.</p>
<p>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>Transparent Data Encryption (TDE) is an encryption technique offered first for Oracle 10g Databases then later introduced into Microsoft SQL Server 2008. <a href="http://msdn.microsoft.com/en-us/library/bb934049.aspx" target="_blank">SQL Server TDE</a> encrypts only at the database level while the <a href="http://www.oracle.com/technetwork/database/security/twp-transparent-data-encryption-bes-130696.pdf" target="_blank">Oracle TDE</a> can also handle column and tablespace encryption strategies. TDE is included only in SQL Server 2008 Enterprise, Data Center, and of course Developer flavors. Correct me if I am wrong, but I think you can add Oracle TDE to any 10g/11i database but it is priced separately. I mention this competition to help establish why SQL Server even offers TDE and also clarify why the technology is available only in the high end SQL Server SKUs. I think it fair to say TDE came to SQL Server as &#8220;me too&#8221; technology.</p>
<blockquote>
<hr />
<p><strong>&#8220;me too&#8221; </strong></p>
<p><strong>How corporate competition stifles software innovation</strong></p>
<p>Say Company O has a product in wide use. Company M enters the market with a lower cost, easier to use product that serves almost the same purpose for the customer but with fewer and different features and without interchangeable compatibility with Company O&#8217;s product. Instead of purchasing the less expensive product, customers tell Company M&#8217;s sales staff that the product is just not as robust as Company O&#8217;s product. The sales staff collects the information and funnels it back to Company M HQ. The potential customers either choose not to switch from Company O&#8217;s product or to purchase from Company O instead of Company M in more cases than not. As things get desperate, Company M&#8217;s sales &amp; marketing folks initiate ever more urgent and decisive enhancement requests for the &#8216;features needed to compete&#8217;! The risk assessment and/or cash flow and/or leadership egos do not allow time for vibrant R&amp;D and anyway, the sales staff is adamant that the risk of upsetting customer&#8217;s with educational requirements for new or significantly different product features is too great. Development becomes fixated on delivering a functional &#8211; even if not yet fully usable &#8211; version 1 feature set to match targeted competitor features. The strategic purpose is to be seen as an equal competitor to Company O &#8211; at least in the silly mirror.&nbsp; The message from leadership is that this vacuous short term play will solve the direct and immediate threat to long term product viability. Thus leaving the technology staff no choice but to make hay of it. Before you know it, when customers complain, account managers can say&nbsp; we have that feature too now. At this point the commonly practiced &#8220;wait for SP1&#8243; avoidance behavior of the (ill-conceived?) feature(s) can begin. Eventually a sufficiently robust competitive feature list evolves while the competitor moves on as well.</p>
<p>The time to deliver those iterations is taken from time available for any other R&amp;D investments. In this way,&nbsp; free market competition leads to a product targeting a competitor&#8217;s&nbsp; feature list rather than any real customer need and time available for true innovation is diminished product wide. The net effect will hopefully include increased short term earnings for corporations and, unfortunately,&nbsp; fewer real choices for consumers of the product.</p>
<p>There is likely no way to even make a good correlation between &#8220;me-too&#8221; R&amp;D and mid or long term benefit to the corporation. Nonetheless, a business strategy that aims to beat others at their own game is risky, expensive, and ultimately counter-productive. It&#8217;s the opposite of a game changer.</p>
<p><hr /></blockquote>
<p>(Ok, I&#8217;ve already exceeded my knowledge of Oracle&#8217;s TDE so I will limit my remarks to Microsoft SQL Server&#8217;s TDE from here.)</p>
<p><strong>SQL Server 2008 Transparent Data Encryption</strong></p>
<p>The <a href="http://technet.microsoft.com/en-us/library/ms189586.aspx" target="_blank">Encryption Hierarchy</a> is equally available in all SQL Server SKUs. However, TDE is included only in Enterprise, Developer and Data Center editions. TDE is an emerging version 1 &#8220;me too&#8221; technology. It has seen a couple service releases. Predictably, the adoption rate was delayed at introduction but is now picking up some steam. Fortunately, I suspect there is not a lot of code involved in TDE so the unexpected consequences for jumping in early were small. <a href="http://www.sqlservercentral.com/articles/Transparent+Data+Encryption/66334/" target="_blank">Roy Ernest found a few good ones</a>. Given the lack of disaster stories &#8211; somewhat confirming that the code changes were not large &#8211; I can only speculate as to why the technology in not available in all $KUs. The additional logic is to implement CryptoAPI hooks into SQL Server Buffer Pool management and plop in a CREATE and ALTER DDL statement &#8211; but no DROP &#8211; to manage the <a href="http://blogs.msdn.com/b/sqlsecurity/archive/2010/06/14/database-encryption-key-dek-management.aspx" target="_blank">Database Encryption Key</a> (DEK) stored in a small and always unencrypted space within the encrypted database. If you are the DBA and you enable TDE and manage the keys &#8211; or nobody manages the keys &#8211; don&#8217;t expect your risk exposure to go down by much. Most of what TDE is about is removing implicit need to trust DBAs and other administrators. What DBAs can benefit from is the always encrypted backups from a TDE database and as result a mechanism to allow the organization to better control who can use that encrypted backup and where. The other main protection that TDE provides &#8211; data at rest encryption &#8211; is pretty close to never in play for a service like SQL Server that is typically running 24&#215;7, has a lock on the file at all times, and exposes all data only in unencrypted form to all user database connections while running anyway. Most of what you need encryption for &#8211; protecting sensitive data &#8211; cannot be done with TDE. Lets face it, TDE is a low cost compliance alternative or supplement to proven application layer encryption, hashing and cryptographic signing approaches to data protection.</p>
<p><em>Compliant corporations absolve liabilities, litigate and lobby. Secure corporations&nbsp; protect your personally identifiable information with all their might. </em></p>
<p>SQL Server TDE occurs in low level IO processing. The data is encrypted just before the bus ride to secondary storage and then decrypted just as it transits back to primary storage. The implementation should benefit from XEON encryption acceleration. The documentation state that TDE uses the, &#8220;Windows Cryptographic API (CAPI)&#8221;. Interestingly, the number one hit in my Google for, &#8220;Windows Cryptographic API (CAPI)&#8221; is a <a href="http://en.wikipedia.org/wiki/Microsoft_CryptoAPI" target="_blank">sardonic wikipedia entry</a> who&#8217;s author(s) seems to have shared my longstanding confusion about all these names for Microsoft Cryptographic technologies being bantered about. The second result is the link to the &#8220;<a href="http://msdn.microsoft.com/en-us/library/aa380255%28v=VS.85%29.aspx" target="_blank">Microsoft CryptoAPI</a>&#8220;. Not one nor the other ever mentions or uses the phrase &#8220;<em>Windows</em> Cryptographic API&#8221; &#8211; not even the one that shows a long list of synonyms for the CryptoAPI. Lucky for me, the search engine seems to know what I want. I think this is a case where the SQL Server Documentation adds confusion where there was already enough. (It&#8217;s almost like the documentation team was trying to make the Wikipedia volunteer look ill-informed by using a name not listed. They are coming after me next I sure.)</p>
<p>The main benefits of TDE over other encryption techniques are:</p>
<ul>
<li>the encryption requires no modification to the application
<li>the encryption is generally recognized as compliant to <a href="https://www.pcisecuritystandards.org/security_standards/documents.php?document=pci_dss_v2-0#pci_dss_v2-0" target="_blank">PCI-DSS</a> Data at Rest requirements
<li>TDE database backups are also encrypted using the DEK
<li>no data is exposed as clear text if files are copied, stolen or probed <em>in-situ </em>- unless the probing is done via a SQL Server connections, in which case all data is exposed as clear text. </li>
</ul>
<p>Nothing about the data being better protected from application level attacks!? This is because TDE exposes only decrypted data to all application and <em>ad hoc</em> user connections to the database. Authenticated users connected to the database &#8211; whether for legitimate or malicious purposes &#8211; see decrypted data in all query results. There is no option to view the cipher text. The encryption is at the page level so the page must be decrypted to even find out much about the rows on that page I would imagine. There is no need for the user to provide credentials other than those presented for a &#8216;normal&#8217; connection without TDE enabled. From the outside world the database is <a href="http://www.youtube.com/watch?v=I1wg1DNHbNU" target="_blank">the same as it ever was</a>. The data is encoded as it moves from primary, i.e. SQL Server data buffers to secondary storage, i.e. a RAIN (redundant array of independent NAND) of 750,000 IOP <a href="http://www.micron.com/products/solid_state_storage/enterprise_pcie_ssd.html" target="_blank">Micron p320hs</a> SSDs or a few direct attached storage enclosures stuffed with commodity SAS drives or a zone of <a href="http://www.brocade.com/downloads/documents/technical_briefs/Encryption_Solutions_GA-TB-099-02.pdf" target="_blank">Brocade</a> 96 gigabits per second encrypted LUNs.</p>
<p>The Database Encryption Key (DEK) is the core secret of TDE. It is not mentioned in any catalog views and is not accessible in the same way as other keys in the database. From Books Online:</p>
<blockquote>
<p>&#8220;The database encryption key cannot be exported from the database. It is available only to the system, to users who have debugging permissions on the server, and to users who have access to the certificates that encrypt and decrypt the database encryption key.&#8221;</p>
</blockquote>
<p>There should be no reason for application user&#8217;s to access the DMK or DEK.&nbsp; Execution of all DMK DDL requires CONTROL permission on the database and VIEW DEFINITION permission on any asymmetric key or certificate mentioned in the DDL. If any application user requires CONTROL of the database they inherit control the DEK. Application users requiring elevated database permission increase the of risks of a breach. (HINT: Applications that require CONTROL of the database for anything are not secure by design.)</p>
<p>If all the application does at the database is INSERT, UPDATE, SELECT and maybe DELETE data, yet has authority &#8211; explicitly or implicitly &#8211; to mess with the DEK then consider tuning the security dial toward the <em>principal of least privilege</em>. IMHO, application users should not have direct INSERT, UPDATE, or DELETE table permissions. This is even more true when the data is at all sensitive or private. Use stored procedures instead. Even for SELECT queries stored procedures are recommended &#8211; <a href="http://msdn.microsoft.com/en-us/library/ms175528.aspx" target="_blank">prepared statements</a> are almost as good but the dependency chain is strongest when only stored procedures are used and they need direct table permission.&nbsp; With stored procedures, the only permission the application user needs is EXECUTE on the procedure.&nbsp; The application user should never own tables, schemas or databases. Only the rarest of application users should be a member of any Fixed Server Role. The access level of the application users must be carefully considered because application users are the most likely way bad guys will initially access the system.</p>
<p>Any database user can still view/copy/modify any data maliciously that they are also able to view/copy/modify legitimately. This is equally true if the user identity is taken over for malicious use or if the user identity is otherwise compromised.&nbsp; This is true whether the data store is protected by TDE or file system encryption (an alternative to TDE described below).&nbsp; TDE encryption protects the data from a file copy attack and some other trust exploitation attacks. TDE also encrypts all backup of the database.&nbsp; By <em>transparent is meant</em>: applications and <em>ad hoc</em> SQL Server connections never know the data at rest is encrypted. Chris Kranz, in &#8220;A NetApp Technical Diary&#8221;, blogs <a href="http://wafl.co.uk/storage-level-data-encryption/" target="_blank">a similar concern about the real benefit of storage level encryption</a> from a systems perspective. </p>
<p>All secrets and certificates that are used to configure the TDE must be protected in order to protect the TDE. There are more than a couple important secrets to protect. The actual number can vary depending up the tactics selected for encryption. If encryption provides a choice between a certificate and secret, most of time I choose the certificate. Ideally, the data administrator must provide one password and the HSM or key vault administrator must provide one other password in order to restore a TDE database backup anywhere but the SQL Server that generated that backup. </p>
<p>The architecture and configuration options for TDE are nicely covered in Zubair Ahmed Mughal&#8217;s post on &#8220;<a href="http://blogs.msdn.com/b/sqlsecurity/archive/2010/06/14/database-encryption-key-dek-management.aspx" target="_blank">Database Encryption Key Management</a>&#8221; in the MSDN <a href="http://blogs.msdn.com/b/sqlsecurity/" target="_blank">SQL Server Security</a> weblog. <em>This should be in Books online.</em></p>
<p>The configuration options for <a href="http://weblogs.sqlteam.com/mladenp/archive/2009/04/28/Comparing-SQL-Server-HASHBYTES-function-and-.Net-hashing.aspx" target="_blank">hashing</a>, <a href="http://www.sommarskog.se/grantperm.html#Certificates" target="_blank">signing</a> and encryption of identified data values are not as easily condensed to a single link. Look for Raul Garcia&#8217;s posts in the <a href="http://blogs.msdn.com/b/sqlsecurity/" target="_blank">SQL Server Security</a> weblog for insights into SQL Server&#8217;s implementation. But even before you go there, a decision whether to encrypt in the application or in the database is needed. A developer/architect starting point is this <a href="http://corporate.visa.com/_media/best-practices.pdf" target="_blank">&#8220;VISA BEST PRACTICES: Data Field Encryption&#8221; (.pdf)</a>&nbsp; that advocates , &#8220;data field encryption as a complement to, rather than a substitute for PCI-DSS compliance requirements&#8221;</p>
<p>As with the EKM + HSM solution, if encryption occurs at the point of data creation or entry, the data administrators need not know the unencrypted values to administer the data. She probably cannot help you much with searching or sorting based on that data values though. Further, the data administrator is not involved in the administration of certificates or secrets other than Certificates encrypted by database master keys .</p>
<hr />
<blockquote>
<p align="center"><strong>TDE is useless against 90% of the attacks on your data!</strong></p>
<p align="center"><strong></strong></p>
</blockquote>
<hr />
<p>Hopefully I have painted the picture enough to clearly show that TDE really isn&#8217;t so much protection in the grand scheme of things. According&nbsp; to this 2009<a href="http://blogs.msdn.com/b/ace_team/archive/2009/12/16/simple-rules-to-stop-bad-guys.aspx" target="_blank"> ACE Team weblog post</a> that provides 6 &#8220;Simple Rules to Stop the Bad Guys&#8221; 90% of attacks come at the application layer. TDE does nothing to stop that 90%. TDE targets some part of the other 10%. It&#8217;s strength is in embargoing the insider attack and securing the backup, but is only effective if the organization has the fortitude to truly protect the encryption key from the DBA and all other administrators. Few take the necessary steps. TDE in that context can help prevent data from walking out the back door. A DBA managed TDE DEK should decelerate the speed with which the back door swings wide open. Any careless use of TDE will increase the CPU load and can result in loss of data if a corruption issue requiring a restore from last known good backup is incurred only to have an untested restore process fail. The good news is, TDE is pretty much plug and play as long as nothing goes wrong.</p>
<p>Column level encryption, implemented in such a way that only authorized users can access the keys required to decrypt the column &#8211; perhaps in conjunction with TDE or file system encryption of the database file(s) &#8211; is a more realistic way to protect sensitive data at rest because it provides protection from application layer attacks. If the key is stored in the SQL Server it cannot be secured from all data administrator and may be more vulnerable to hacking. Keeping the encryption keys in a physical store that administrators of the database, database server OS and database subnet do not control will improve protection of <em>the data</em> from internal attacks. At a minimum, a good <a href="http://it-audit.sans.org/blog/2010/04/26/translating-security-principles-management-separation-duties/" target="_blank">separation of responsibilities strategy</a> would require that at least two admins be in cahoots to be able to steal a backup.</p>
<p>EKM enables separation of responsibilities by moving the certificate store to a Hardware Security Modules (HSM), and thereby breaking away from the single principle in control condition of the SQL Server Encryption Hierarchy. At least a few currently available HSMs advertise that they have the required Cryptographic Provider .dll for use with the SQL Server EKM.&nbsp; I have no hands on experience with an HSM. Unless I am mistaken, the 5 HSMs reviewed in this <a href="http://www.opendnssec.org/wp-content/uploads/2011/01/A-Review-of-Hardware-Security-Modules-Fall-2010.pdf" target="_blank">Internet Infrastructure Foundation commissioned HSM review (.pdf)</a> all serve keys to the EKM? A good place to jump in and learn a little anyway.</p>
<hr />
<p><strong><em>Are there alternatives when you do not have a TDE enable SQL Server SKU, cannot change the application, and yet have important and sensitive data that must be protected when at rest for compliance?</em></strong></p>
<hr />
<p>Lets set the bar low and say we want to be able to use SQL Server 2005 EXPRESS or better. Better meaning that the solution will also work on other SQL Server 2005 SKUs or any SQL Server 2008 SKU, or any SQL Server 2008 R2 SKU -only better because SQL Server 2005 EXPRESS is the poodle in the wolf pack.</p>
<p>Microsoft has published a white paper titled, &#8220;<a href="http://msdn.microsoft.com/en-us/library/cc278098.aspx" target="_blank">Database Encryption in SQL Server 2008 Enterprise Edition</a>&#8220;. Mostly it is a yet another how-to on implementing TDE. Though it does give a bit of valid consideration to several options. The most interesting of those options is file system encryption.</p>
<p><strong>Transparent File System Encryption -vs- TDE</strong></p>
<p>One option to encrypt the file system is <a href="http://technet.microsoft.com/en-us/library/cc732774.aspx" target="_blank">BitLocker</a> integrated file system encryption included with Windows 7+ Vista + Server 2008. Or its predecessor the <a href="http://www.sqlservercentral.com/articles/Administration/implementing_efs/870/" target="_blank">Encrypting File System</a> in Windows 2000+XP-Pro+Server 2003, or even one of the <a href="http://en.wikipedia.org/wiki/Comparison_of_disk_encryption_software" target="_blank">3rd party disk encryption software</a>.&nbsp; One vendor, <a href="http://www.gosecure.eu/compare.html" target="_blank">gosecure, provides a nice comparison</a> of their product to a couple other encryption software products with a list price and to <a href="http://www.truecrypt.org/" target="_blank">TrueCrypt</a>, an open source, free, on-the-fly and transparent encryption software that could even encrypt your MySQL databases that runs on a Linux box if you were so inclined. I&#8217;ll focus on TrueCrypt because I have actually used the product.</p>
<p>TrueCrypt allows three kinds encryption containers. Files, non-boot operating system logical drives, and the boot device. Encrypting the all drives including the boot device &#8211; and entering the strong password to complete the encryption key during each system startup &#8211; is the best encryption protection because the <em>pagefile.sys</em> and any installation and configuration files that get created on the boot device and do reveal clues about sensitive data are found on the boot device. This a far more protection than TDE affords. Encrypting all drives including the boot device also carries the most overhead. Encrypting non-boot Volumes is attractive in a SQL Server direct attached storage configuration. The optimal SQL Server configuration with separate physical RAID arrays for data, log, and tempdb could be encrypted in this configuration. On a SQL Server I would expect the addition of the boot device to the encryption scheme would not add so much burden except at start-up since the IO on a database server is almost all about the data cache. (If a SQL Server is writing to the OS paging file it is already in performance hell. If you can&#8217;t fix that problem, I recommend you not mess with even open source, open license encryption solutions until you lay your hands on adequate memory.)</p>
<p>A SQL Server database device cannot be encrypted by encryption software. Instead, the .mdf<em> </em>and .ldf files are placed in already created encryption containers. If tempdb is to be encrypted place it in a TrueCrypt devices as well. Another subtle difference is that anyone that can read from a mounted TrueCrypt drive can get to the unencrypted data. Not the encrypted container created by TrueCrypt, that is definitely encrypted. I&#8217;m referring to the drive letter that shows up in Windows Explorer when a TrueCrypt container is mounted in the file system. Although, anyone with enough access to initiate such access would have a much easier time of it and a lower risk of being caught using the same credentials and T-SQL.</p>
<p>Unlike BitLocker, TrueCrypt can encrypt the boot drive or a file container.&nbsp; There is a nicely detailed <a href="http://www.tomshardware.com/reviews/bitlocker-truecrypt-encryption,2587.html" target="_blank">comparison of BitLocker and TrueCrypt at Tom&#8217;s Hardware</a>.</p>
<p><em>TrueCrypt exposes the decrypted data when the encrypted container is accessed through the mounted file system device.</em> This is an intended characteristic of transparent encryption. Once the mounting process acquires a drive letter, the drive must be secured at least as well as the SQL Server installation. If you are a Member of the Super Users Group on the machine, when you mount the container file, the permissions could allow other Super Users to access your containers.</p>
<p><em>TrueCrypt VHDs must be mounted and dismounted in the correct sequence.</em> For encrypted disk to protect the database, a commitment to detach the database with sensitive data or alternately shut down the SQL Server Service and dis-mount the TrueCrypt device when the database is not in use and then remount and re-attach (or restart as the case may be) on demand may be a good option. Easy enough to automate&#8230;</p>
<p><em>TrueCrypt-ed data can be viewed in clear text.</em> The TDE encrypted database is presented to everyone that connects to the database as unencrypted data. This is also true when the disk is encrypted except that in addition, decrypted data can also be exposed through the logical file system device as unencrypted data &#8211; for example if the file is copied using the logical drive to unencrypted storage the encryption is removed. The way to move encrypted TrueCrypt data is to un-mount the logical device and copy the encrypted container file. This does not integrate well with SQL Server. Better to have a good plan to start. To be safe from prying eyes, the logical device must have very restrictive (principle of least privilege) ACLs . With BitLocker a pre-boot password is required. With TrueCrypt it may only mean that a file is mounted to the already running local system before the SQL Server can be started. Although TrueCrypt can also be configured to encrypt the boot disk &#8211; and would also require the pre-boot password in this context.</p>
<p><em>TrueCrypt cannot encrypt existing files.</em> Nor can it encrypt a SQL Server data file. Instead, the SQL Server data file must be placed inside the TrueCrypt created file container after it is mounted. When mounted, the encrypted file is assigned a logical drive letter and is used like any other drive. Care must be taken that the same drive letters are used for each device else the attach script will need to be edited before each use.</p>
<p><em>TrueCrypt is open source and free.</em> TDE is integrated with SQL Server. TrueCrypt container encryption does not use SQL Server in any way. In both cases the encryption algorithm, certificate and password are user specified. And in both cases the FIPs complaint AES encryption algorithms and SHA1 hashing algorithm are available for selection. (Why use anything else? You want to be compliant don&#8217;t you?)</p>
<p><em>TrueCrypt uses Intel&#8217;s </em><a href="http://www.intel.com/Assets/PDF/whitepaper/323587.pdf" target="_blank"><em>Advanced Encryption Standard New Instructions (AES-NI)</em></a><em> hardware acceleration.</em> By <a href="http://www.remkoweijnen.nl/blog/2011/03/11/aes-ni-benchmarks/" target="_blank">some accounts</a> AES-NI hardware acceleration is over 4x faster than without. No reason not to believe that even TDE is using the hardware acceleration although I do not see much propaganda to that effect. TrueCrypt identifies <a href="http://ark.intel.com/MySearch.aspx?AESTech=true" target="_blank">AES-NI capable CPUs</a> and allows enable/disable configuration of AES hardware acceleration.</p>
<p><em>TrueCrypt is not integrated with SQL Server.</em> I said this already. It deserves repeating because there are so many pros and cons to that condition. With TDE there is no intermediate step like mounting a file and starting the SQL Server as is required when a TrueCrypt file container is used. SQL Server can auto-starts with the OS as designed with TDE. TrueCrypt will prevent SQL server from starting and could result in a database being marked suspect if the service is able to start but the database file cannot be found. The TrueCrypt piece of the startup/shutdown process can be automated and can include the startup/shutdown of the SQL Server service <em>if</em> the automation user is able to start services.</p>
<p><em>TrueCrypt can prevent users with CONTROL of the SQL Server from overriding the encryption. </em>The password needed to mount the TrueCrypt device could, for example, belong to the data center operations group (Ops) and Ops could be excluded from CONTROL of the server and from access to the database.</p>
<p>With TDE you could use the EKM Cryptographic Provider (.dll) from an HSM. TDE&nbsp; with EKM in a configuration where the HSM administrator does not have access to database subnet or a login to the SQL server is the clear winner but the cost difference is very significant. The scenario where domain administrators do not control the SQL Server and the database administrators are not local administrators on the SQL Server box is almost achievable. (There is always a way for a local administrator to gain authorized access to a SQL Server. For this reason, it is better to entrust the key management&nbsp; to a group that has no elevated authority as a database user, as a local system user, or on the domain and all other ACLs of the database subnet.)</p>
<p><strong>As with my recommendation for TDE: if the SQL instance can work with an encrypted file system you may as well use it.&nbsp; The main costs are a CPU overhead that will never bother most SQL Servers,&nbsp; and the time the DBA and any external key store owners must invest to verify, document and test the various security configurations and restore scenarios.&nbsp;&nbsp;&nbsp; </strong></p>
<p><strong>T-SQL Encryption&nbsp; </strong></p>
<p>That VISA document above says to consider encrypting the data for defense in depth along with TDE. As if data value encryption had little or no protection to offer or was at most a supplemental option. I&#8217;m here to tell you that is 100% backwards! And the TDE documentation seems to agree with me. I want to take it one step farther and state that encryption efforts must be redoubled in scope and hardness and TDE can be used as the supplemental technology to protect the database data at rest when the SQL Server is down. If we don&#8217;t roll up our sleeves and do as has been advocated by security experts and damn soon, surfing the Internet is going to feel like a <a href="http://www.my-art-prints.co.uk/UK/fine-art-prints/-Michelangelo--Buonarroti-/The-Last-Judgement----Boat-of-Charon-from-Sistine-Chapel--section--7066002.html" target="_blank">ride on Charon&#8217;s boat</a>. To be clear, the TDE documentation gets it right. The first sentence of the article, &#8220;<a href="http://msdn.microsoft.com/en-us/library/bb934049.aspx" target="_blank">Understanding Transparent Data Encryption (TDE)</a>&#8221; states,</p>
<blockquote>
<p>You can take several precautions to help secure the database such as designing a secure system, encrypting confidential assets, and building a firewall around the database servers. &#8230;</p>
</blockquote>
<p>Whether the SQL Server supports TDE or file encryption must be used to protect the data files and the backups, the increase level of security possible with data value level encryption is far more than the net security benefit of TDE or encrypted files. Most security guidelines recommend using transparent encryption along with data value encryption of identified sensitive values.</p>
<p>Encrypting at the application layer provides the most protection al la <em>Translucent Data Encryption</em>. Accurately identifying personally identifiable information seem to be tricky as well. You just have to do your homework. Do you care if the primary key to the customer table is exposed as clear text as long as the name, address and&nbsp; or the news story BLOBS that are served up to all Internet users on demand? If you were dumb enough to build customer IDs that contain any meaningful tidbits &#8211; say a three letter prefix that can be used to group customers you just may have to encrypt the primary key to be secure. If all data access occurs by stored procedure then the encoding and decoding can pretty easily be done in the stored procedures, but I&#8217;m telling you this is almost for sure not the best way, even if it is better than not encrypting data.&nbsp; At least the rest of the application will not have to know anything about the encrypted data, but you still have that problem with a single principal responsible for the encryption hierarchy.</p>
<p>In summary, until the focus is turned toward security and away from compliance in lieu of security expect many a profitable company to give up your personally identifiable data unabated and unrequited but don&#8217;t expect them to tell you it happened.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/193/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/193/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/193/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=193&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/06/22/the-emperors-new-transparent-data-encryption/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
		<item>
		<title>Protecting Sensitive Data at Rest in SQL Azure</title>
		<link>http://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/</link>
		<comments>http://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/#comments</comments>
		<pubDate>Thu, 26 May 2011 13:23:16 +0000</pubDate>
		<dc:creator>bwunder</dc:creator>
				<category><![CDATA[Encryption Hierarchies]]></category>
		<category><![CDATA[Secure Data]]></category>
		<category><![CDATA[HASHBYTES()]]></category>
		<category><![CDATA[SQL Azure]]></category>

		<guid isPermaLink="false">https://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/</guid>
		<description><![CDATA[&#8220;Cloud computing is a model for enabling ubiquitous, convenient, on-demand network access to a shared pool of configurable computing resources (e.g., networks, servers, storage, applications, and services) that can be rapidly provisioned and released with minimal management effort or service &#8230; <a href="http://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=190&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>&#8220;Cloud computing is a model for enabling ubiquitous, convenient, on-demand network access to a shared pool of configurable computing resources (e.g., networks, servers, storage, applications, and services) that can be rapidly provisioned and released with minimal management effort or service provider interaction. This cloud model promotes availability and is composed of five essential characteristics, three service models, and four deployment models.&#8221;&nbsp; &#8211; <a href="http://csrc.nist.gov/publications/nistpubs/800-145/SP800-145.pdf" target="_blank">The NIST Definition of Cloud Computing</a> U.S. Department of Commerce National Institute of Standards and Technology (NIST)</p>
<p>The five characteristics:</p>
<ol>
<ol>
<ol>
<li>On-demand self-service
<li>Broad network access
<li>Resource pooling
<li>Rapid elasticity
<li>Measured Service </li>
</ol>
</ol>
</ol>
<p>The 3 service models:</p>
<ol>
<ol>
<ol>
<li>Software as a Service (SaaS)
<li>Platform as a Service (PaaS)
<li>Infrastructure as a Service (IaaS) </li>
</ol>
</ol>
</ol>
<p>The 4 deployment models</p>
<ol>
<ol>
<ol>
<li>Private
<li>Community
<li>Public
<li>Hybrid </li>
</ol>
</ol>
</ol>
<p>Also in January 2011, NIST published a draft &#8220;<a href="http://csrc.nist.gov/publications/drafts/800-144/Draft-SP-800-144_cloud-computing.pdf" target="_blank">Guidelines on Security and Privacy in Public Cloud Computing</a>&#8220;.&nbsp; 4 broad guidelines are expanded in some detail in this document.</p>
<ol>
<li>Carefully plan the security and privacy aspects of cloud computing solutions before<br />engaging them
<li>Understand the public cloud&nbsp; computing&nbsp; environment offered by the&nbsp; cloud provider and ensure that&nbsp; a cloud computing solution satisfies&nbsp; organizational security and privacy requirements.
<li>Ensure that the client-side computing environment meets organizational security and privacy requirements for cloud computing
<li>Maintain accountability over the privacy and security of data&nbsp; and applications implemented and deployed in public cloud computing environment </li>
</ol>
<p>Even at this highest level, the enormous distance that must be bridged to bring SQL Azure into the organizational security strategy should be obvious.</p>
<p>It can&#8217;t be that bad. Can it? Well maybe&#8230; at issue is the compatibility of internally developed custom code based on long standing organizational security decisions and a dynamic resource on a public network. The disparity is huge. Sounds likes an interface with some new avenues of exploit for the malicious user base to me. Most of the holes should be filled in&nbsp; few years. Just in time for the next wave&#8230;</p>
<p>Consider that SQL Azure:</p>
<ul>
<li>only knows SQL Authentication </li>
</ul>
<blockquote><p>Microsoft has long discouraged SQL Authentication because it is, well&#8230;, less secure. From the Books Online topic &#8220;<a href="http://msdn.microsoft.com/en-us/library/ms144228.aspx" target="_blank">Security Considerations for a SQL Server Installation</a>&#8221; the security best practice recommendation is unequivocal, &#8220;Require Windows Authentication for connections to SQL Server.&#8221;</p>
<p>The SQL Azure documentation&#8217;s Development: How-to Topics includes <a href="http://msdn.microsoft.com/en-us/library/ee336282.aspx" target="_blank">Guidelines for Connecting to SQL Azure Database</a> and several detailed documents for connecting to SQL Azure from a short list of Microsoft selected client application platforms. There is also a fairly detailed Technet document about &#8220;<a href="http://social.technet.microsoft.com/wiki/contents/articles/sql-azure-connection-security.aspx" target="_blank">SQL Azure Connection String Security</a>&#8220;.&nbsp; Another very important item for SQL Azure is the <a href="http://msdn.microsoft.com/en-us/library/wfc2t3az.aspx" target="_blank">.NET Protected Configuration Provider</a> used to encrypt the login and password in connection configuration files &#8211; e.i. web.config, app.config, etc &#8211; on the client. (see &#8220;<a href="http://social.technet.microsoft.com/wiki/contents/articles/sql-azure-connection-security.aspx" target="_blank">SQL Azure Connection Security</a>&#8221; for more on Protected Configurations including a custom provider when the SQL Azure client is Windows Azure.)</p>
<p>The biggest concern I have with SQL Authentication is shared logins (see below) The second most concerning issue is password attacks. I do not know if SQL Azure will deal with a brute force password attack. I threw bad password at the connection from SSMS 10 times. The connection failed every time but it let me retry with no lockout.</p>
</blockquote>
<ul>
<li>allows only 1 SQL Authenticated server level principal </li>
</ul>
<blockquote><p>not that there is much the server level principal needs to do:&nbsp; backups, firewall configuration, create databases and manage logins. Probably won&#8217;t be more than&#8230; oh&#8230; say 6 or 8 people in a typical organization with the keys to the car. Anybody that thinks that that is secure absolutely must speak with me about keeping their money in my bank account.</p>
</blockquote>
<ul>
<li>provides 2 Fixed Server Roles proxied through user roles in the master database </li>
</ul>
<blockquote><p>&#8220;Like the <code>securityadmin</code> role for an on-premise instance of SQL Server, the <code>loginmanager</code> role in SQL Azure Database is required in order to create logins.&#8221;</p>
<p>&#8220;The SQL Azure Database <code>dbmanager</code> role is similar to the <code>dbcreator</code> role for an on-premise instance of SQL Server.&#8221;</p>
<p>(I notice a slightly more exhaustive table that calls out some SQL Azure vs SQL Server differences in <a href="http://msdn.microsoft.com/en-us/library/ee336235.aspx" target="_blank">Managing Databases and Logins in SQL Azure</a>.)</p>
</blockquote>
<ul><!--EndFragment-->
<li>requires firewall configuration </li>
</ul>
<blockquote><p>Before the first user, the server principal, can access a SQL Azure instance, that user must open the IP address of that user&#8217;s connection in the SQL Azure Firewall &#8211; and any necessary steps to open the path from the user side of the connection must be completed.</p>
<p>SQL Azure is available only through port 1433 and only by TCP.</p>
<p>The <em>MicrosoftServices</em> firewall rule was already in place on my SQL Azure instance before I signed is as the server principal. I am able to add and remove this rule, however I am not able to ascertain the consequences of either action. Also, the documentation tells me to add a second application rule, &#8220;Allow Windows Azure&#8221; to use my SQL Azure instance with my Windows Azure services.</p>
</blockquote>
<pre style="width:691px;height:146px;" class="code">

<span style="color:blue;">select </span><span style="color:gray;">* </span><span style="color:blue;">from </span><span style="color:green;">sys</span><span style="color:gray;">.</span>firewall_rules

<span style="color:blue;">exec </span>sp_set_firewall_rule <span style="color:red;">N'MicrosoftServices'</span><span style="color:gray;">, </span><span style="color:red;">'0.0.0.0'</span><span style="color:gray;">, </span><span style="color:red;">'0.0.0.0'</span>

<span style="color:blue;">exec </span>sp_delete_firewall_rule <span style="color:red;">N'MicrosoftServices' </span>

<span style="color:red;"></span><span style="color:blue;">exec </span>sp_set_firewall_rule <span style="color:red;">N'Allow Windows Azure'</span><span style="color:gray;">, </span><span style="color:red;">'0.0.0.0'</span><span style="color:gray;">, </span><span style="color:red;">'0.0.0.0' </span>

<span style="color:red;"></span><span style="color:blue;">exec </span>sp_delete_firewall_rule <span style="color:red;">N'Allow Windows Azure'</span>
</pre>
<ul>
<li>does not support distributed transactions </li>
</ul>
<ul>
<li>cannot be used in SQL Server Replication </li>
</ul>
<blockquote>
<p>SQL Azure does provide Sync services.</p>
</blockquote>
<ul>
<li>does not allow impersonation or provide a local task scheduler or Service Broker </li>
</ul>
<blockquote>
<p>Impersonation by manipulating a scheduled task or handing work to a background process has long been an accepted way to circumvent security configuration for the on-premise SQL Server. Lesser privileged users to modify data in some table, the agent or broker picks up the data and executes a task restricted to higher privileged users: start a backup, add a login, TRUNCATE a table, etc. None of this will work with SQL Azure. More recently stored procedures could be marked WITH EXECUTE AS&nbsp; to allow code to impersonate a more entitled user. This implicit sharing of database users will work Unfortunately, explicitly sharing database users will also&nbsp; work&#8230;</p>
</blockquote>
<ul>
<li>backup is un-like the sunny SQL Server backup </li>
</ul>
<blockquote>
<p>To backup a database the CREATE DATABASE statement is used. BACKUP DATABASE is not supported. The options are, you can create a database copy on the local SQL Azure instance or on another SQL Azure instance.</p>
<p>Use the <strong>sys.dm_database_copies</strong> view to see the currently active copies&#8230; er&#8230; I mean backups. OK, I have copy o my database. But how do I back it up? And what does the restore look like?</p>
<p>A well defined strategy is needed and you don&#8217;t get many building blocks with SQL Azure. Watch for some 3rd party cloud ware&#8230;</p>
</blockquote>
<ul>
<li>Limited Cryptographic support </li>
</ul>
<blockquote>
<p>No Certificate store, no support for the SQL Server&#8217;s Encryption Hierarchy, no Transparent Data Encryption (TDE),&nbsp; no Cryptographic Providers,&nbsp; no EKM, and no CLR integration. Direct cryptographic support in SQL Azure looks pretty much limited to HASHBYTES and VARBINARY storage for already encrypted data.</p>
<p>You do have to load a key in order to access the instance, so some chance that key is used to protect data at rest, but I do not know is this is so or how it works.</p>
</blockquote>
<p><strong>Look ma, no cryptography!</strong></p>
<p>The state of SQL Azure cryptography may actually be good where it is. Waiting until data reaches the database to encrypt is too long anyway. The longer encryption is postponed the less certainty that the data is not compromised. Furthermore, the more user friendly the encryption &#8211; to wit TDE &#8211; the easier to circumvent intended data protection or discombobulate expected recoverability. And the encryption is not fully protective. TDE offers no protection from SQL injection, cross-site scripting or in-flight attacks like man-in-the-middle. A TDE restore to a development environment will still inappropriately expose sensitive data and could easily compromise the Database Encryption Key. As long as a user can get a connection to the database instance, the data is transparently available in unencrypted form. From the opposite view, loss of data due to a missing or forgotten key export or key export password only adds to the woes of a data center during a calamity. Perhaps better to risk a breach than to risk a mis-step due to the added complexity regardless of the database weather conditions? (I don&#8217;t really believe that but it is worth thinking about.)</p>
<p>From another perspective, threats to cloud hosted data are notably different than threats to local network hosted data; not that either scenario should leave you with any feeling other than the creeps.&nbsp; I really don&#8217;t know how a malicious cloud user behaves. Are there spiders crawling around the underlying infrastructure? Are there additional SQL Injection/cross site scripting benefits or risks. I do not know. I have a suspicion the cloud providers&#8217; are building risk profiles from the by now most established trails as you read.</p>
<p>My SQL Azure instance doesn&#8217;t know what a certificate or a database master key is so is not likely that the SaaS service model would expose TDE any time soon. More likely the encryption requirement, and ultimately privacy compliance from the cloud would demand the Platform-as-a-Service Paas or Infrastructure-as-a-service Iaas service model or perhaps SQL Azure will become able to store certificates. A reasonable common sense alternative would be to encrypt the data in the application- where it originates &#8211; and unencrypt the data in the locally hosted or Windows Azure application &#8211; only where it is needed in unencrypted form. Store the encrypted bytes in an appropriate VARBINARY typed column in SQL Server or SQL Azure. End of problem.</p>
<p>Windows Azure can store Services keys (.pfx &#8211; public+private) and Management keys (.cer &#8211; the public key only from a public+private asymmetric pair). (protecting the private key is of utmost importance.)</p>
<p>Compliance Standards such as <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402.pdf" target="_blank">FIPS 140-2</a>, the US standard for encryption certification or <a href="https://www.pcisecuritystandards.org/security_standards/documents.php" target="_blank">PCI-DSS</a>, the credit card industry standard for protecting sensitive data include explicit requirements for protecting sensitive data at rest. Unfortunately, the standards may be ineffective. Sony&#8217;s ongoing (is it unstoppable?) breach and the RSA breach lost sensitive data from apparently compliant systems. Due diligence is in order. Consideration of the standards is prudent, but ultimately protecting the data must be the objective.</p>
<p>T-SQL&nbsp; HASHBYTES() is a deterministic cryptographic hash function built from a block cipher &#8211; a randomly generated symmetric key. HASHBYTES() performs a a one way encryption or hash on the passed string parameter. The value is not intended to be decrypted. Block Ciphers are useful for authentication, data comparison and searching by digest (the hashed byte array output that provides a meaningless and 16 or 20 bytes values &#8211; depending on the hashing algorithm used). Using HASHBYTES() could eliminate much application logic that instead now uses the sensitive data directly.</p>
<p>Without a doubt the movement of sensitive data to public networks will increase demand for developers adept in current cryptography practices. The Technet article &#8220;<a href="http://social.technet.microsoft.com/wiki/contents/articles/sql-azure-connection-security.aspx" target="_blank">SQL Azure Connection Security</a>&#8221; includes best practices for writing secure applications and secure connection strings that use SQL Azure. There is quite a lot of information to be found concerning Windows Azure cryptography. The MSDN&#8217;s <a href="http://msdn.microsoft.com/en-us/library/ff934690.aspx" target="_blank">Security Resources for Windows Azure</a> is great place to begin to dig deeper as is the MSDN Windows Development <a href="http://msdn.microsoft.com/en-us/library/ee663293%28v=VS.85%29.aspx" target="_blank">Security</a> topic.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bwunder.wordpress.com/190/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bwunder.wordpress.com/190/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bwunder.wordpress.com/190/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bwunder.wordpress.com&amp;blog=16910711&amp;post=190&amp;subd=bwunder&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bwunder.wordpress.com/2011/05/26/protecting-sensitive-data-at-rest-in-sql-azure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ee536e504ab772d7e2a2d6907853c180?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">bwunder</media:title>
		</media:content>
	</item>
	</channel>
</rss>
