本教程将演示如何通过System.Security.Cryptography在.NET Framework 1.1中实现对称加密/密钥加密。
加密技术研究的是如何加密数据从而达到以下目的:
从某种意义上说,它也掩盖了大量恶行,因为那些有恶意的人无法阅读或者修改针对其他接收方的消息。
将实际消息转换为编码形式(编码)被称为加密,并且反向转换(解码)被称为解密。要加密的消息称为纯文本或消息文本。加密过程的输出称为密文或密码电文。发送消息文本的人称为发送方,即将接收消息文本的人称为接收方。以纯文本而不是密文形式向接收方发送消息被称为在明文中发送。打算窃取发送方和接收方之间的密文的人称为入侵者或攻击者。用于执行加密的这组数据转换集合被称为加密算法或简称为密码,通常,该转换由一个或多个密钥参数化。破译密码的技术被称为密码分析,开发和破译密码的技术统称为密码学。
有两种类型的加密技术。
本文中我们只讨论对称加密算法。
对称加密是最早开始使用的非常古老的加密方案之一,也称为密钥加密。在这种方案中,发送方和接收方共享相同的加密和解密密钥。显然,这种方案使用旧的基于数学的替代和置换函数来替代明文,达到加密和解密的效果,这就是为什么将该算法的名字称为对称加密方案。该方案如下图所示:
.NET Framework为我们提供了以下密钥加密算法:
分组密码以纯粹的组合方式进行操作,在逐块计算的基础上将固定变换应用于大块明文,最常见的块大小为八个字节。由于每个块都经过了大量处理,分块密码提供了更高级别的安全性。但是,分组密码算法往往执行得更慢。
分组密码对每个块使用相同的加密算法。正因为如此,当使用相同的密钥和算法进行加密时,明文块总是会返回相同的密文。由于此行为可用于破解密码,因此引入了密码模式,可根据早期块加密的反馈修改加密过程。修改过后的加密算法比简单的块加密提供更高的安全级别。
大多数明文消息不包含大量填充完整块的字节。通常没有足够的字节来填充最后一个块。发生这种情况时,将向文本添加填充字符串。例如,如果块长度为64位,最后一个块只包含40位,则会添加24位填充字符串。
我们将只使用TripleDES和Rinjndael算法。
我们将在.NET Framework 1.1中实现这个概念。我们将以Radix / Base64格式加解密数据以实现标准化。启动一个新的Windows应用程序项目并分配名称“数字签名”并执行以下操作。
在FORM1上添加以下控件(界面应该像下图所示的形式:为了更清晰的下载代码)。
以上就是现有的界面了。让我们开始编程吧:
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Public Class Form1
Inherits System.Windows.Forms.Form
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'set defaults inilizations for
Me.RadioButton1.Checked = True 'padding,
Me.RadioButton5.Checked = True 'cipher modes
Me.RadioButton10.Checked = True 'Algorithm
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles
Button3.Click
Dim fromEncrypt() As Byte, roundtrip As String
Dim d As String
'check TripleDEs was selected
If Me.RadioButton10.Checked = True Then
' Now decryption
Dim decryptor As ICryptoTransform = Tdes.CreateDecryptor(MyKey, MyIV)
'Now decrypt the previously encrypted message using the decryptor
' obtained in the above step.
'use main memory for I/O.
Dim msDecrypt As New MemoryStream(Encrypted1)
'get CryptoStream for decrypted data
Dim csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
fromEncrypt = New Byte(Encrypted1.Length) {}
'Read the data out of the crypto stream.
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length)
'Convert the byte array back into a string.
roundtrip = Encoding.ASCII.GetString(fromEncrypt)
TxtDecrypt.Text = (roundtrip)
'get valid TripleDES key (or Block) sizes through KeySizes enumrator
Dim myKeySizes1 As KeySizes
For Each myKeySizes1 In Tdes.LegalKeySizes
With myKeySizes1
d = "Triple DES Legal key (or Block) sizes in bits:" & vbCrLf _
& "Max=" & .MaxSize & " bits " & _
"(" & (.MaxSize / 8) & " bytes)" & vbCrLf _
& "Min=" & .MinSize & " bits " & _
"(" & (.MinSize / 8) & " bytes)" & vbCrLf _
& "Skip=" & .SkipSize & " bits " & _
"(" & (.SkipSize / 8) & " bytes)"
End With
Next
'display them
MsgBox(d, MsgBoxStyle.Information)
Exit Sub
End If ' 10
'check TripleDEs was selected
If Me.RadioButton11.Checked = True Then
' Now decryption
Dim decryptor As ICryptoTransform = Rinjndael.CreateDecryptor(MyKey, MyIV)
'Now decrypt the previously encrypted message using the decryptor
' obtained in the above step.
'use main memory for I/O.
Dim msDecrypt As New MemoryStream(Encrypted1)
'get CryptoStream for decrypted data
Dim csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
fromEncrypt = New Byte(Encrypted1.Length) {}
'Read the data out of the crypto stream.
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length)
'Convert the byte array back into a string.
roundtrip = Encoding.ASCII.GetString(fromEncrypt)
TxtDecrypt.Text = (roundtrip)
'get valid Rinjndael key (or Block) sizes through KeySizes enumrator
Dim myKeySizes As KeySizes
For Each myKeySizes In Rinjndael.LegalKeySizes
With myKeySizes
d = "Rijndael/AES Legal key (or Block) sizes in bits:" & vbCrLf _
& "Max=" & .MaxSize & " bits " & _
"(" & (.MaxSize / 8) & " bytes)" & vbCrLf _
& "Min=" & .MinSize & " bits " & _
"(" & (.MinSize / 8) & " bytes)" & vbCrLf _
& "Skip=" & .SkipSize & " bits " & _
"(" & (.SkipSize / 8) & " bytes"
End With
Next
'display them
MsgBox(d, MsgBoxStyle.Information)
Exit Sub
End If '11
End Sub
Private Sub Button1_Click_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim fromEncrypt() As Byte
Dim encrypted() As Byte
Dim toEncrypt() As Byte
Dim roundtrip As String
Dim key1() As Byte
Dim abytSalt() As Byte
Dim abytKey() As Byte
Dim str As String
'first set ICryptoTransform for encryption later
Dim encryptor As ICryptoTransform
'RandomNumberGenerator
Dim rng As RandomNumberGenerator = RandomNumberGenerator.Create()
' check to see if no key pharse is entered
If Me.TxtKeyPharse.Text = "" Then
'derive random key
Keypharse = False
End If
' check to see CFB mode is selected it will not work on rinjndael
' convert to default
If Me.RadioButton4.Checked = True Then
PdMode = CipherMode.CBC
End If
If Keypharse Then 'if Enter key pharse in textbox
'asssgin key to string variable
str = Me.TxtKeyPharse.Text
If Me.RadioButton10.Checked = True Then 'seleect TDES
' Tdes is used so set key and iv/salt arrays to valid size
ReDim abytSalt(11) '12 bit Salt
ReDim abytKey(23) '24 bit key
'use PasswordDeriveBytes instance to derive a key
Dim pdb As New PasswordDeriveBytes(str, abytSalt)
'fill salt array to specfied size
rng.GetBytes(abytSalt)
'Get the same amount of bytes as the current abytKey length
abytKey = pdb.GetBytes(abytKey.Length)
'set padding mode
Tdes.Padding = Padd
'set cipher mode
Tdes.Mode = PdMode
'assign key
Tdes.Key = abytKey
'set key
MyKey = Tdes.Key
'Get IV.
Tdes.GenerateIV()
'set iv
MyIV = Tdes.IV
'CreateEncryptor for encryption later
encryptor = Tdes.CreateEncryptor(MyKey, MyIV)
End If ' 10
If Me.RadioButton11.Checked = True Then 'Rijndael is selected
'Rinjndael is used so set key and iv/salt arrays to valid size
' A good rule-of-thumb is to make the salt 1/2 the length of the key.
ReDim abytSalt(15) '16 bit salt
ReDim abytKey(31) '32 bit key
'use PasswordDeriveBytes instance to derive a key
Dim pdb As New PasswordDeriveBytes(str, abytSalt)
'fill salt array to specfied size
rng.GetBytes(abytSalt)
'Get the same amount of bytes as the current abytKey length
abytKey = pdb.GetBytes(abytKey.Length)
'set padding mode
Rinjndael.Padding = Padd
'set cipher mode
Rinjndael.Mode = PdMode
' assign key
Rinjndael.Key = abytKey
'set key
MyKey = Rinjndael.Key
'Get IV.
Rinjndael.GenerateIV()
'set IV
MyIV = Rinjndael.IV
'CreateEncryptor for encryption later
encryptor = Rinjndael.CreateEncryptor(MyKey, MyIV)
End If '11
Else 'no Keypharse is selected then derive random key and IV
'see which alogrithm is seected
If Me.RadioButton10.Checked = True Then 'TDES is used
'set padding mode
Tdes.Padding = Padd
'set cipher mode
Tdes.Mode = PdMode
'genrate random key
Tdes.GenerateKey()
'genrate random iv
Tdes.GenerateIV()
'set values
MyKey = Tdes.Key
'set iv
MyIV = Tdes.IV
'CreateEncryptor for encryption later
encryptor = Tdes.CreateEncryptor(MyKey, MyIV)
End If
If Me.RadioButton11.Checked = True Then 'Rinjndael is used
'set padding mode
Rinjndael.Padding = Padd
'set cipher mode
Rinjndael.Mode = PdMode
'genrate random key
Rinjndael.GenerateKey()
'genrate random iv
Rinjndael.GenerateIV()
'set values
MyKey = Rinjndael.Key
MyIV = Rinjndael.IV
'CreateEncryptor for encryption later
encryptor = Rinjndael.CreateEncryptor(MyKey, MyIV)
End If
End If 'Keypharse
'Encrypt the data. Whether TripleDES or Rinjndael is selected
'use main memory for I/O.
Dim msEncrypt As New MemoryStream
'get CryptoStream for encrypted data
Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, _
CryptoStreamMode.Write)
'Convert the data to a byte array.
toEncrypt = Encoding.ASCII.GetBytes(Me.txtPlaintex.Text)
'Write all data to the crypto stream and flush it.
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
csEncrypt.FlushFinalBlock()
'Get encrypted array of bytes.
encrypted = msEncrypt.ToArray()
Encrypted1 = encrypted
'convert to base64/Radix form
TxtEncrypt.Text = Convert.ToBase64String(encrypted)
End Sub
Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
Handles RadioButton1.CheckedChanged, RadioButton3.CheckedChanged, _
RadioButton4.CheckedChanged
'return selected cipher mode number
PdMode = Pmode(sender.tabindex)
End Sub
Private Sub RadioButton6_CheckedChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
Handles RadioButton6.CheckedChanged, RadioButton5.CheckedChanged, _
RadioButton2.CheckedChanged
'return selected padding mode number
Padd = Padding(sender.tabindex)
End Sub
Private Sub TxtKeyPharse_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles
TxtKeyPharse.TextChanged
'set to true if dat is enterned to know in future that key
'will be derived from key phrase
Keypharse = True
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles
Button4.Click
Help.ShowHelp(Me, Tut)
End Sub
End Class
现在执行以下操作:
Imports System.Security.Cryptography
Imports System.Text
Module Global
'creates new instance of Tripldes
Public Tdes As New TripleDESCryptoServiceProvider
'creates new instance of Rinjndael
Public Rinjndael As New RijndaelManaged
'Stores key whether from phrase or random
Public MyKey() As Byte
'Stores random IV
Public MyIV() As Byte
'store encrypted data
Public Encrypted1() As Byte
'store decrypted data
Public Decrypted1() As Byte
'Unicode encoding instnace
Public MyEncoder As New UTF8Encoding
'flag to remember that key was derived from phrase
Public Keypharse As Boolean = False
'stores padding mode
Public Padd As Int16
'Store cipher mode
Public PdMode As Int16
'Function that will return selected Padding mode number
Public Function Padding(ByVal mode As Int16) As Int16
Padding = mode
Return Padding
End Function
'Function that will return selected Cipher block mode number
Public Function Pmode(ByVal mode As Int16) As Int16
Pmode = mode
Return Pmode
End Function
End Module 'global