Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Visual Studio 2005 (2006) [eng]

.pdf
Скачиваний:
117
Добавлен:
16.08.2013
Размер:
21.9 Mб
Скачать

Chapter 16

<Exponent>AQAB</Exponent>

</RSAKeyValue>

As you will learn later, this public key can be distributed so that it can be used to encrypt and sign information. Of course, the private key should be kept in a secure location.

Creating a Symmetric Key

In the example, only David is going to create a symmetric key that will be shared with Susan after being encrypted and signed using a combination of their asymmetric keys. A more secure approach would be for both parties to generate symmetric keys and for them to be shared and combined into a single key.

Before adding code to generate the symmetric key, extend the dialog so the key can be displayed. Figure 16-2 shows two textboxes that will contain the Initialization Vector and the Key. The data being encrypted is broken down into a series of individually encrypted input blocks. If two adjacent blocks are identical, the process of encrypting a stream of data using a simple key would result in two identical blocks in the encrypted output. Combined with knowledge of the input data, this can be used to recover the key. A solution to this is to use the previous input block as a seed for the encryption of the current block. Of course, at the beginning of the data there is no previous block, which is where the initialization vector is used. This vector can be as important as the key itself, so it should also be kept secure.

Figure 16-2

In the event handler for the Create Symmetric Key button, you need to create an instance of the TripleDESCryptoServiceProvider class, which is the default implementation of the TripleDES algorithm. Create a new instance of the class and then call the GenerateIV and GenerateKey methods to randomly generate a new key and initialization vector. Because these are both byte arrays, convert them to a base-64 string so they can be displayed in the textbox:

Public Class Form1

#Region “Step 1 - Creating Asymmetric Keys” ‘...

#End Region

#Region “Step 2 - Creating Symmetric Keys”

Private Sub BtnCreateSymmetric_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

206

Cryptography

Handles BtnCreateSymmetric.Click

Dim TDES As New TripleDESCryptoServiceProvider()

TDES.GenerateIV()

TDES.GenerateKey()

Me.TxtSymmetricIV.Text = Convert.ToBase64String(TDES.IV)

Me.TxtSymmetricKey.Text = Convert.ToBase64String(TDES.Key)

End Sub

#End Region

End Class

Encrypting and Signing the Key

Now that we have the symmetric key, we need to encrypt it using Susan’s public key and generate a hash value that can be signed using David’s private key. The encrypted key and signature can then be transmitted securely to Susan. Again, appropriate controls have been added to the dialog in Figure 16-3, so you can create and display the encrypted key, the hash value, and the signature.

Figure 16-3

As discussed, this step involves three actions: encrypting the symmetric key, generating a hash value, and generating a signature. Encrypting the symmetric key is again done using an instance of the RSACrypto ServiceProvider class, which is initialized using Susan’s public key. It is then used to encrypt both the initialization vector and the key into appropriate byte arrays. Because you want to create only a single hash and signature, these two byte arrays are combined into a single array, which is pre-pended with the lengths of the two arrays. This is done so the arrays can be separated prior to being decrypted.

The single-byte array created as part of encrypting the symmetric key is used to generate the hash value with the SHA1Managed algorithm. This hash value is then signed again using an instance of the RSACryptoServiceProvider, initialized this time with David’s private key. An instance of the RSAPKCS1SignatureFormatter class is also required to generate the signature from the hash value:

207

Chapter 16

Public Class Form1 #Region “Step 1 & 2” ‘...

#End Region

#Region “Step 3 - Encrypt, Hash and Sign Symmetric Key”

Private Sub BtnEncryptKey_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles BtnEncryptKey.Click

EncryptSymmetricKey()

Me.TxtHashValue.Text = Convert.ToBase64String _

(CreateSymmetricKeyHash(Me.TxtEncryptedKey.Text))

SignSymmetricKeyHash() End Sub

Private Sub EncryptSymmetricKey()

Dim iv, key As Byte()

Dim encryptedIV, encryptedkey As Byte()

iv = Convert.FromBase64String(Me.TxtSymmetricIV.Text) key = Convert.FromBase64String(Me.TxtSymmetricKey.Text)

‘Load the RSACryptoServiceProvider class using ‘only the public key

