<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Laurentiu Cristofor's blog @microsoft.com : SQL Server - cryptography</title><link>http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx</link><description>Tags: SQL Server - cryptography</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>New attack on AES-256</title><link>http://blogs.msdn.com/lcris/archive/2009/10/14/new-attack-on-aes-256.aspx</link><pubDate>Thu, 15 Oct 2009 00:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9907378</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/9907378.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=9907378</wfw:commentRss><description>&lt;P&gt;A new attack improves significantly on previous attacks against AES-256, see: &lt;A href="http://schneier.com/crypto-gram-0908.html#8"&gt;http://schneier.com/crypto-gram-0908.html#8&lt;/A&gt;. This doesn't mean that AES-256 is broken yet, but the surprising bit here is that AES-128 is not susceptible to this particular attack. Don't panic if you are using AES-256&amp;nbsp;and&amp;nbsp;read&amp;nbsp;Bruce Schneier's commentary carefully - for example, note that the attack is against a 10 round AES-256, while standard implementations use 14 rounds.&lt;/P&gt;
&lt;P&gt;It's interesting to see that the strength of AES-256 is eroded by new attacks, but AES-128 doesn't suffer from them yet. It's another example that larger (or more expensive) isn't necessarily also better.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9907378" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>Can encryption make you more vulnerable?</title><link>http://blogs.msdn.com/lcris/archive/2008/02/11/can-encryption-make-you-more-vulnerable.aspx</link><pubDate>Tue, 12 Feb 2008 03:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7629291</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/7629291.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=7629291</wfw:commentRss><description>&lt;P&gt;A &lt;A class="" href="http://security.itworld.com/4341/encryption-makes-you-more-vulnerable-080211/page_1.html" mce_href="http://security.itworld.com/4341/encryption-makes-you-more-vulnerable-080211/page_1.html"&gt;recent article&lt;/A&gt; brings up this question and argues that encrypting data at rest&amp;nbsp;can open the door to a new range of security and usability problems. Speaking only of the security aspects, I both agree and disagree,&amp;nbsp;so&amp;nbsp;I'd like to add a few comments on this topic.&lt;/P&gt;
&lt;P&gt;I think that the article makes a very good point that&amp;nbsp;represents a great truth about security: the features you build to protect against attackers could end up being used by the attackers against you - this is&amp;nbsp;the double-edged aspect of security. Once&amp;nbsp;a system is compromised and the attacker gets&amp;nbsp;to control&amp;nbsp;it, he can use its defenses against the lawful users. This is not a new idea, but it is one that can be easily forgotten when adding new security features.&lt;/P&gt;
&lt;P&gt;That being said, I don't think that the scenario presented in the article about ransoming data is a new or very interesting scenario. Here are the reasons why:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;- An attacker can use his own encryption routines to encrypt the data - it doesn't matter if the compromised system had any encryption capabilities. Malware with the capability to encrypt data has existed for years and cyber-criminals are known to be proficient at using encryption to protect their data. Thus, ransoming is not really a new threat - it just appears new to those that also see encryption as a new technology.&lt;BR&gt;- Ransoming could only work in a database system that lacks a disaster recovery procedure. Data loss is an ever-present threat for databases - even if ransoming would be new, it would be addressed by the same measures that address an old threat - data/key backups.&lt;BR&gt;- The weakest link in ransoming is the ransom collection - that's where the attacker exposes himself - this makes ransoming not very tempting.&lt;BR&gt;- Ransoming is also a bad idea because it tells the system owner that his system has been breached and gives him a chance to close that breach.&lt;BR&gt;- If an attacker can get access to data worth ransoming, it is more easy for him to make money from selling it and keeping his access secret than by attempting to ransom it.&lt;/P&gt;
&lt;P&gt;However, I &lt;STRONG&gt;do&lt;/STRONG&gt; think that encryption can make you more vulnerable - it can do that by giving people a false sense of security&amp;nbsp;if they think that just by having data encrypted,&amp;nbsp;it&amp;nbsp;becomes&amp;nbsp;secure. I went in a bit more detail about this idea&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/11/30/who-needs-encryption.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/11/30/who-needs-encryption.aspx"&gt;here&lt;/A&gt;, but the&amp;nbsp;point is that deploying encryption is not only about encrypting data but about carefully considering how the data will be accessed &lt;STRONG&gt;and&lt;/STRONG&gt; about securing that access -&amp;nbsp;sadly, the latter part&amp;nbsp;is where the security of most applications fails. Encryption addresses well certain scenarios such as stealing data at rest, but those scenarios do not necessarily represent how most data&amp;nbsp;is getting compromised today.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7629291" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: How to debug errors in code that does encryption</title><link>http://blogs.msdn.com/lcris/archive/2008/01/31/sql-server-2005-how-to-debug-errors-in-code-that-does-encryption.aspx</link><pubDate>Thu, 31 Jan 2008 23:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7358699</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/7358699.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=7358699</wfw:commentRss><description>&lt;P&gt;Encryption builtin functions in SQL Server have no known issues and, if used properly, they will produce the expected results. However, if they are used incorrectly, it can be hard to figure out what exactly is the problem, so in this post I am going to collect some hints about what to look for in the malfunctioning code.&lt;/P&gt;
&lt;P&gt;There are two main types of encryption code related issues that I have seen popping up in forums; they usually are described as "encryption errors", which is not what they really are.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Issue 1:&amp;nbsp;Corruption of encrypted value&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This issue happens when the output of encryption is corrupted when stored or passed around by code. This happens because the encryption blob is truncated during a conversion or because the column in which it is stored is shorter or has the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms187403.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms187403.aspx"&gt;ANSI_PADDING&lt;/A&gt; option set to OFF. For determining the size of a column that should hold encrypted data, see &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2008/01/11/sql-server-2005-how-to-determine-the-size-of-a-column-that-will-hold-encrypted-data.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2008/01/11/sql-server-2005-how-to-determine-the-size-of-a-column-that-will-hold-encrypted-data.aspx"&gt;this post&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Symptom:&lt;/STRONG&gt; Decryption of corrupted encryption blob will return NULL.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;How to debug this?&lt;/STRONG&gt; Print the output of the encryption function, before it is processed in any way - this is the original encrypted blob value. Then also print the blob after each conversion or assignment; if it is inserted into a column, select back the inserted value. Any difference from the original blob value will indicate where the error happened. Most often, you don't even need to do a byte by byte comparison and you can instead just compare the lengths of the blob at different stages - you can get the length&amp;nbsp;using the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms173486.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms173486.aspx"&gt;datalength()&lt;/A&gt; builtin.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Issue 2: Incorrect conversion of the decrypted value&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This issue happens when encrypting a Unicode string and when later, after decryption, we try to&amp;nbsp;convert the binary&amp;nbsp;decryption output to a non-Unicode value. Or vice-versa. There is nothing wrong with the encryption or decryption in this case, which can be determined by following the debugging steps for Issue 1. It is easy to get this issue because the difference between &lt;STRONG&gt;n&lt;/STRONG&gt;varchar (Unicode) and varchar (ASCII) is the single letter &lt;EM&gt;&lt;STRONG&gt;n&lt;/STRONG&gt;&lt;/EM&gt;, which you may fail to type in.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Symptom:&lt;/STRONG&gt; Decrypted data is displayed as garbage.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;How to debug this?&lt;/STRONG&gt; Compare the type of the data you compress and verify that the decompressed blob is appropriately converted back to that type.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7358699" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: A great post by Aaron Morton about using MARS to access opened keys</title><link>http://blogs.msdn.com/lcris/archive/2008/01/17/sql-server-2005-a-great-post-by-aaron-morton-about-using-mars-to-access-opened-keys.aspx</link><pubDate>Fri, 18 Jan 2008 09:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7146652</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/7146652.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=7146652</wfw:commentRss><description>&lt;P&gt;&lt;A class="" href="http://www.thelastpickle.com/" mce_href="http://www.thelastpickle.com/"&gt;Aaron Morton&lt;/A&gt; has a &lt;A class="" href="http://www.thelastpickle.com/2008/01/17/how-to-read-encrypted-data-and-the-problem-of-mars/" mce_href="http://www.thelastpickle.com/2008/01/17/how-to-read-encrypted-data-and-the-problem-of-mars/"&gt;very interesting post and demo&lt;/A&gt; that show how MARS can be used to access keys temporarily opened by a procedure. This is a must-read for anyone that is interested in implementing custom restrictions around the use of encryption keys.&amp;nbsp;Some time ago, I wrote a &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/01/13/sql-server-2005-example-for-how-to-allow-a-user-to-encrypt-but-not-decrypt.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/01/13/sql-server-2005-example-for-how-to-allow-a-user-to-encrypt-but-not-decrypt.aspx"&gt;post&lt;/A&gt; about restricting the use of an encryption key just for encryption. Aaron's demo goes further and demonstrates a pitfall if one would attempt to restrict the use of an encryption key for specific data decryption. The issue happens because MARS allows interleaving around SELECT statements, and a way to prevent it is to use auto-decryption routines, which open the key in the context of the transaction rather than the session context.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7146652" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: Why you should not encrypt data with certificates</title><link>http://blogs.msdn.com/lcris/archive/2008/01/11/sql-server-2005-why-you-should-not-encrypt-data-with-certificates.aspx</link><pubDate>Fri, 11 Jan 2008 23:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7080575</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/7080575.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=7080575</wfw:commentRss><description>&lt;P&gt;I often recommended to only encrypt data in SQL Server using symmetric keys and to reserve the use of asymmetric encryption for protection of symmetric keys and for signing.&amp;nbsp;In this post, I will go in more detail about why asymmetric encryption is not appropriate for protecting data.&lt;/P&gt;
&lt;P&gt;There are three reasons why asymmetric encryption is not suitable for encrypting data:&lt;/P&gt;
&lt;P&gt;(1) Asymmetric encryption is much slower than symmetric encryption.&lt;/P&gt;
&lt;P&gt;(2) For small data like SSNs and CCNs, asymmetric encryption will result in a blob that will be significantly larger than what you would get from symmetric encryption - about 2 times larger or more.&lt;/P&gt;
&lt;P&gt;(3) While for symmetric encryption, the largest data that can be compressed is around 8000 bytes, because of limitations in the SQL Server encryption interfaces,&amp;nbsp;for asymmetric key encryption, the limit is much smaller and is due to limitations of the&amp;nbsp;technology itself. The limits are: a 512 bit RSA key can encrypt up to 53 bytes, a 1024 bit key can encrypt&amp;nbsp;up to 117 bytes, and a 2048 bit key can encrypt&amp;nbsp;up to 245 bytes (reminder: in SQL Server, both certificates and asymmetric keys are wrappers over RSA keys).&lt;/P&gt;
&lt;P&gt;So, by using asymmetric encryption to encrypt data,&amp;nbsp;you&amp;nbsp;pay additional&amp;nbsp;time&amp;nbsp;and space&amp;nbsp;costs, and on top of that you are limited&amp;nbsp;about how large a piece of data you can encrypt.&lt;/P&gt;
&lt;P&gt;All these points are unrelated to the actual implementation of the algorithms; they are simply derived from the properties of RSA encryption, which is the only form of asymmetric encryption supported in SQL Server 2005.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Related to (3), also see &lt;A class="" href="http://blogs.msdn.com/yukondoit/archive/2005/11/24/496521.aspx" mce_href="http://blogs.msdn.com/yukondoit/archive/2005/11/24/496521.aspx"&gt;this post&lt;/A&gt; and &lt;A class="" href="http://groups.google.com/group/microsoft.public.sqlserver.security/browse_thread/thread/29fa470a60d03fc9/f8034886d9da6420?hl=en&amp;amp;lnk=gst&amp;amp;q=encryption+size#f8034886d9da6420" mce_href="http://groups.google.com/group/microsoft.public.sqlserver.security/browse_thread/thread/29fa470a60d03fc9/f8034886d9da6420?hl=en&amp;amp;lnk=gst&amp;amp;q=encryption+size#f8034886d9da6420"&gt;this post&lt;/A&gt;, which contain information that can help you determine the limits for RSA keys of different sizes than I enumerated above (or you can just determine those limits by trial and error).&lt;/P&gt;
&lt;P mce_keep="true"&gt;Also related is this post about the &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2007/10/04/sql-server-2005-a-note-about-the-use-of-certificates.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2007/10/04/sql-server-2005-a-note-about-the-use-of-certificates.aspx"&gt;use of certificates&lt;/A&gt; in SQL Server and this post about the difference between &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/03/13/550904.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/03/13/550904.aspx"&gt;certificates and asymmetric keys&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7080575" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: How to determine the size of a column that will hold encrypted data</title><link>http://blogs.msdn.com/lcris/archive/2008/01/11/sql-server-2005-how-to-determine-the-size-of-a-column-that-will-hold-encrypted-data.aspx</link><pubDate>Fri, 11 Jan 2008 22:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7078373</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/7078373.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=7078373</wfw:commentRss><description>&lt;P&gt;This issue has been addressed before on forums, but with the heavy traffic, it can be hard to find the proper post. So, I'll provide some explanations here as well.&lt;/P&gt;
&lt;P&gt;Note:&amp;nbsp;This article is written with symmetric encryption in mind, but the actual technique would work for&amp;nbsp;asymmetric encryption&amp;nbsp;too.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When encrypting a piece of data, the encrypted version will always be larger than the original data. This happens because encryption doesn't compress the data and, in addition to that, SQL Server prefixes the encrypted blob with some data, the most significant being the &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/07/06/658409.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/07/06/658409.aspx"&gt;GUID of the symmetric key used for encryption&lt;/A&gt;. It is possible to compute in advance what will be the length of the encryption for a given piece of data, but rather than working with a formula, a safer and simpler method is to just perform the encryption using EncryptByKey and pass the result to the datalength() builtin function. While the contents of the encrypted blob are non deterministic due to the use of a random IV, the length of the blob will be constant if the same&amp;nbsp;method is used for encryption; in fact, the length of the encryption doesn't even depend on the data that is encrypted - it only depends on the length of that data.&lt;/P&gt;
&lt;P&gt;So, when trying to decide the size of a column that is supposed to hold encrypted data, you only need to determine, as you would normally do in the absence of encryption, what is the maximum size of unencrypted data that you are willing to store; once you know this, you can just generate a piece of data of that size, encrypt it, and get the length of the result using datalength()&amp;nbsp;- that will be the maximum length that you should define for the encrypted column.&lt;/P&gt;
&lt;P&gt;Although I remember several posts on this topic, I could only find one with a quick search. Fortunately, it's a very good post from &lt;A class="" href="http://blogs.msdn.com/raulga/" mce_href="http://blogs.msdn.com/raulga/"&gt;Raul&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=908990&amp;amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=908990&amp;amp;SiteID=1&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Update (later same day):&lt;/STRONG&gt; This is the &lt;A class="" href="http://blogs.msdn.com/yukondoit/archive/2005/11/24/496521.aspx" mce_href="http://blogs.msdn.com/yukondoit/archive/2005/11/24/496521.aspx"&gt;original post&lt;/A&gt; from Raul that explains in more detail the formula you could use to determine the length of an encrypted blob without actually encrypting. The blog on which it is posted has been discontinued, but there are some good posts made to it that are worth checking out. And if you are wondering about the blog name, Yukondoit was one of the slogans used on T-shirts around the launch of SQL Server 2005, whose code name was&amp;nbsp;"Yukon".&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7078373" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: Restoring the backup of a database that uses encryption</title><link>http://blogs.msdn.com/lcris/archive/2007/11/16/sql-server-2005-restoring-the-backup-of-a-database-that-uses-encryption.aspx</link><pubDate>Fri, 16 Nov 2007 22:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6314934</guid><dc:creator>lcris</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/lcris/comments/6314934.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=6314934</wfw:commentRss><description>&lt;P&gt;I have addressed this topic in previous threads and comments (&lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/07/08/sql-server-2005-a-look-at-the-master-keys.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/07/08/sql-server-2005-a-look-at-the-master-keys.aspx"&gt;here&lt;/A&gt;, &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/09/30/475822.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/09/30/475822.aspx"&gt;here&lt;/A&gt;,&amp;nbsp;and&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/lcris/archive/2007/11/14/sql-server-2005-how-to-recover-when-the-service-master-key-smk-is-not-accessible.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2007/11/14/sql-server-2005-how-to-recover-when-the-service-master-key-smk-is-not-accessible.aspx"&gt;here&lt;/A&gt;, for example), both on this blog&amp;nbsp;and on various forums, but it looks like when you need the answer, it can be hard to dig out. So I'm hoping that&amp;nbsp;by placing these steps in a dedicated post, they will become easier to find.&lt;/P&gt;
&lt;P&gt;When you restore a database that uses encryption features, there is only one thing you need to take care off - if the database master key (DbMK)&amp;nbsp;needs a service master key (SMK)&amp;nbsp;encryption,&amp;nbsp;you need to regenerate this encryption.&amp;nbsp;Note that this encryption is&amp;nbsp;made&amp;nbsp;by default when you create the DbMK, but it may be intentionally dropped, if you want&amp;nbsp;tighter control of&amp;nbsp;access to the encrypted data. Anyway, if you did have such SMK encryption for the DbMK, the steps to regenerate it are the following:&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms174433.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms174433.aspx"&gt;OPEN MASTER KEY&lt;/A&gt; DECRYPTION BY PASSWORD = 'password'&lt;BR&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms186937.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms186937.aspx"&gt;ALTER MASTER KEY&lt;/A&gt; ADD ENCRYPTION BY SERVICE MASTER KEY&lt;BR&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms188387.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms188387.aspx"&gt;CLOSE MASTER KEY&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;That's it - the database encryption features should now work as when the backup was taken. Also note that it doesn't matter if you restore the database on the server where the backup was taken or elsewhere. The only thing that matters for this procedure&amp;nbsp;is that you know one of the passwords protecting&amp;nbsp;the DbMK (yes, there can be more than one - see &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/09/23/473464.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/09/23/473464.aspx"&gt;this post&lt;/A&gt;).&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6314934" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: How to recover when the service master key (SMK) is not accessible</title><link>http://blogs.msdn.com/lcris/archive/2007/11/14/sql-server-2005-how-to-recover-when-the-service-master-key-smk-is-not-accessible.aspx</link><pubDate>Thu, 15 Nov 2007 00:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6231099</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/6231099.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=6231099</wfw:commentRss><description>&lt;P&gt;I wrote earlier today a reply on this topic on the public forums, but now that I checked, the reply appears to have got lost, although I still entertain the hope it may only have got delayed and will appear there in 24 hours. Anyway, this is the reason why I prefer to write longer posts on this blog rather than on forums - they don't get lost as easily, either due to forum bugs or to threads going old and forgotten.&lt;/P&gt;
&lt;P&gt;So, the problem I want to discuss is about what can be done if the SMK, for some reason or another, becomes inaccessible. I had previously touched on this in a &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/04/10/572678.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/04/10/572678.aspx"&gt;previous article&lt;/A&gt;, but this time I want to&amp;nbsp;go in&amp;nbsp;more details.&lt;/P&gt;
&lt;P&gt;First, let's look into why such a thing could happen. For the SMK to become inaccessible, something out of the ordinary must happen - either a disk corruption, which would most likely impact more data than just the SMK, or a change in the system configuration that would invalidate the DPAPI encryption of the SMK, or some other problem that I don't know yet about - maybe some obscure software error we have yet to see. In the years since SQL Server 2005 has shipped, I have&amp;nbsp;seen only one case where the SMK became inaccessible and the reason for that was that the master database had been restored on a different system, such that the DPAPI encryptions of the SMK were invalid - even this issue had happened in an internal testing environment and not in a real production scenario. So, there is a&amp;nbsp;way you can realistically end up with an inaccessible SMK, but&amp;nbsp;it is not an ordinary scenario.&lt;/P&gt;
&lt;P&gt;The following discussion assumes that something happened to the SMK and just to the SMK&amp;nbsp;- I don't make any assumption on what happened, I just assume that this SMK&amp;nbsp;problem is not compounded by the existence of other problems affecting other areas than the SMK. Also, before launching yourself into a recovery operation, make sure that you can at least recover from that - you should backup your database files such that you don't get in a worse situation than when you started.&lt;/P&gt;
&lt;P&gt;Let's review the encryption hierarchy around the SMK, because this helps us understand what we need to fix. On one hand, the SMK has two DPAPI encryptions:&amp;nbsp;using the service account and the machine account credentials, so for the SMK to become inaccessible, the system must be incapable of decrypting &lt;STRONG&gt;both&lt;/STRONG&gt; these encryptions (also see&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/09/30/475822.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/09/30/475822.aspx"&gt;this article&lt;/A&gt;). On the other hand, the SMK is used for encrypting three different classes of entities: credentials, linked server passwords, and database master keys (also see &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/04/10/572678.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/04/10/572678.aspx"&gt;this article&lt;/A&gt;). This information allows us to determine what must have happened for the SMK to become inaccessible -&amp;nbsp;both DPAPI encryptions&amp;nbsp;must be undecryptable,&amp;nbsp;and what is the effect of the SMK becoming inaccessible -&amp;nbsp;credentials, linked server passwords, and database master keys&amp;nbsp;become undecryptable by the system. (If you're reading this article while working with future versions of SQL Server, keep in mind that the list of entities encrypted by the SMK may change.) We can also use this information to verify that the SMK is indeed inaccessible; to do this, we could&amp;nbsp;attempt to use the SMK&amp;nbsp;to encrypt a new entity, such as a new database master key (in a database created just for the purpose of this test) or a credential secret - if such operations fail, a final test can be made by attempting to regenerate the SMK - if this fails as well, it becomes pretty clear that the problem we're dealing with is related to the SMK.&lt;/P&gt;
&lt;P&gt;So, the best fix for the problem would be to fix the DPAPI encryptions of the SMK.&amp;nbsp;We can do this in two ways:&lt;/P&gt;
&lt;P&gt;(A) If&amp;nbsp;we have a backup of the SMK (this is why such backups are recommended), then&amp;nbsp;we can restore that backup.&amp;nbsp;We will need to use the FORCE option because the current SMK cannot be decrypted. This should fix our SMK&amp;nbsp;and we can check this using the tests I mentioned above.&lt;/P&gt;
&lt;P&gt;(B) If we don't have a backup of the SMK and if the issue happened because we moved the databases from a machine to another and if that machine is still available, then all is not lost. We can either make a backup of the SMK on the original machine (if it still has the database system on it) and then apply it according to the (A) solution, or we can copy the database files back to the original machine, to make such a backup. Either way, the purpose would be that we want to make&amp;nbsp;a backup of the SMK and then restore it on the machine that has the SMK problem.&lt;/P&gt;
&lt;P&gt;If neither of these apply - we don't have a backup of the SMK and there is no original system where we can make one, then we're in some trouble. Not a lot, but we'll have some non-trivial cleanup to do. So let's assess the situation in this case: we don't have a SMK backup and we can't access the SMK, so let's face it: we've lost the SMK; this means we've lost the credentials and linked server passwords encrypted by the SMK - we'll need to regenerate all of these with help from whoever created them. The good part is that we didn't loose the database master keys - unless we managed to also forget the passwords protecting them - that would be quite unfortunate. Because DbMKs are always encrypted by a password, besides a default SMK encryption, the latter can always be fixed as long as we know the DbMK password. So, let's enumerate the steps we need to follow to cleanup the situation:&lt;/P&gt;
&lt;P&gt;(a) We need to regenerate the SMK, because&amp;nbsp;the current one is now unrecoverable. So we need to use REGENERATE and the FORCE option to create a new and valid SMK.&lt;/P&gt;
&lt;P&gt;(b) For each&amp;nbsp;DbMK that had a SMK encryption, we need to open the DbMK using its password encryption and then we need to re-encrypt the DbMK using the SMK. This is the same kind of step that we would need to do when moving a database from one system to another. Here is the TSQL for it:&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms174433.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms174433.aspx"&gt;OPEN MASTER KEY&lt;/A&gt; DECRYPTION BY PASSWORD = 'password'&lt;BR&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms186937.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms186937.aspx"&gt;ALTER MASTER KEY&lt;/A&gt; ADD ENCRYPTION BY SERVICE MASTER KEY&lt;BR&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms188387.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms188387.aspx"&gt;CLOSE MASTER KEY&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;(c) We need now to recreate all credentials and linked server passwords.&lt;/P&gt;
&lt;P&gt;The steps above should bring our database system back to normal operational state as far as the SMK is concerned. It's going to be painful to do (c), but that's the price to pay because we didn't have a SMK backup. (b) and&amp;nbsp;(c)&amp;nbsp;need to be done after (a) because&amp;nbsp;they need a valid SMK, but their order can be swapped, i.e. we can do (c) before (b).&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6231099" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: A note about the use of certificates</title><link>http://blogs.msdn.com/lcris/archive/2007/10/04/sql-server-2005-a-note-about-the-use-of-certificates.aspx</link><pubDate>Fri, 05 Oct 2007 06:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5285355</guid><dc:creator>lcris</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lcris/comments/5285355.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=5285355</wfw:commentRss><description>&lt;P&gt;To avoid any confusion, this post is not about the use of certificates for securing the communication between a client machine and the server; instead, this&amp;nbsp;refers&amp;nbsp;to the use of certificates created via the CREATE CERTIFICATE DDL.&lt;/P&gt;
&lt;P&gt;I am prompted in writing this post by a recent question I just saw, which I know I answered&amp;nbsp;many times before, but I now realized I never wrote about it here. The question is simply around the differences between how certificates are used elsewhere and how certificates are used in SQL Server. I'll answer this question here and I'll add some additional information and references, which I hope you will find useful.&lt;/P&gt;
&lt;P&gt;The main use of certificates that we are familiar with from daily browsing activities is about the signing of code on the Internet. This signing is done as a way to prove the authenticity of a piece of software, because a signature can help&amp;nbsp;validate the manufacturer of a piece of software. I say &lt;EM&gt;"can help"&lt;/EM&gt;, because not everyone checks carefully the details of a digital signature to ensure it is indeed&amp;nbsp;trustworthy. For more details around this type of use scenario, you can look into &lt;A class="" href="http://en.wikipedia.org/wiki/Public_key_infrastructure" mce_href="http://en.wikipedia.org/wiki/Public_key_infrastructure"&gt;PKI - Public Key Infrastructure&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Certificates can be used in many ways, because asymmetric key encryption is a&amp;nbsp;very powerful&amp;nbsp;tool, so, when certificates were introduced in SQL Server, one of&amp;nbsp;the design goals was to build a generic store for encryption keys, without putting any unnecessary restrictions on their use. Because of this, expiry settings or certificate revocation&amp;nbsp;are not enforced.&amp;nbsp;SQL Server&amp;nbsp;just regards the certificate as a key container and&amp;nbsp;keeps track of all of its settings, but&amp;nbsp;it doesn't restrict its use - it is up to&amp;nbsp;you to decide&amp;nbsp;what&amp;nbsp;to do with&amp;nbsp;it. The main use scenarios within SQL Server do not require any restrictions, so the only thing that&amp;nbsp;is done is to give some warnings at the time the certificate is imported - if it was expired, for example. I should also note that features within SQL Server may do additional checks on a certificates's settings: for example, the Service Broker feature does check for expiration of its certificates. If your intent is to plug into PKI, that is also possible through CLR.&lt;/P&gt;
&lt;P&gt;So, what are the main use scenarios for having certificates in SQL Server? Here they are:&lt;/P&gt;
&lt;P&gt;1. You can use certificates to sign T-SQL code.&lt;BR&gt;2. You can use certificates to encrypt symmetric encryption keys or small pieces of data.&lt;/P&gt;
&lt;P&gt;Let's discuss these a little. Signing T-SQL code is the most powerful security feature shipped with SQL Server 2005 (my opinion, of course, as is any other subjective evaluation you may read on this blog). But, really, think about it: signing allows you to grant permissions to code instead of granting them to principals calling the code -&amp;nbsp;this opens a world of possibilities in terms of how you can manage permissions and how you can restrict access to objects. So that you don't get any wrong idea at my enthusiasm for this feature, I will add that I made no significant contributions to it, so I am not trying to push forward my work ;) For a simple example of the things you can do with signing, you can have a look at this &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/01/13/512829.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/01/13/512829.aspx"&gt;example&lt;/A&gt;. &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/01/13/512829.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/01/13/512829.aspx"&gt;Raul's blog&lt;/A&gt;&amp;nbsp;has additional examples and information on this feature.&lt;/P&gt;
&lt;P&gt;You can also use special builtin functions (SignByCert)&amp;nbsp;to sign your own data, but unfortunately, due to&amp;nbsp;a bug, their implementation uses the MD5 algorithm instead of the SHA1 algorithm used&amp;nbsp;in T-SQL signing, so they are not interoperable - you cannot use these functions to simulate the internal code signing, so that you could manually compute the signature of a function, for example; instead, you would need to actually create the function and sign it via ADD SIGNATURE, then read the signature blob from the system catalogs.&lt;/P&gt;
&lt;P&gt;The second use of certificates is quite natural for an encryption key&amp;nbsp;- we would definitely&amp;nbsp;like to encrypt something with it. The reason why certificates are more convenient to use for protecting symmetric keys than other methods is simply because they can be backed up individually. This also gives them an edge over their cryptographic sibling - the asymmetric keys. For a discussion of why there are two objects encapsulating RSA keys in SQL Server, see this &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2006/03/13/550904.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2006/03/13/550904.aspx"&gt;explanation&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Some people think that certificate encryption is inherently safer than symmetric key encryption - it is not. There is no significant gain in strength from securing your data with an RSA key instead of using an AES one, as long as you are using equivalent key lengths - not equal, but&amp;nbsp;equivalent - more on this below. The RSA encryption is slower than any symmertric key encryption and its larger key length is simply due to&amp;nbsp;it being a fundamentally different technique and requiring longer key lengths than symmetric key algorithms, to offer the same strength of encryption. For a&amp;nbsp;discussion of key lengths and a comparison of key lengths across symmetric and asymmetric algorithms,&amp;nbsp;you can check&amp;nbsp;this &lt;A class="" href="http://en.wikipedia.org/wiki/Key_length" mce_href="http://en.wikipedia.org/wiki/Key_length"&gt;article&lt;/A&gt;&amp;nbsp;or a cryptography book. This means that certificates are not appropriate for data encryption and their use should be restricted to the encryption of symmetric keys (which are small enough that the encryption performance is not a concern) and to the application of digital signatures (when the key is only used to encrypt what is basically a hash of the signed data, hence, again,&amp;nbsp;performance is not a concern&amp;nbsp;given that&amp;nbsp;the length of a&amp;nbsp;SHA1 hash value&amp;nbsp;is 20 bytes/160 bits).&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5285355" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2008: Transparent data encryption feature - a quick overview</title><link>http://blogs.msdn.com/lcris/archive/2007/10/03/sql-server-2008-transparent-data-encryption-feature-a-quick-overview.aspx</link><pubDate>Thu, 04 Oct 2007 02:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5270262</guid><dc:creator>lcris</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/lcris/comments/5270262.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=5270262</wfw:commentRss><description>&lt;P&gt;I have kept silent on this feature while it was being developed, but as it has now&amp;nbsp;been publicly&amp;nbsp;advertised in various ways (being mentioned &lt;A class="" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2138363&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2138363&amp;amp;SiteID=1"&gt;here&lt;/A&gt;, &lt;A class="" href="http://download.microsoft.com/download/a/c/d/acd8e043-d69b-4f09-bc9e-4168b65aaa71/SQL2008_ProductOverview.doc" mce_href="http://download.microsoft.com/download/a/c/d/acd8e043-d69b-4f09-bc9e-4168b65aaa71/SQL2008_ProductOverview.doc"&gt;here&lt;/A&gt;, &lt;A class="" href="http://www.pcworld.com/article/id,137558-pg,1/article.html" mce_href="http://www.pcworld.com/article/id,137558-pg,1/article.html"&gt;here&lt;/A&gt;, and &lt;A class="" href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&amp;amp;articleId=9037060&amp;amp;intsrc=hm_list" mce_href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&amp;amp;articleId=9037060&amp;amp;intsrc=hm_list"&gt;here&lt;/A&gt;, for example), I think it is probably time to write a bit about it. Given that my posts so far have covered SQL Server 2005, I'll point out again that this is a SQL Server &lt;STRONG&gt;2008&lt;/STRONG&gt; feature!&lt;/P&gt;
&lt;P&gt;The transparent data encryption feature in the next SQL Server version is the last feature I worked on while I was in the SQL Server security team, before my &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2007/04/21/transition.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2007/04/21/transition.aspx"&gt;move&lt;/A&gt; to&amp;nbsp;MSR. Transparent data encryption is quite a long name, so I'll just refer to it as TDE from now on.&lt;/P&gt;
&lt;P&gt;TDE addresses&amp;nbsp;two of the encryption requests we have received most often&amp;nbsp;from forum questions and from discussions with customers:&lt;/P&gt;
&lt;P&gt;(1) a way to&amp;nbsp;enable data encryption without affecting applications that consumed that data (for an idea of what problems are raised&amp;nbsp;when encrypting a&amp;nbsp;table column&amp;nbsp;in a database, see this&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/12/22/506931.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/12/22/506931.aspx"&gt;post&lt;/A&gt;)&lt;BR&gt;(2) a way to encrypt an entire database&lt;/P&gt;
&lt;P&gt;TDE addresses both these requests by providing a database level encryption feature. Both&amp;nbsp;the data and the log files of a database are encrypted on disk and get decrypted when they are read into memory. This makes encryption really transparent to applications. Because database applications attempt to minimize their I/O (a costly operation),&amp;nbsp;tying encryption and decryption&amp;nbsp;to I/O&amp;nbsp;will also take advantage of existing application design optimizations to minimize the performance impact of encryption.&lt;/P&gt;
&lt;P mce_keep="true"&gt;It is important to note that TDE should not be perceived as a replacement of the encryption solutions shipped with SQL Server 2005; instead, TDE should be viewed as a complementary feature providing encryption at a coarser granularity level. Whereas the encryption features introduced in SQL Server 2005 provide a way to encrypt individual pieces of data&amp;nbsp;(something we&amp;nbsp;refer to&amp;nbsp;as cell-level encryption, because it offers finer granularity than column level encryption), the new TDE feature&amp;nbsp;enables encryption at database level. Also, from a cryptographic point of view, the algorithms used in TDE have also been available with the cell-level encryption, so the two features&amp;nbsp;offer the same encryption strength.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The encryption of a database with TDE is done using a special key called, simply,&amp;nbsp;&lt;EM&gt;database encryption key&lt;/EM&gt; (or DEK, for short). The DEK can be managed using standard DDL (CREATE/ALTER/DROP) and the actual state of the encryption can be turned on or off using the ALTER DATABASE statement and&amp;nbsp;a new clause: SET ENCRYPTION [ON | OFF].&amp;nbsp;Information about DEKs can be gathered from a DMV called sys.dm_database_encryption_keys. If you like using&amp;nbsp;a GUI for database operations, all these features are also exposed from within Management Studio. I&amp;nbsp;prefer typing SQL queries&amp;nbsp;when it comes to managing a database,&amp;nbsp;which is the reason why in my posts you'll&amp;nbsp;find more details about&amp;nbsp;DDL and system catalogs&amp;nbsp;than about&amp;nbsp;menus and dialog options.&lt;/P&gt;
&lt;P mce_keep="true"&gt;If you have&amp;nbsp;a &lt;A class="" href="http://technet.microsoft.com/en-us/sqlserver/bb498264.aspx" mce_href="http://technet.microsoft.com/en-us/sqlserver/bb498264.aspx"&gt;CTP build&lt;/A&gt;, you can quickly check for the presence of the TDE&amp;nbsp;feature by issuing the following statement: &lt;EM&gt;alter database&amp;nbsp;&amp;lt;db_name&amp;gt; set encryption on&lt;/EM&gt;. A syntax error will mean that&amp;nbsp;the feature is not present, while a more specific error message will indicate&amp;nbsp;that the feature is available - note that the statement should&amp;nbsp;result in no state changes&amp;nbsp;anyway, as long as you have not used TDE before. As of today, to my knowledge, only the latest CTP&amp;nbsp;build includes this feature.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5270262" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>Who needs encryption?</title><link>http://blogs.msdn.com/lcris/archive/2006/11/30/who-needs-encryption.aspx</link><pubDate>Fri, 01 Dec 2006 05:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1181423</guid><dc:creator>lcris</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/lcris/comments/1181423.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=1181423</wfw:commentRss><description>&lt;P&gt;For those that read my previous posts, the question in the title may be startling. I want to reassure you from the start: this post is not about encryption being a useless technique; it is&amp;nbsp;just about it not being a solution for certain problems and definitely not being a general solution for any problem. Also, this post is not product specific - I am discussing the technique of encryption in general, not the way&amp;nbsp;encryption is implemented in one particular product. The limitations I will discuss are properties of current standard encryption techniques, not limitations of specific product implementations.&lt;/P&gt;
&lt;P&gt;Over the last year, I&amp;nbsp;have seen&amp;nbsp;too many attempts of applying encryption to problems where&amp;nbsp;encryption does not really solve anything. So, in this post,&amp;nbsp;I&amp;nbsp;would like to make an attempt and explain why encryption is not a magical band-aid that only needs to be applied to&amp;nbsp;data,&amp;nbsp;to have it secured. To understand this, we have to understand a&amp;nbsp;few basic facts about encryption and about what it achieves. There are not many such facts, but they are extremely important.&lt;/P&gt;
&lt;P&gt;No part&amp;nbsp;of this post requires any deep&amp;nbsp;cryptographical knowledge - the only thing you need to know about encryption is that it transforms data into a form that hides all its properties&amp;nbsp;in such a way that cannot be reverted unless a piece of information referred to as the decryption&amp;nbsp;key is known. The encryption operation requires the use of another piece of information referred to as the encryption key. There are encryption algorithms where the encryption key and the decryption key are the same - these are called symmetric algorithms. There are also algorithms in which these are different - these are called asymmetric algorithms. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fact 1: Encryption does not eliminate the need to protect some data&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A small detail, but most important, really. If we want to protect some data, encryption does not fully help - it just reduces the amount of data we need to protect. Instead of having to protect a large amount of data, we will just have to protect a small piece -&amp;nbsp;the decryption key. This changes the difficulty of a problem: for example, if you want to keep secret 100 pages of information, one choice is to memorize them and then burn them, but few people can memorize so much information, so&amp;nbsp;a more practical solution using encryption would be to encrypt those pages using a password and then&amp;nbsp;to commit that password to memory. The bottom line is that you still have some information to protect, which, if discovered, would compromise your encrypted data.&lt;/P&gt;
&lt;P&gt;So, encrypted data is only as secure as you can secure the key that decrypts it.&lt;/P&gt;
&lt;P&gt;But how can we secure the decryption&amp;nbsp;key? Encrypting it&amp;nbsp;with another key only results in the same problem. So, eventually, we will need to protect a key with one or more of the following&amp;nbsp;methods used to control access to data:&lt;/P&gt;
&lt;P&gt;(1)&amp;nbsp;- something that you know (for example:&amp;nbsp;a password&amp;nbsp;or a PIN)&lt;BR&gt;(2)&amp;nbsp;- something that you have (for example:&amp;nbsp;a magnetic card)&lt;BR&gt;(3)&amp;nbsp;- something that only you are supposed to be able to produce&amp;nbsp;(biometrics, for example: fingerprint, iris scan, voice recognition)&lt;/P&gt;
&lt;P&gt;Debit cards, for example, are a combination of (1) and (2). (3) is tricky, because, for example, the verification method for voice recognition should be able to distinguish between the real voice and a recording. Credit cards, when the signature is verified or when they have a photograph attached, attempt to do a combination of (2) and (3).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fact 2: Encrypted data is unusable until it is decrypted&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This is pretty obvious, right? But this is often ignored and it makes a lot of difference in some scenarios I will discuss later here. Encryption is designed to hide the meaning of the data, which means we cannot make much sense out of it in encrypted form, so it is no longer as usable as it used to be when it was unprotected. If encryption would not achieve this, it would not be very useful&amp;nbsp;for protecting the data.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fact 3: Decryption cannot happen without having access to the decryption key&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Again, a rather obvious fact. I am almost embarassed of having to mention it, as it is what we are relying on when we use encryption: we want to make sure the process cannot be reverted without knowing the decryption key. But there is a useful takoff from this obvious fact, which is&amp;nbsp;overlooked more often than not.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fact 4: Designing an encryption algorithm is not easy&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Any decent cryptography book will tell us&amp;nbsp;right away that designing a good encryption algorithm is not something anyone can do. Unless you have devoted years of your life with successful results to the science of cryptography,&amp;nbsp;you&amp;nbsp;should use standard&amp;nbsp;algorithms validated by the scientific community,&amp;nbsp;instead of&amp;nbsp;designing and implementing your own.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Fact 5: There is nothing magic about encryption&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you can read this post to the end&amp;nbsp;and it makes sense to you, then you will probably agree about this fact. If not, then I am not sure what I can suggest other than to post your questions in the comment section.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What&amp;nbsp;are some key&amp;nbsp;learnings from these facts?&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Takeoff 1:&amp;nbsp;Decryption key protection is essential for safeguarding the encrypted data&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This derives from Fact 1. It means that if we cannot secure the decryption key, there was not much point in encrypting the data at all. Whoever&amp;nbsp;can get the key and the encrypted data,&amp;nbsp;can get access to the decrypted data.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Takeoff 2: A system that&amp;nbsp;does any meaningful&amp;nbsp;querying of&amp;nbsp;encrypted data needs to have access to the decryption key&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A system cannot use the encrypted data without decrypting it first (as per Fact 2) and it cannot do that without access to the decryption key (as per Fact 3), hence access to the key is required.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So, encryption will help against someone that can only get access to the encrypted data. This is a valid use scenario for encryption. For example, it will protect against someone that steals an encrypted database, if the decryption key was not stolen as well. But let us look at a few other database related scenarios that come up pretty often and&amp;nbsp;for which encryption is of no benefit:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Scenario 1: DRM&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;DRM is mainly used in relation to media protection, such as music files, but in this case, I use this&amp;nbsp;acronym for the following kind of database scenario:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;"I would like to package my database application in a form that would allow a customer to use it, but without him ever&amp;nbsp;being capable to access the actual data stored in it. I think encrypting the database&amp;nbsp;should help".&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Unfortunately, encryption will not help. The reason it will not help is that the customer still needs to be able to use the database, so, according to Fact 2 and Takeoff 2, the encryption key needs to be present somewhere on the customer's machine. At this point, the protection breaks, because there is no place on a machine where&amp;nbsp;software can store some information&amp;nbsp;in such a way that the machine owner cannot get to it. Once the key is found, the database can be decrypted and the protection is broken.&lt;/P&gt;
&lt;P&gt;Encryption in this case would act as obfuscation. This is the case with the old SQL Server CREATE PROCEDURE ... WITH ENCRYPTION feature. This feature has been hammered hard because it attempted to do something impossible. Some people suggested improvements related to using a better encryption algorithm. This was not the problem - this feature uses RC4 and no one&amp;nbsp;broke it by breaking the encryption algorithm -&amp;nbsp;attackers just figured out where the system gets the key from. Any other solution for this problem would just change a bit the algorithm, but the issues remain the same.&lt;/P&gt;
&lt;P&gt;To be&amp;nbsp;more specific, the difference between obfuscation and encryption is the following: with obfuscation, the&amp;nbsp;strength relies in the algorithm itself, disclosing it would allow someone to easily&amp;nbsp;break it; with encryption, the strength relies in the decryption key, not in the algorithm - even knowing the algorithm would not be sufficient to break the encryption. Using encryption and obfuscating the decryption key&amp;nbsp;makes the ensemble equate&amp;nbsp;to obfuscation.&lt;/P&gt;
&lt;P&gt;Obfuscation is not completely useless. It can serve a purpose if the cost of breaking it is higher than the benefit of breaking it. However, a successful commercial obfuscation method will most certainly be broken and the chance will increase with the degree of commercial success of the method, because the more data it protects, the more benefit can be derived from breaking it. It really is a matter of economics,&amp;nbsp;more than&amp;nbsp;security.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Scenario 2: Separation of duties from machine administrator&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;"I think encrypting the data in the database will prevent a machine administrator from being able to read it".&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Unfortunately, encryption will not help with this scenario either. The problem is similar to the one in the previous scenario: the decryption key has to be available to the database system, which needs it to be able to process the data, but this also makes it available to the machine administrator, which has unlimited access to the system.&lt;/P&gt;
&lt;P&gt;Unfortunately, PCs were not designed with separation of duties in mind. The PC acronym stands for personal computer - this machine was originally meant to be a personal device; it is only due to the amazing advancements in hardware over the last two decades that this originally humble machine became capable of handling increasingly complicated tasks, which require a different level of security. The result is that the PC does not permit information to be processed by software without the administrator&amp;nbsp;of the machine&amp;nbsp;being able to see it. Trying to protect information from the eyes of the machine administrator is similar to attempting to hide&amp;nbsp;your valuables&amp;nbsp;from your landlord - you can sue him after he steals them, but you cannot prevent him from doing so.&lt;/P&gt;
&lt;P&gt;To be clear, it would be extremely expensive to build a machine and the software around it that could provide an absolute guarantee about separation of duties. And using the system would probably be fairly inconvenient. So, it should not come as a surprise that a PC does not provide such guarantee.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Scenario 3: Protections against a hacker attack on an online database&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;"If an attacker hacks into my database, he'll get my sensitive information, but if I encrypt it, it will be useless to him".&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Well, depending on how the hacker gets in and how the data is used, this may or may not be true. In most practical situations, unfortunately, I expect that this will not hold true.&lt;/P&gt;
&lt;P&gt;To take a recent data theft as an example, an attacker was able to use a SQL injection attack to steal SSNs from a database system. The investigation of this attack appeared to deplore the fact that this information was stored in clear. But would it have really helped if it were encrypted? The database system was probably using that information and was serving it in decrypted form&amp;nbsp;to the authorized users that requested it; if the injection was made under an account that was authorized to see the data in decrypted form, the attacker would have been able to read that data as easily as if it was not encrypted.&lt;/P&gt;
&lt;P&gt;Too many "if"s? Maybe, but what they mean is that there is no guarantee that the encrypted data is safe from an attacker that gets access to the live system. Especially if encryption was done "transparently", for usability purposes, then there would be no barrier against an attacker other than the regular authorization system - such encryption would not protect at all against a SQL injection attack.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To conclude this rather long article, encryption is not a "silver bullet" of security. Having data encrypted does not necessarily mean that it also&amp;nbsp;becomes automatically secured. Unfortunately, encrypted data still has to be decrypted before being used, and at that moment it becomes vulnerable. We can make some strong security guarantees based on the use of encryption in some scenarios, but we cannot use encryption in an arbitrary scenario and claim security just for doing that.&lt;/P&gt;
&lt;P&gt;If you want to learn more about encryption than what I covered here (I could not cover very much), then I recommend the books written by &lt;A class="" href="http://www.schneier.com/" mce_href="http://www.schneier.com/"&gt;Bruce Schneier&lt;/A&gt;. He has been writing for years about the dangers of using cryptography (or other various procedures)&amp;nbsp;without understanding security and, while I wrote this post in my own words, I cannot shake the feeling that I am repeating some of the ideas that Bruce keeps mentioning in his books - maybe for the same reason why he also keeps mentioning them, because some security mistakes are constanty being repeated too.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1181423" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+security/default.aspx">SQL Server - security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: An example for how to use counter signatures</title><link>http://blogs.msdn.com/lcris/archive/2006/10/19/sql-server-2005-an-example-for-how-to-use-counter-signatures.aspx</link><pubDate>Fri, 20 Oct 2006 04:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:847157</guid><dc:creator>lcris</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lcris/comments/847157.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=847157</wfw:commentRss><description>&lt;P&gt;A while ago, I wrote a &lt;A class="" href="http://blogs.msdn.com/lcris/archive/2005/06/15/429631.aspx" mce_href="http://blogs.msdn.com/lcris/archive/2005/06/15/429631.aspx"&gt;post&lt;/A&gt; showing how signatures can be used to allow users to perform operations without explicitly granting them the permissions required for that operation. In this post I'll present&amp;nbsp;more details about the&amp;nbsp;use of signatures.&lt;/P&gt;
&lt;P&gt;One&amp;nbsp;important thing to keep in mind when working with signatures is that, normally,&amp;nbsp;they will only have effect while the signed module is executed. When executing a signed module, the signatures will be temporarily added to the SQL token, but they will be lost if the module executes another one or if it&amp;nbsp;terminates execution. In some situations, you may want the signatures to be persisted across multiple module calls. This is where counter signatures can be used. A counter signature is&amp;nbsp;a special form of signature: by itself, it does not grant any permissions; however, it allows signatures made by the same certificate or asymmetric key to be kept for the duration of the call made to the counter signed module.&lt;/P&gt;
&lt;P&gt;I bet this sounds rather complicated, so let's go over an example that is slightly less complicated (TSQL code is at the end of this post). Let's say we have user Alice calling procedure ProcAlice, which calls procedure ProcT, which selects from table T. Alice has EXECUTE permission on ProcAlice and ProcT, but she cannot select from T, and no ownership chaining is involved in this entire chain. So Alice cannot access T - neither directly, nor through the use of ProcAlice and ProcT. The tricky part&amp;nbsp;is that we&amp;nbsp;want Alice to always use ProcAlice for access -&amp;nbsp;we don't want her to use ProcT. How can we accomplish this? Sure, we could sign ProcT, such that ProcT can access T, but then Alice can invoke ProcT directly - she doesn't have to call ProcAlice. We could deny EXECUTE permission on ProcT to Alice, but then Alice would not be able to call ProcT through ProcAlice either (remember that no ownership chaining is involved). Signing ProcAlice would not work by itself, because the signature would be lost in the call to ProcT. However, by counter signing ProcT with the same certificate used to sign ProcAlice,&amp;nbsp;SQL Server&amp;nbsp;will keep the signature across the call chain and will allow access to T; also, if Alice will attempt to call ProcT directly, she still won't be able to access T, because the counter signature doesn't grant any rights.&lt;/P&gt;
&lt;P&gt;This is the essence of the TSQL example shown below. In the example, ProcAlice appears as proc_select_t_for_alice, and ProcT is proc_select_t.&amp;nbsp;I have not tried to eliminate the ownership chaining between these two. While running through this example, I recommend examining how the state of the login and user tokens is changed by adding the signatures. Finally, do not use this example as an example for how to select passwords :)&lt;/P&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- A demo for counter signatures&lt;BR&gt;--&lt;BR&gt;-- create test database&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; test_cs&lt;BR&gt;go&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;use&lt;/FONT&gt;&lt;FONT size=2&gt; test_cs&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create table t&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;table&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;c &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;int&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;insert&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;into&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;values&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;42&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create a bogus user to own t&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;user&lt;/FONT&gt;&lt;FONT size=2&gt; bogus without &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;BR&gt;alter&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;authorization&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;on&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; bogus&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create a certificate for signing&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cs_select_t&lt;BR&gt;&amp;nbsp;&amp;nbsp;encryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'SimplePwd01'&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; subject &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Certificate used to grant SELECT on t'&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;user&lt;/FONT&gt;&lt;FONT size=2&gt; ucs_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cs_select_t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;grant&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;on&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; ucs_select_t&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create a principal with low privileges&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; alice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'SimplePwd01'&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;user&lt;/FONT&gt;&lt;FONT size=2&gt; alice&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- verify alice cannot access t&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.login_token&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;db_name&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.user_token&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;revert&lt;/P&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create a procedure that directly accesses t&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;procedure&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.login_token&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;db_name&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.user_token&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;print&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Now selecting from t...'&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;end&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;go&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;grant&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;on&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- verify procedure&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- verify alice cannot access t through procedure&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;revert&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create special procedure for accessing t&lt;BR&gt;-- this will call proc_select_t but will do some extra processing&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;procedure&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.login_token&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;db_name&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.user_token&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;user_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;()&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&amp;lt;&amp;gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;user_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;print&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Only alice can use this'&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;end&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT size=2&gt;exec&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;end&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;go&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;grant&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;on&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- verify procedure&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- alice still can't use the procedure yet&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;revert&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Sign procedure to grant it SELECT permission&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;add&lt;/FONT&gt;&lt;FONT size=2&gt; signature &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cs_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'SimplePwd01'&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- retry - it still won't work, but we'll see some nice tokens&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;revert&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Counter sign proc_select_t, to make this work&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;add&lt;/FONT&gt;&lt;FONT size=2&gt; counter signature &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;to&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cs_select_t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'SimplePwd01'&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- retry - now it finally works&lt;BR&gt;-- note that calling proc_select_t directly still doesn't work&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;execute&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'alice'&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t_for_alice&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;exec&lt;/FONT&gt;&lt;FONT size=2&gt; proc_select_t&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;revert&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- cleanup&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;use&lt;/FONT&gt;&lt;FONT size=2&gt; master&lt;BR&gt;go&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;drop&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; test_cs&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;drop&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;login&lt;/FONT&gt;&lt;FONT size=2&gt; alice&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;--&lt;BR&gt;-- EOD&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=847157" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+security/default.aspx">SQL Server - security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category></item><item><title>SQL Server 2005: How to determine what key was used to encrypt a piece of data</title><link>http://blogs.msdn.com/lcris/archive/2006/07/06/sql-server-2005-how-to-determine-what-key-was-used-to-encrypt-a-piece-of-data.aspx</link><pubDate>Fri, 07 Jul 2006 02:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:658409</guid><dc:creator>lcris</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lcris/comments/658409.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=658409</wfw:commentRss><description>&lt;P&gt;Let's say&amp;nbsp;we have some data that is encrypted and&amp;nbsp;we would like to find out what key was used to perform the encryption. SQL Server 2005&amp;nbsp;knows what key was used to encrypt the data&amp;nbsp;because the key identifier (the key_guid value) is prefixed to the encrypted data. We can&amp;nbsp;find out the key same as SQL Server does&amp;nbsp;with a one-line TSQL statement. Here's a small demo that wraps that one-line statement&amp;nbsp;in a function for easier use:&lt;/P&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Set up a database for this demo&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; test&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;use&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; test&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- We use the identity_value clause to obtain the same fixed GUID on all systems&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; skey &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; algorithm &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; triple_des&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; identity_value &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Test'&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; encryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Anss$pt@Ihnbwef&amp;amp;o!'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- The following query should return&lt;BR&gt;-- 5D910600-5D5F-874F-54F5-1892D884C477&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; key_guid &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.symmetric_keys&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;where&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;name&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'skey'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- create a simple function to return the guid of the key that was used to encrypt a piece of data&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;function&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; key_guid_from_bytes &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;@data &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;varbinary&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;8000&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;))&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;returns&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;uniqueidentifier&lt;BR&gt;as&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;convert&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;uniqueidentifier&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;/FONT&gt;&lt;FONT size=2&gt; @data&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;end&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- encrypt using skey and use the key_guid_from_bytes function to examine the encrypted data&lt;BR&gt;-- we should retrieve the key guid - 5D910600-5D5F-874F-54F5-1892D884C477 and the key name - skey&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;open&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; skey decryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Anss$pt@Ihnbwef&amp;amp;o!'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;select&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;key_guid_from_bytes&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;encryptbykey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;key_guid&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'skey'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Top Secret'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;name&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.symmetric_keys&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;where&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; key_guid &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;key_guid_from_bytes&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;encryptbykey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt;key_guid&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'skey'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Top Secret'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;));&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;close&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; skey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Cleanup&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;use&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; master&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;drop&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT color=#000000 size=2&gt; test&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=658409" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>SQL Server 2005: How to regenerate the same symmetric key in two different databases</title><link>http://blogs.msdn.com/lcris/archive/2006/07/06/sql-server-2005-how-to-regenerate-the-same-symmetric-key-in-two-different-databases.aspx</link><pubDate>Fri, 07 Jul 2006 01:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:658364</guid><dc:creator>lcris</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/lcris/comments/658364.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=658364</wfw:commentRss><description>&lt;P&gt;In a previous post on &lt;A href="http://blogs.msdn.com/lcris/archive/2005/10/14/481434.aspx"&gt;using symmetric keys&lt;/A&gt;, I mentioned that keys can be recreated using the KEY_SOURCE and IDENTITY_VALUE clauses of CREATE SYMMETRIC KEY. In this post, I'd like to expand a little on this topic and present a small demo as well.&lt;/P&gt;
&lt;P&gt;Because keys cannot be individually backed up and restored, there is no direct way of moving a key from one database to another. However, by specifying the same values for the ALGORITHM, KEY_SOURCE, and IDENTITY_VALUE clauses of CREATE SYMMETRIC KEY, the same key can be generated on different databases. The KEY_SOURCE is the most important clause: the passphrase specified here is used to determine the key bits, so the phrase should be protected as carefully as the key itself&amp;nbsp;or the data protected by it are protected. By specifying the same KEY_SOURCE, you are guaranteed to&amp;nbsp;obtain the same key, assuming of course that you specified the same encryption algorithm. However, this is not sufficient to allow us to decrypt data encrypted by the key in another database - we also need for this key to be identified by the system as the same key -&amp;nbsp;that is, &amp;nbsp;the key needs to have the same identifier, because this identifier is appended to the encrypted data and is used to determine the key that should be used for decryption. (The identifier of a key is shown in the key_guid column in the sys.symmetric_keys dialog and is also the value that needs to be passed to the encryptbykey functions). This is where the IDENTITY_VALUE clause comes into place - the phrase specified here will be used to generate a key identifier. The IDENTITY_VALUE clause doesn't have to be secret, but&amp;nbsp;there's no reason it should be advertised either. The KEY_SOURCE is what you need to protect carefully.&lt;/P&gt;
&lt;P&gt;And here is a small script that shows how to create a key using these clauses and how to decrypt data encrypted by it in a different database.&lt;/P&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Set up the databases used for the demo&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; db_source&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; db_destination&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;use&lt;/FONT&gt;&lt;FONT size=2&gt; db_source&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Keep the key_source phrase carefully protected - it''s the key!!!&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT size=2&gt; skey&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; algorithm &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; triple_des&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;identity_value &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Data encryption key 07/06/2006'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;key_source &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Now he''s a clock-punching insurance claims adjuster fighting boredom and a bulging waistline.'&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;encryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Avc#ptNO$cf@o!'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;open&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT size=2&gt; skey decryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Avc#ptNO$cf@o!'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.symmetric_keys&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.openkeys&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Encrypt some data in a table&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;table&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;data &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;varbinary&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;1024&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;insert&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;into&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;values&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;encryptbykey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;key_guid&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'skey'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Top Secret!'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; t&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;close&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT size=2&gt; skey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Now copy the encrypted data to another table in another database&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;use&lt;/FONT&gt;&lt;FONT size=2&gt; db_destination&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;table&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;data &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;varbinary&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;1024&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;));&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;insert&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;into&lt;/FONT&gt;&lt;FONT size=2&gt; t &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;data&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;)&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; t_src&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;data &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; db_source&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;dbo&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;.&lt;/FONT&gt;&lt;FONT size=2&gt;t t_src&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; t&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Recreate the encryption key, so we can decrypt&lt;BR&gt;-- The key can have a different name and can be protected with a different mechanism,&lt;BR&gt;-- but it has to be obtained from the same algorithm, key_source, identity_value combo&lt;BR&gt;-- In this database, we'll protect the key using a certificate&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; master &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT size=2&gt; encryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; password &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;A href="mailto:'Yahtf%pt@Hwht$f!O!'"&gt;'Yahtf%pt@Hwht$f!O!'&lt;/A&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cert_skey &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; subject &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Certificate for accessing symmetric keys 07/06/2006'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;create&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;symmetric&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;key&lt;/FONT&gt;&lt;FONT size=2&gt; skey2&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;with&lt;/FONT&gt;&lt;FONT size=2&gt; algorithm &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; triple_des&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;identity_value &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Data encryption key 07/06/2006'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;key_source &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;=&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'Now he''s a clock-punching insurance claims adjuster fighting boredom and a bulging waistline.'&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;encryption &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;by&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;certificate&lt;/FONT&gt;&lt;FONT size=2&gt; cert_skey&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.symmetric_keys&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;*&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;sys.openkeys&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Now use the key to decrypt the copied data&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;select&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff00ff size=2&gt;convert&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;varchar&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;256&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT size=2&gt; decryptbykeyautocert&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT size=2&gt;cert_id&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;'cert_skey'&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;),&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;NULL,&lt;/FONT&gt;&lt;FONT size=2&gt; data&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;))&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;from&lt;/FONT&gt;&lt;FONT size=2&gt; t&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;
&lt;P&gt;-- Cleanup&lt;BR&gt;--&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;use&lt;/FONT&gt;&lt;FONT size=2&gt; master&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;drop&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; db_source&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;drop&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;database&lt;/FONT&gt;&lt;FONT size=2&gt; db_destination&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;You might want to experiment with the arguments used to create skey2. You will notice that if either the KEY_SOURCE or the IDENTITY_VALUE are not identical, the key will be created, but it will be different, and the decryption will not work.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=658364" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item><item><title>Why encryption should be salted and a small C# demo</title><link>http://blogs.msdn.com/lcris/archive/2006/05/08/why-encryption-should-be-salted-and-a-small-c-demo.aspx</link><pubDate>Tue, 09 May 2006 00:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:592868</guid><dc:creator>lcris</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/lcris/comments/592868.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lcris/commentrss.aspx?PostID=592868</wfw:commentRss><description>&lt;P&gt;In my previous post on &lt;A href="http://blogs.msdn.com/lcris/archive/2005/12/22/506931.aspx"&gt;searching encrypted data&lt;/A&gt;, I mentioned that the SQL Server 2005 encryption procedures are salted and that this prevents an index on encrypted data from being useful for any type of cleartext searches. Today, I will&amp;nbsp;illustrate why encryption should be salted&amp;nbsp;by presenting&amp;nbsp;a&amp;nbsp;small C#&amp;nbsp;encryption demo.&lt;/P&gt;
&lt;P&gt;Interest in searching encrypted data comes primarily from the use of social security numbers and credit card numbers as identifying information, while these are&amp;nbsp;at the same time&amp;nbsp;supposed to be confidential information. Thus, the requirement for the ability to search these data is combined with the need to protect it via encryption. To make the demo relevant to these requirements, I will use two made-up credit card numbers, but the&amp;nbsp;issues I will point out&amp;nbsp;are relevant to social security numbers&amp;nbsp;as well as to&amp;nbsp;other types of data.&lt;/P&gt;
&lt;P&gt;Before I present the code, I should explain some technical details&amp;nbsp;about&amp;nbsp;encryption. In the following discussion, plaintext will refer to the unencrypted data and ciphertext will refer to the encrypted data.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Block encryption algorithms:&lt;/STRONG&gt; TripleDES is a block encryption algorithm with a block size of 64 bits (8 bytes). This means that the algorithm encrypts chunks of 64 bits at a time. It takes the first 64 bit block&amp;nbsp;of the cleartext, encrypts it, then moves on to the next 64 bit block of cleartext. This also means that if we encrypt two pieces of cleartext and they have an identical 64 bit block, then the&amp;nbsp;corresponding encrypted block will&amp;nbsp;be identical in both encryptions. Most encryption algorithms today are block algorithms: AES (128 bit block)&amp;nbsp;and RC2 (64 bit block), for example, are&amp;nbsp;other examples of block&amp;nbsp;encryption algorithms.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Chaining Modes:&lt;/STRONG&gt; To mitigate&amp;nbsp;the fact that the same plaintext block would encrypt to the same ciphertext block, various chaining methods can be used for encryption. The chaining mode I will use in this demo is called Cipher Block Chaining (CBC) and is&amp;nbsp;a commonly used&amp;nbsp;mode. In this mode, when a cleartext block is about to be encrypted, it is first combined with the previously encrypted block (through a XOR operation), before the actual encryption transformation takes place. This way, even if two blocks of plaintext are identical, the corresponding encrypted blocks&amp;nbsp;would still be different&amp;nbsp;except when&amp;nbsp;all previous plaintext blocks were identical as well. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Initialization Vector:&lt;/STRONG&gt; So the CBC mode will combine the currently processed plaintext block with the previous ciphertext block. But what will happen if we just started encryption and we're processing the first block of plaintext - there is no previously generated ciphertext block yet! This is where the Initialization Vector comes into play - an IV is just a randomly generated block that will play the role of the first ciphertext block. By using a different IV for each encryption, prefix patterns are hidden because the first ciphertext block is the IV and it is different for each encryption. Using a fixed IV will allow prefix patterns to be reflected in the output of the encryption, as we will see in the demo. The use of a random IV for each encryption is also referred to as salting.&lt;/P&gt;
&lt;P&gt;So,&amp;nbsp;putting these together, block encryption can leak information about the plaintext having identical blocks, because when this happens, the ciphertext blocks&amp;nbsp;will be identical too. Chaining modes combined with random IVs for each encryption will strengthen the encryption by hiding&amp;nbsp;patterns in the cleartext, but both these mechanisms have to be used for this to happen. The encryption procedures in SQL Server 2005 use both&amp;nbsp;CBC and random IVs to prevent patterns in the cleartext data from being reflected in the ciphertext data.&lt;/P&gt;
&lt;P&gt;In the demo, we will encrypt two credit card numbers using a TripleDES key. The credit card numbers will have the same first eight digits because&amp;nbsp;we will process them as ASCII and 8 characters require 8 bytes - the size of a TripleDES block. The initial encryptions will be done using the same IV.&amp;nbsp;We will also perform an encryption of a credit card number with the same TripleDES key but with a&amp;nbsp;different IV, to show the difference made by changing the IV. Then we'll look at the encrypted data and see what we can learn from it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;1.&lt;/STRONG&gt; First, let's start by creating a TestCryptoSalt.cs file and copying the code below into it:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;//////////////////&lt;BR&gt;///&lt;BR&gt;/// TestCryptoSalt&lt;BR&gt;///&lt;BR&gt;/// Small demo of encryption and salting&lt;BR&gt;///&lt;BR&gt;/// compile command:&lt;BR&gt;/// csc TestCryptoSalt.cs&lt;BR&gt;///&lt;BR&gt;//////////////////&lt;BR&gt;using System;&lt;BR&gt;using System.Collections;&lt;BR&gt;using System.Text;&lt;BR&gt;using System.Security.Cryptography;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;namespace TestCryptoSalt&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;/// &amp;lt;summary&amp;gt;&lt;BR&gt;&amp;nbsp;/// Showing effect of salt on encryption&lt;BR&gt;&amp;nbsp;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class TestCryptoSalt&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// The main entry point for the application.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [STAThread]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; crypto_test_no_salt();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Helper function for hexadecimal display of a byte array&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ///&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Arguments:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// str - a description to be output before the hex print&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// data -&amp;nbsp; the byte array to print&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void print_bytes(string str, byte[] data)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\n" + str);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write("\t");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; data.Length; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(String.Format("0x{0:X}", data[i]));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write(' ');&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((i + 1) % 8 == 0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write("\n\t");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// The main test&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void crypto_test_no_salt()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Two made-up credit card numbers with identical first half&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string strCC1 = "4011023411013758";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string strCC2 = "4011023410254622";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Display CC1&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\nCC1: " + strCC1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytesCC1 = Encoding.ASCII.GetBytes(strCC1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("CC1 (bytes):", bytesCC1);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Display CC2&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\nCC2: " + strCC2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytesCC2 = Encoding.ASCII.GetBytes(strCC2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("CC2 (bytes):", bytesCC2);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a TripleDES key&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We'll use the Cipher Block Chaining encryption mode&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TripleDES tdes = TripleDES.Create();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tdes.KeySize = 128;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tdes.Mode = CipherMode.CBC;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tdes.GenerateKey();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Display the key and its Initialization Vector&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES key (bytes):", tdes.Key);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES IV (bytes):", tdes.IV);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Encrypt CC1&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ICryptoTransform tdes_encr = tdes.CreateEncryptor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytesCC1Encrypted = tdes_encr.TransformFinalBlock(bytesCC1, 0, bytesCC1.Length);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES encryption of CC1 (bytes):", bytesCC1Encrypted);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Encrypt CC2&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytesCC2Encrypted = tdes_encr.TransformFinalBlock(bytesCC2, 0, bytesCC2.Length);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES encryption of CC2 (bytes):", bytesCC2Encrypted);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set a new Initialization Vector&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tdes.GenerateIV();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Display the key and its Initialization Vector&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES key (bytes):", tdes.Key);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES IV (bytes):", tdes.IV);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Re-encrypt CC2 using the new IV&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tdes_encr = tdes.CreateEncryptor(tdes.Key, tdes.IV);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytesCC2EncryptedNewIV = tdes_encr.TransformFinalBlock(bytesCC2, 0, bytesCC2.Length);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_bytes("Triple DES encryption of CC2 using new IV (bytes):", bytesCC2EncryptedNewIV);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Now attempt to decrypt, just for fun, to show CBC's nice recovery&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Only the last encryption will be fully decrypted correctly,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // because the first two were made using a different IV&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ICryptoTransform tdes_decr = tdes.CreateDecryptor();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\nRetrieving encrypted CC1: "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + Encoding.ASCII.GetString(tdes_decr.TransformFinalBlock(bytesCC1Encrypted, 0, bytesCC1Encrypted.Length)));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\nRetrieving encrypted CC2: "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + Encoding.ASCII.GetString(tdes_decr.TransformFinalBlock(bytesCC2Encrypted, 0, bytesCC2Encrypted.Length)));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("\nRetrieving encrypted CC2: "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + Encoding.ASCII.GetString(tdes_decr.TransformFinalBlock(bytesCC2EncryptedNewIV, 0, bytesCC2EncryptedNewIV.Length)));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;2.&lt;/STRONG&gt; Now, let's&amp;nbsp;compile this file using the csc&amp;nbsp;compiler. For example, on my system, the command for compiling the demo looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;C:\WINNT\Microsoft.NET\Framework\v2.0.50727\csc.exe TestCryptoSalt.cs&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;3.&lt;/STRONG&gt;&amp;nbsp;Let's execute the program. The output will differ each time the program is run because a new encryption key will be generated with each execution. On my system, I got the following output:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;CC1: 4011023411013758&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;CC1 (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x34 0x30 0x31 0x31 0x30 0x32 0x33 0x34&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x31 0x31 0x30 0x31 0x33 0x37 0x35 0x38&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;CC2: 4011023410254622&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;CC2 (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x34 0x30 0x31 0x31 0x30 0x32 0x33 0x34&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x31 0x30 0x32 0x35 0x34 0x36 0x32 0x32&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES key (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0xD 0xDC 0xFC 0xC4 0xD7 0xD 0xB7 0xB8&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x92 0xC5 0x77 0xA8 0xD 0x96 0x1 0xBD&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES IV (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x1A 0x42 0xD0 0x17 0x9E 0xA1 0xE6 0xF4&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES encryption of CC1 (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x26 0x8B 0xEC 0x7C 0x56 0x5F 0x5A 0xD3&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x13 0xB4 0xB6 0xCB 0x7F 0x80 0x52 0x49&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x12 0xBB 0x89 0x7 0x37 0xF6 0x9F 0x69&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES encryption of CC2 (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x26 0x8B 0xEC 0x7C 0x56 0x5F 0x5A 0xD3&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x3B 0x8F 0xB0 0xAD 0x4C 0x14 0x1 0xB2&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x76 0xBD 0x56 0x8C 0x52 0x6C 0x22 0xD&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES key (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0xD 0xDC 0xFC 0xC4 0xD7 0xD 0xB7 0xB8&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x92 0xC5 0x77 0xA8 0xD 0x96 0x1 0xBD&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES IV (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x4D 0x25 0x8E 0xEC 0x38 0xF7 0xA6 0xE9&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Triple DES encryption of CC2 using new IV (bytes):&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0xC6 0x49 0xD3 0x43 0x79 0x96 0xF7 0xE6&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x50 0xC3 0xAC 0x5E 0x27 0x9C 0xF9 0xF&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x60 0x3 0xB 0x2B 0x4A 0xA1 0x8D 0x2B&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;Retrieving encrypted CC1: cWo??ds)11013758&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Retrieving encrypted CC2: cWo??ds)10254622&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Retrieving encrypted CC2: 4011023410254622&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;4.&lt;/STRONG&gt; Let's discuss the&amp;nbsp;program output.&lt;/P&gt;
&lt;P&gt;We start by printing out the two credit numbers in ASCII and hexadecimal representations. The hexadecimal printouts are arranged so that we have 8 bytes per line -&amp;nbsp;the size of a TripleDES&amp;nbsp;block. This will make it easier to compare identical blocks.&lt;/P&gt;
&lt;P&gt;We then print the TripleDES key - it has 16 bytes - 128 bits. The IV is 8 bytes, the size of a block.&lt;/P&gt;
&lt;P&gt;Looking at the encryptions of CC1 and CC2 that are done with the same IV,&amp;nbsp;we can&amp;nbsp;notice that the first blocks are identical. This happens because the two credit card numbers share their first&amp;nbsp;eight digits, and the encryption discloses this fact. The credit card numbers actually&amp;nbsp;share their first&amp;nbsp;nine digits, but the nineth digit&amp;nbsp;will be encrypted as part of the second block, so we cannot see that it is shared just by looking at the encrypted output.&lt;/P&gt;
&lt;P&gt;The program is now generating a new IV and prints again the key and this IV. We can observe that the key is the same as before; only the IV has changed. The second credit card number is now encrypted using this new IV and this time the output&amp;nbsp;has no common pattern with the previous outputs. We can no longer detect that this encryption was made&amp;nbsp;for a plaintext that has anything&amp;nbsp;in common&amp;nbsp;with the plaintexts from which the previous two ciphertexts were generated.&lt;/P&gt;
&lt;P&gt;Finally, using the last IV,&amp;nbsp;we will attempt to decrypt the three ciphertexts. This is just a side-demo that illustrates how the CBC chaining mode recovers from an error. Because&amp;nbsp;we are using the wrong IV for the&amp;nbsp;first two ciphertexts,&amp;nbsp;we are not able to decrypt those ciphertexts completely: the first block is garbled because the IV is incorrect, however, the subsequent blocks are decrypted correctly and&amp;nbsp;we can retrieve the second halves of the credit card numbers. Of course, the decryption of the third ciphertext works as expected and decrypts the entire credit card number.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusions&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;We have seen in this demo that by using a fixed IV, prefix patterns in cleartext data can be reflected in the ciphertext data. The common prefix has to be at least as large as an encryption block for this to happen. In the example, because the numbers were stored as ASCII,&amp;nbsp;an 8 digit common prefix would be reflected in the ciphertext. If we would have encrypted credit card numbers as Unicode, a common 4 digit prefix would show up in the ciphertext.&amp;nbsp;It's also not uncommon for credit card numbers or social security numbers to have common&amp;nbsp;prefixes; for example, the first 4 digits of a credit card number&amp;nbsp;are used to identify the card type.&lt;/P&gt;
&lt;P&gt;Of course, knowing that two credit card numbers have the same prefix doesn't automatically allow us to find out what those credit card numbers are. But it's a very good start. If we can identify one number from some other information (maybe we inserted one of the records), then we automatically find out information about the other number, and this doesn't require any number crunching.&lt;/P&gt;
&lt;P&gt;So, the reason why SQL Server 2005 encryption procedures are&amp;nbsp;using&amp;nbsp;a random IV for each encryption&amp;nbsp;is to provide the safest use of encryption. It's not sufficient to use a good encryption algorithm, it's also necessary to use it well, and block encryption algorithms should be used with a chaining mode and a random IV for each encryption.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=592868" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server+-+cryptography/default.aspx">SQL Server - cryptography</category><category domain="http://blogs.msdn.com/lcris/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://blogs.msdn.com/lcris/archive/tags/computer+security/default.aspx">computer security</category><category domain="http://blogs.msdn.com/lcris/archive/tags/encryption/default.aspx">encryption</category></item></channel></rss>