前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET中的密钥加密

.NET中的密钥加密

作者头像
MelodyS
发布2018-03-12 11:51:12
2.9K0
发布2018-03-12 11:51:12

对称密码学(密钥加密)

介绍

本教程将演示如何通过System.Security.Cryptography在.NET Framework 1.1中实现对称加密/密钥加密。

背景

加密技术研究的是如何加密数据从而达到以下目的:

  1. 任何非法得到它的人将无法解读它。
  2. 您预期的接收方将能够轻松解读它。

从某种意义上说,它也掩盖了大量恶行,因为那些有恶意的人无法阅读或者修改针对其他接收方的消息。

加密术语中的重要术语

将实际消息转换为编码形式(编码)被称为加密,并且反向转换(解码)被称为解密。要加密的消息称为纯文本或消息文本。加密过程的输出称为密文或密码电文。发送消息文本的人称为发送方,即将接收消息文本的人称为接收方。以纯文本而不是密文形式向接收方发送消息被称为在明文中发送。打算窃取发送方和接收方之间的密文的人称为入侵者或攻击者。用于执行加密的这组数据转换集合被称为加密算法或简称为密码,通常,该转换由一个或多个密钥参数化。破译密码的技术被称为密码分析,开发和破译密码的技术统称为密码学。

密码学的类型

有两种类型的加密技术。

  • 对称加密
  • 公钥加密

本文中我们只讨论对称加密算法。

对称加密是最早开始使用的非常古老的加密方案之一,也称为密钥加密。在这种方案中,发送方和接收方共享相同的加密和解密密钥。显然,这种方案使用旧的基于数学的替代和置换函数来替代明文,达到加密和解密的效果,这就是为什么将该算法的名字称为对称加密方案。该方案如下图所示:

.NET Framework为我们提供了以下密钥加密算法:

  • DES CryptoServiceProvider
  • RC2 CryptoServiceProvider
  • Rijndael Managed / AES(高级加密标准)
  • TripleDESCryptoServiceProvider

分组密码

分组密码以纯粹的组合方式进行操作,在逐块计算的基础上将固定变换应用于大块明文,最常见的块大小为八个字节。由于每个块都经过了大量处理,分块密码提供了更高级别的安全性。但是,分组密码算法往往执行得更慢。

分组密码对每个块使用相同的加密算法。正因为如此,当使用相同的密钥和算法进行加密时,明文块总是会返回相同的密文。由于此行为可用于破解密码,因此引入了密码模式,可根据早期块加密的反馈修改加密过程。修改过后的加密算法比简单的块加密提供更高的安全级别。

分组密码模式
  • 密码块链(CBC)模式引入了一种反馈机制。在每个明文块被加密之前,它通过按位异或运算与前一个块的密文相结合。这确保即使明文包含许多相同的块,它们也将分别加密成为不同的密文块。初始化向量在块被加密之前通过按位异或运算与第一个明文块组合。
  • 密码反馈(CFB)模式处理明文的小增量作为密文,而不是一次处理整个块。该模式使用一个长度为一个块的移位寄存器,并分成若干部分。例如,如果块大小为8个字节,并且每次处理一个字节,则移位寄存器分为8个部分。
  • 电子密码本(ECB)模式单独地加密每个块。这意味着任何相同且处于相同消息中的明文或者使用相同密钥加密的不同消息块将被转换为相同的密文块。

填充

大多数明文消息不包含大量填充完整块的字节。通常没有足够的字节来填充最后一个块。发生这种情况时,将向文本添加填充字符串。例如,如果块长度为64位,最后一个块只包含40位,则会添加24位填充字符串。

填充模式
  • PKCS#7填充字符串由一系列字节组成,每个字节等于所添加的填充字节总数。例如,如果需要添加24位(3个字节)来进行填充,则填充字符串为“03 03 03”。
  • 填充字符串由设置为零的字节组成。

我们将只使用TripleDES和Rinjndael算法。

我们将在.NET Framework 1.1中实现这个概念。我们将以Radix / Base64格式加解密数据以实现标准化。启动一个新的Windows应用程序项目并分配名称“数字签名”并执行以下操作。

在FORM1上添加以下控件(界面应该像下图所示的形式:为了更清晰的下载代码)。

  1. 命名为Session Key的Groupbox,其中包含以下控件:
    • 带有文本的标签控件“选择一个关键短语以派生密钥或保留空白以导出随机会话密钥”。
    • 有一个名称为“TxtKeyPharse”的文本框控件,并将其Multiline属性设置为true。
  2. 命名为Padding Mode的Groupbox,其中包含以下控件:
    • 命名为Radiobutton2的单选按钮,其文本属性为“零”。
    • 命名为Radiobutton5的单选按钮,其文本属性为“PKCS7(默认)”。
  3. 命名为Block Mode的Groupbox,其中包含以下控件:
    • 命名为Radiobutton1的单选按钮,其文本属性为“CBC(Cipher BlockChaining)默认模式”。
    • 命名为Radiobutton3的单选按钮,其文本属性为“ECB(电子码本)”。
    • 命名为Radiobutton4的单选按钮,其文本属性为“CFB(密码反馈)”。
  4. Groupbox上有以下控件:
    • 三个文本框命名为txtPlaintex,TxtEncrypt,TxtDecrypt。 后面两个将只读属性设置为true。
    • 一个名为Label1并带有Text属性的标签控件:“在此输入纯文本”。
    • 一个名为Button1的按钮,Text属性为“加密”。
    • 一个名为Button3的按钮,Text属性为“解密”。
    • Groupbox命名密码模式,其中包含以下控件:
      • 命名为Radiobutton10的单选按钮,其文本属性为“TripleDES”。
      • 命名为Radiobutton11的单选按钮,其文本属性为“Rinjndael / AES”。
  5. 底部的标签控件Label3显示所选密码的有效密钥/块大小。

以上就是现有的界面了。让我们开始编程吧:

“Form1”的代码清单:
代码语言:txt
复制
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

所有代码都做了什么?

  • 根据是否输入密钥文本,然后选择适当的填充,密码和算法,加密按钮将会为您加密文本。
  • 之后按解密按钮将以Base64格式解密文本。
  • 有关详细说明请参阅代码注释。

现在执行以下操作:

  • 为全局变量声明添加模块名称“Global”。
Module“Global”的代码清单:
代码语言:txt
复制
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
评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对称密码学(密钥加密)
  • 介绍
  • 背景
    • 加密术语中的重要术语
    • 密码学的类型
    • 分组密码
      • 分组密码模式
      • 填充
        • 填充模式
          • “Form1”的代码清单:
          • 所有代码都做了什么?
            • Module“Global”的代码清单:
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档