Dim RSA As New RSACryptoServiceProvider() RSA.FromXmlString(Me.TxtPublicKey1.Text)

‘Encrypt the Symmetric Key encryptedIV = RSA.Encrypt(iv, False) encryptedkey = RSA.Encrypt(key, False)

‘Create a single byte array containing both the IV and Key ‘so that we only need to encrypt and distribute a single value

Dim keyOutput(2 * 4 - 1 + encryptedIV.Length + encryptedkey.Length) As Byte Array.Copy(BitConverter.GetBytes(encryptedIV.Length), 0, keyOutput, 0, 4) Array.Copy(BitConverter.GetBytes(encryptedkey.Length), 0, keyOutput, 4, 4) Array.Copy(encryptedIV, 0, keyOutput, 8, encryptedIV.Length) Array.Copy(encryptedkey, 0, keyOutput, 8 + encryptedIV.Length, _

encryptedkey.Length)

Me.TxtEncryptedKey.Text = Convert.ToBase64String(keyOutput)

End Sub

Private Function CreateSymmetricKeyHash(ByVal inputString As String) As Byte()

‘Retrieve the bytes for this string Dim UE As New UnicodeEncoding()

Dim MessageBytes As Byte() = UE.GetBytes(inputString)

‘Use the SHA1Managed provider to hash the input string Dim SHhash As New SHA1Managed()

Return SHhash.ComputeHash(MessageBytes) End Function

Private Sub SignSymmetricKeyHash()

‘The value to hold the signed value.

208

Cryptography

Dim SignedHashValue() As Byte

‘Load the RSACryptoServiceProvider using the ‘private key as we will be signing

Dim RSA As New RSACryptoServiceProvider RSA.FromXmlString(Me.TxtPrivateKey2.Text)

‘Create the signature formatter and generate the signature

Dim RSAFormatter As New RSAPKCS1SignatureFormatter(RSA)

RSAFormatter.SetHashAlgorithm(“SHA1”)

SignedHashValue = RSAFormatter.CreateSignature _

(Convert.FromBase64String(Me.TxtHashValue.Text))

Me.TxtSymmetricSignature.Text = Convert.ToBase64String(SignedHashValue)

End Sub

#End Region

End Class

At this stage, the encrypted key and signature are ready to be transferred from David to Susan.

Verifying Key and Signature

To simulate the encrypted key and signature being transferred, create additional controls on Susan’s side of the dialog. Shown in Figure 16-4, the Retrieve Key Information button will retrieve the key, signature, and public key from David and populate the appropriate textboxes. In a real application, information could potentially be e-mailed, exported as a file and copied, or sent via a socket connection to a remote application. Essentially, it doesn’t matter how the key and signature are transferred, as they are encrypted to prevent any unauthorized person from accessing the information.

Because the key and signature might have been sent via an unsecured channel, it is necessary to validate that the sender is who they claim to be. This can be done by validating the signature using the public key from the sender. Figure 16-4 shows what the form would look like if the Validate Public Key button is pressed and the signature received is successfully validated against the public key from the sender.

Figure 16-4

209

Chapter 16

The code to validate the received signature is very similar to how the signature was created. A hash value is created from the encrypted key. Using the same algorithm used to create the received signature, a new signature is created. Finally, the two signatures are compared using the VerifySignature method, and the background color is adjusted accordingly:

Public Class Form1 #Region “Step 1 - 3” ‘...

#End Region

#Region “Step 4 - Transfer and Validate Key Information”

Private Sub BtnRetrieveKeyInfo_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles BtnRetrieveKeyInfo.Click Me.TxtRetrievedKey.Text = Me.TxtEncryptedKey.Text Me.TxtRetrievedSignature.Text = Me.TxtSymmetricSignature.Text Me.TxtRetrievedPublicKey.Text = Me.TxtPublicKey2.Text

End Sub

Private Sub BtnValidate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles BtnValidate.Click ‘Create the expected hash from the retrieved public key

Dim HashValue, SignedHashValue As Byte()

HashValue = CreateSymmetricKeyHash(Me.TxtRetrievedKey.Text)

‘Generate the expected signature

