April 11, 2011, 11:17 p.m.
posted by angryuser
Security Technologies and Standards
Security is really three different but complementary technologies. Generally speaking, to secure an application can mean
This first item, ensuring access for only authorized users, is commonly broken into two pieces:
Examples of authentication include the HTTP Digest technology, and the popular Kerberos. The most secure authentication technologies use cryptographic techniques to send a ticket, or binary blob of data, that includes the user's data. Public key technology can then verify the ticket as the appropriate user and ensure that only the appropriate Kerberos ticket readers read the data.
Typically, authorization is handled either by platform specific technologies, such as Windows 2000 security, or via custom security checks once the user identity has been verified. Authorization also can be performed as a service.
Confidentiality refers to keeping data secret, typically via cryptographic techniques. The two major forms of encryption are public key and private key. Private key is a little simpler; public key has broader applications.
Private Key Encryption
Private keys are binary blobs of data, generally between 64 and 512 bits in size. A private key and its initialization vector (commonly called an IV) can both encrypt and decrypt the same piece of data. Because private key works in both directions—encryption and decryption—the key is described as symmetric. Often, the data to be encrypted is called plain text.
Here is an example of a symmetric, private key that is used for the Rijndael (pronounced "rain doll") algorithm. (By the way, this key algorithm is now called AES, or Advanced Encryption Standard.)
Symmetric encryption algorithms often use an initialization vector. This IV is some random binary data that is used to ensure that any two pieces of encrypted data are never the same. This helps to prevent cryptographic attacks. Here is an initialization vector for the Rijndael algorithm:
Using private keys is fairly simple with the .NET Framework. An entire namespace of classes is used for cryptography: System.Security.Cryptography. This namespace has an abstract class called Symmetric-Algorithm, from which specific implementations of various symmetric, or private key, encryption algorithms are derived.
Use these specific derived classes to manipulate keys and perform cryptographic operations. You can also use these classes to create encryptors and decryptors to be handed off to a CryptoStream object. This stream class works in much the same way as other stream classes, such as NetworkStream. As a matter of fact, because this is a stream, you can compose this cryptographic stream with others.
Figure shows a small Windows application that uses the Rijndael algorithm. This sample will encrypt some plain text. It also displays the IV and key used, which are randomly generated each time the text is encrypted. The same key and IV will then decrypt the now encrypted text.
To begin with, we'll import these namespaces:
using System.Security.Cryptography; using System.IO;
Next, we'll create a memory stream and the RijndaelManaged object, which we then pass off to a CryptoStream object:
MemoryStream stream = new MemoryStream(); RijndaelManaged rainDoll = new RijndaelManaged(); CryptoStream encStream = new CryptoStream(stream, rainDoll.CreateEncryptor(rainDoll.Key, rainDoll.IV), CryptoStreamMode.Write);
Now, we'll write the plain text string into the CryptoStream:
Byte bin = System.Text.Encoding.UTF8.GetBytes(txtPlain.Text); encStream.Write(bin, 0, bin.Length); encStream.FlushFinalBlock();
Finally, we'll transform the MemoryStream into a string using the Convert class:
Byte bout = stream.ToArray(); txtEncrypt.Text = Convert.ToBase64String( bout );
Decryption follows a similar process. The major differences are the FOR loop needed to reconstruct the string, and setting the key and IV to the same ones used to encrypt the text.
Public Key Encryption
Public key encryption, also known as asymmetric encryption, is a more flexible form of encryption that involves two keys (and no initialization vector). One key is public, and others use it to encrypt messages. Only the private key, which is secret, can decrypt the messages.
Typically, there needs to be a key exchange or some other process to permit each party in the communication to exchange public keys. Often, it's possible to query public authorities (such as VeriSign) for public keys as well.
The .NET Framework contains many different classes for public key encryption. These classes are derived from the AsymmetricAlgorithm class. For this example, we'll use the RSACryptoServiceProvider class, which uses the RSA encryption algorithm. This class and other asymmetric encryption algorithms don't use the CryptoStream class. This application will resemble Figure.
To begin with, we will need to import the following namespaces:
using System.Security.Cryptography; using System.IO;
Next, we'll create the RSA encryption object, which will create a default private key and a default public key; and we'll save the public key information in an XML format within a text field:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.PersistKeyInCsp = false; txtKey.Text = rsa.ToXmlString( true );
Finally, to finish encrypting, we'll merely call the Encrypt method, and then base64 encode the array of bytes, and display those:
Byte bout = rsa.Encrypt( System.Text.UTF8Encoding.UTF8.GetBytes(txtPlain.Text), false); txtEncrypt.Text = Convert.ToBase64String( bout );
To decrypt, we'll merely reverse the process, with the exception of reading in the XML format, which includes the public key:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString( txtKey.Text );
And, we'll call the Decrypt method:
Byte bout = rsa.Decrypt( Convert.FromBase64String(txtEncrypt.Text), false);
The W3C (World Wide Web Consortium) currently is working on a specification for defining the encryption of XML documents. This is important work, because the encryption technologies we've been discussing aren't really powerful enough by themselves to do the job when it comes to XML. They lack the ability to discuss how XML should be treated and transformed when encrypted. Most important, they lack a way to state in XML which pieces of XML are encrypted, all in a standard manner.
The beauty of XML is that a single XML document may be passed from person to person, seamlessly across heterogeneous networks. However, in many cases, not every intermediary recipient should have the right to look at parts of or the entire XML document.
For example, imagine you have a health records document that looks like this:
<HealthRecord> <Name>Keith Ballinger</Name> <SSN>123-45-6789</SSN> <IllnessHistory> <Disease>Botulism</Disease> <Disease>Crazy</Disease> <Disease>Fat</Disease> </IllnessHistory> <CurrentMeds> <Med> <Name>Botul-Go!</Name> <Amount>500mg</Amount> <Freq>1d</Freq> </Med> </CurrentMeds> <PaymentInfo> <CCNum>1111-1111-1111-1111</CCNum> <Expires>04/04</Expires> </PaymentInfo> </HealthRecord>
Now, this document may get passed from your doctor, to your insurance company, to your pharmacy. In each case, there are pieces you don't want the others to be able to read. For example, when the pharmacy handles the XML document, you probably want to keep private the information about previous illnesses. XML Encryption permits this by encrypting that element of the document, as shown in Listing 13.1.
<HealthRecord> <Name>Keith Ballinger</Name> <SSN>123-45-6789</SSN> <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <CipherData> <CipherValue>A47383829BCZ</CipherValue> </CipherData> </EncryptedData> <CurrentMeds> <Med> <Name>Botul-Go!</Name> <Amount>500mg</Amount> <Freq>1d</Freq> </Med> </CurrentMeds> <PaymentInfo> <CCNum>1111-1111-1111-1111</CCNum> <Expires>04/04</Expires> </PaymentInfo> </HealthRecord>
Of course, when this document is traveling across the Internet, you may want the entire thing encrypted, as shown in Listing 13.2.
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml"> <CipherData> <CipherValue>123AB456</CipherValue> </CipherData> </EncryptedData>
You can encrypt three things with XML Encryption:
Each of these is kept within an EncryptedData element. It is the Type attribute that distinguishes what exactly is being encrypted. When it is merely the value of a node, the type is http://www.w3.org/2001/04/xmlenc#Content. Listing 13.3 shows an example.
<HealthRecord> <Name>Keith Ballinger</Name> <SSN> <EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#' Type="http://www.w3.org/2001/04/xmlenc#Content"> <CipherData> <CipherValue>123AB456</CipherValue> </CipherData> </EncryptedData> </SSN> <CurrentMeds> <Med> <Name>Botul-Go!</Name> <Amount>500mg</Amount> <Freq>1d</Freq> </Med> </CurrentMeds> <PaymentInfo> <CCNum>1111-1111-1111-1111</CCNum> <Expires>04/04</Expires> </PaymentInfo> </HealthRecord>
To encrypt an entire document, the URI http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml is used, as shown in Listing 13.2. And, to encrypt an element, the URI http://www.w3.org/2001/04/xmlenc#Element is used.
When you encrypt a piece of an XML document, you may want to include information about the key being used. The XML Signature specification includes an XML syntax for describing keys. The next section deals with XML Signature and the concept of message integrity.
An interesting aspect of public key encryption is the ability to verify the integrity of data without necessarily encrypting it. Creating a hash, which is then encrypted with public key encryption, does this. Figure shows the process described thus far.
A receiver of the message, which can be anyone with access to the public key, can then decrypt the signature. This produces a hash. The receiver of the message can then make a hash of the message itself, and see if the two hashes match. If they match, then the receiver can be confident of the integrity of the message data—it has not been tampered with en route. The signature can then be combined with the message, along with the public key needed to send a new message (Figure).
Notice that if the receiver of the message trusts the public key, then this signature does two things:
As it does for encryption, the .NET Framework also contains classes for signing and verifying signatures of data. Let's build a small sample application (see Figure) that will work in a similar manner to the previous encryption samples, for signing and verifying signatures.
To begin with, the same namespace should be imported. We'll also need the IO namespace:
using System.Security.Cryptography; using System.IO;
To create a signature, the SignData method should be used:
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); Byte bout = dsa.SignData( System.Text.UTF8Encoding.UTF8.GetBytes(txtPlain.Text) );
To verify the signature, we'll use the VerifyData method:
Byte bout = dsa.SignData( System.Text.UTF8Encoding.UTF8.GetBytes(txtPlain.Text) );
The XML Signature specification is a W3C recommendation (worked on in conjunction with the Internet Engineering Task Force, or IETF) for signing XML data. Just as with XML Encryption, this is a flexible specification that allows you to sign less than an entire document.
Listing 13.4 shows the typical example given in the XML Signature specification.
<Signature Id="SimpleSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/> <Reference URI="http://www.w3.org/TR/2000/REC-xhtml1-20000126/"> <Transforms> <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue> </Reference> </SignedInfo> <SignatureValue>MC0CFFrVLtRlk= . . . </SignatureValue> <KeyInfo> <KeyValue> <DSAKeyValue> <P> . . . </P><Q> . . . </Q><G> . . . </G><Y> . . . </Y> </DSAKeyValue> </KeyValue> </KeyInfo> </Signature>
As you can see, a signature is contained within a Signature element, which contains three key pieces of information: The SignedInfo element, the SignatureValue, and the KeyInfo. The SignedInfo element indicates the information needed to replicate the signature, including the transform, the canonicalization, the digest method, and the SignatureMethod.
The most interesting of these is the transform and the canonicalization. The transform refers to the pieces of XML within the document that are included in the signature. Often, this is an XPath expression. However, some well-defined XPath transformations can be referred to by URI as well. The canonicalization is the way that the XML should be changed into a format that is semantically the same, but not textually the same. The XML Signature group defined a format for canonicalization called exclusive canonicalization, but it has the drawback of not being a schema-aware format. A better canonicalization would be one that uses schema and the PSVI (Post-Schema Validated Infoset) instead.