.NET中的密钥加密

对称密码学(密钥加密)

介绍

本教程将演示如何通过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”的代码清单:

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”的代码清单:

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

本文的版权归 MelodyS 所有,如需转载请联系作者。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏流媒体

MediaCodec进行AAC编解码(文件格式转换)

AAC,全称Advanced Audio Coding,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性...

1194
来自专栏逸鹏说道

ExecuteReader在执行有输出参数的存储过程时拿不到输出参数

异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 后期会在博客首发更新:http://dnt...

3297
来自专栏跟着阿笨一起玩NET

ZPL打印中文信息

  相信各位在实际的项目中,需要开发打条码模块的也会有不少,很多同行肯定也一直觉得斑马打印机很不错,但是ZPL打印中文字符很麻烦。如果购买字体卡,或者通过COD...

10
来自专栏逆向与安全

网秦安全盾 原理分析

环境: 手机: 中兴 u887 系统 android2.3.5 调试器: IDA pro 6.5

600
来自专栏LeoXu的博客

[翻译]Ext JS 教程-ExtJS 4中的数据包(Package)

数据包(data package)是用来加载和保存你应用程序中的数据的东西,包含41个类,但是其中有三个类比所有其他类更加重要——Model,Store和Ext...

752
来自专栏Android学习之路

Android中关于UUID的操作

2336
来自专栏Java Web

JavaFX-TableView详解

前言 最近在着手一个学生管理系统的编写,涉及到TableView的使用,这前前后后的也有了些经验和想法想要记录和分享一下(事实上我正在想要用html网页代替界面...

3376
来自专栏落影的专栏

iOS面试题----实践向

前言 很多人都说熟悉UIKit,那对于常见的API是否熟悉? 多线程是前端经久不衰的考点。 大家对于Block的weak-strong dance都耳熟能详...

4037
来自专栏积累沉淀

初识HtmlParser

1、概念 网页解析,即程序自动分析网页内容、获取信息,从而进一步处理信息。 htmlparser包提供方便、简洁的处理html文件的方法,它将html页面中...

1845
来自专栏青蛙要fly的专栏

项目需求讨论-Vlayout来快速构建及扩展复杂界面

大家好,今天又带来了项目中具体遇到的需求。做一个首界面,该首界面有很多功能块,同时这些功能块是动态的,因为登录的人的权限的不同,会显示不同的功能块,因为功能模块...

632

扫描关注云+社区