Dim RSA As New RSACryptoServiceProvider() RSA.FromXmlString(Me.TxtRetrievedPublicKey.Text)

Dim RSADeformatter As New RSAPKCS1SignatureDeformatter(RSA) RSADeformatter.SetHashAlgorithm(“SHA1”)

SignedHashValue = Convert.FromBase64String(Me.TxtRetrievedSignature.Text)

‘Validate against received signature

If RSADeformatter.VerifySignature(HashValue, SignedHashValue) Then Me.TxtRetrievedKey.BackColor = Color.Green

Else

Me.TxtRetrievedKey.BackColor = Color.Red End If

End Sub #End Region End Class

Now that you have received and validated the encrypted key, the last remaining step before you can use the symmetric key to exchange data is to decrypt the key.

Decrypting the Symmetric Key

Decrypting the symmetric key will return the initialization vector and the key required to use the symmetric key. In Figure 16-5, the dialog has been updated to include the appropriate textboxes to display the decrypted values. These should match the initialization vector and key that were originally created by David.

210

Cryptography

Figure 16-5

To decrypt the symmetric key, reverse the process for encrypting the symmetric key. Start by breaking up the single encrypted byte array into the iv and key byte arrays. To decrypt the key, you again need to create an instance of the RSACryptoServiceProvider class using Susan’s private key. Because the data was encrypted using Susan’s public key, the corresponding private key needs to be used to decrypt the data. This instance is then used to decrypt the initialization vector and the key:

Public Class Form1 #Region “Step 1 - 4” ‘...

#End Region

#Region “Step 5 - Decrypt Symmetric key”

Private Sub BtnDecryptKeyInformation_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles BtnDecryptKeyInformation.Click

Dim iv, key As Byte()

‘Retrieve the iv and key arrays from the single array

Dim keyOutput As Byte() = Convert.FromBase64String(Me.TxtRetrievedKey.Text) ReDim iv(BitConverter.ToInt32(keyOutput, 0) - 1)

ReDim key(BitConverter.ToInt32(keyOutput, 4) - 1) Array.Copy(keyOutput, 8, iv, 0, iv.Length) Array.Copy(keyOutput, 8 + iv.Length, key, 0, key.Length)

‘Load the RSACryptoServiceProvider class using Susan’s private key

211

Chapter 16

Dim RSA As New RSACryptoServiceProvider()

RSA.FromXmlString(Me.TxtPrivateKey1.Text)

‘Decrypt the symmetric key and IV.

Me.TxtDecryptedIV.Text = Convert.ToBase64String(RSA.Decrypt(iv, False))

Me.TxtDecryptedKey.Text = Convert.ToBase64String(RSA.Decrypt(key, False))

End Sub

#End Region

End Class

Sending a Message

Both Susan and David have access to the symmetric key, which they can now use to transmit secure data. In Figure 16-6, the dialog has been updated one last time to include three textboxes and a Send button. Text can be entered in the first textbox. Pressing the Send button will encrypt the text and place the encrypted data in the second textbox. The third textbox will be used to receive information from the other party.

Figure 16-6

212

Cryptography

In the following code, the symmetric key is used to encrypt the text entered in the first textbox, placing the encrypted output in the second textbox. You will notice from the code that the process by which the data is encrypted is different from what you used with an asymmetric algorithm. Asymmetric algorithms are useful for encrypting short amounts of data, which means that they are typically used for keys and pass phrases. Conversely, symmetric algorithms can chain data together, enabling large amounts of data to be encrypted. For this reason they are suitable for a streaming model. When encrypting or decrypting, the input data can come from any stream, be it a file, the network, or an in-memory stream. Here is the code:

Public Class Form1 #Region “Step 1 - 5” ‘...

#End Region

#Region “Step 6 - Sending a Message”

Private Sub btnSendAToB_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles btnSendAToB.Click Me.TxtMessageAEncrypted.Text = EncryptData(Me.TxtMessageA.Text, _

Me.TxtDecryptedIV.Text, _

Me.TxtDecryptedKey.Text)

End Sub

Private Sub BtnSendBToA_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _

Handles BtnSendBToA.Click Me.TxtMessageBEncrypted.Text = EncryptData(Me.TxtMessageB.Text, _

Me.TxtSymmetricIV.Text, _

Me.TxtSymmetricKey.Text)

End Sub

Private Function EncryptData(ByVal data As String, ByVal iv As String, _

ByVal key As String) As String Dim KeyBytes As Byte() = Convert.FromBase64String(key)

Dim IVBytes As Byte() = Convert.FromBase64String(iv)

‘Create the output stream

Dim strm As New IO.MemoryStream

‘Create the TripleDES class to do the encryption Dim Triple As New TripleDESCryptoServiceProvider()

‘Create a CryptoStream with the output stream and encryption algorithm Dim CryptStream As New CryptoStream(strm, _

Triple.CreateEncryptor(KeyBytes, IVBytes), _ CryptoStreamMode.Write)

‘Write the text to be encrypted

Dim SWriter As New StreamWriter(CryptStream) SWriter.WriteLine(data)

SWriter.Close()

Return Convert.ToBase64String(strm.ToArray)

End Function

#End Region

End Class

213

Chapter 16

To encrypt the text message to be sent, create another instance of the TripleDESCryptoService Provider, which is the same provider you used to create the symmetric key. This, combined with the memory output stream, is used to create the CryptoStream. A StreamWriter is used to provide an interface for writing the data to the stream. The content of the memory stream is the encrypted data.

Receiving a Message

The final stage in this application is for the encrypted data to be transmitted and decrypted. To wire this up, trap the TextChanged event for the encrypted data textboxes. When this event is triggered, the encrypted data will be copied to the receiving side and decrypted, as shown in Figure 16-7. This simulates the information being sent over any unsecured channel.

Figure 16-7

Decrypting the encrypted data is done the same way as the data was encrypted. An instance of the TripleDESCryptoServiceProvider is used in conjunction with the memory stream, based on the encrypted data, to create the CryptoStream. Using a StreamReader, the decrypted data can be read from the stream:

Public Class Form1 #Region “Step 1 - 6” ‘...

214

Cryptography

#End Region

#Region “Step 7 - Receiving a Message”

Private Sub TxtMessageAEncrypted_TextChanged(ByVal sender As Object, _

ByVal e As System.EventArgs) _

Handles TxtMessageAEncrypted.TextChanged

Me.TxtReceivedMessageFromA.Text = DecryptData( _

Me.TxtMessageAEncrypted.Text, _

Me.TxtSymmetricIV.Text, _

Me.TxtSymmetricKey.Text)

End Sub

Private Sub TxtMessageBEncrypted_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) _

Handles TxtMessageBEncrypted.TextChanged Me.TxtReceivedMessageFromB.Text = DecryptData( _

Me.TxtMessageBEncrypted.Text, _ Me.TxtDecryptedIV.Text, _ Me.TxtDecryptedKey.Text)

End Sub

Private Function DecryptData(ByVal data As String, ByVal iv As String, _

ByVal key As String) As String Dim KeyBytes As Byte() = Convert.FromBase64String(key)

Dim IVBytes As Byte() = Convert.FromBase64String(iv)

‘Create the input stream from the encrypted data

Dim strm As New IO.MemoryStream(Convert.FromBase64String(data))

‘Create the TripleDES class to do the decryption Dim Triple As New TripleDESCryptoServiceProvider()

‘Create a CryptoStream with the input stream and decryption algorithm Dim CryptStream As New CryptoStream(strm, _

Triple.CreateDecryptor(KeyBytes, IVBytes), _ CryptoStreamMode.Read)

‘Read the stream.

Dim SReader As New StreamReader(CryptStream) Return SReader.ReadToEnd

End Function #End Region

End Class

As demonstrated in this example, you can use asymmetric keys to authenticate the communicating parties and securely exchange a symmetric key. This ensures non-repudiation, as only the authenticated parties have access to the key, and the information is securely encrypted to achieve confidentiality and data integrity. Using a combination of algorithms you have achieved the goals of cryptography.

Miscellaneous

So far, this chapter has covered the principles and algorithms that make up the primary support for cryptography within the .NET Framework. To round out this discussion, the following sections describe both how to use the SecureString class and how to use a key container to store a private key.

215