net文本加密
.Net软件的特点,一些强大的编译工具可以对.Net可执行文件进行反编译操作,并得出相应的IL代码甚至是源代码。即使是采用混淆工具以及强命名工具也不能从根本上解决问题,代码依然会很容易地被Reflectoer等工具反编译源代码。
软件加密狗:威步(WIBU)的CodeMeter,AxProtector(for.net)两款软件加密狗性能非常不错
反编译的问题,与传统的代码混淆工具(Obfuscator)不同,AxProtector可以完全阻止对.NET
程序集(由
C#,
VB.NET,
Delphi.NET,
ASP.Net…
等语言编写)的反编译。通俗的讲,AxProtector在破解者和您的
.NET
代码之间构建了强大的防破解保护屏障,生成一个基于
Windows
的而不是基于
MSIL
的兼容格式文件。原始的
.NET
代码完整的被加密后封装在本地代码内,无论何时都不会释放到硬盘,对于破解者是不可见的。
与单纯的.net加密软件不同,AxProtector与CodeMeter硬件加密狗配套餐使用,采用了更为严密的密钥管理,及最先进的AES、RSA、ECC等加密算法存储或传输密钥,保证通讯安全。
.Net代码编译后生成的
.class
中包含有源代码中的所有信息(不包括注释),尤其是在其中保存有调试信息的时候。所以一个按照正常方式编译的.class
文件可以非常轻易地被反编译。一般软件开发商会采用一种叫做混淆器的工具。混淆器的作用是对编译好的代码进行混淆,使得其无法被反编译或者反编译后的代码混乱难懂。由于混淆器只是混淆了方法名称或流程,而不能防止源代码被反编译,因此混淆器的作用只是增加了反编译的难度,最终的结果也是治标不治本。对于一些掌握工具的人来说几乎还是透明的。AxProtector是一款真正意义的加密源代码、防止反编译的.net软件加密软件。
AxProtector加密了.net原代码,任何时候原代码都不可能被还原到硬盘当中。采用AxProtector加密后的.net代码只有在程序调用或执行某一段函数的时候,才能通过AxProtectorClass在内存中解密后返回到程序中执行,运行之后迅速立即加密。这种随机加密、按需解密原代码的功能,能很好的防止.Net程序的反编译,同时能够很好地防止API加密点被摘除。有效地保证了源代码的执行效率和安全性。
2. 使用.net内置的DES进行加密
好了,明白了它的License种类,我们得看看它是如何验证合法的License的,换句话说就是它的License是如何构成的。它通过定位/bin目录下的License文件,License文件由类名(FreeTextBox)+ “.lic”构成。FreeTextBox.Lic文件内容分三个部分,第一部分为明文FreeTextBox License,也就是类名+ License”字符串,第二部分为[License种类的加密文本],加密算法采用的.NET内置的DES,用于DES加密的密钥和偏移量均为{ 0x39, 0x48, 0x42, 50, 0x38, 0x31, 70, 0x36 },当然它不是直接对文本加密的,做了一个小小的处理,这个处理就是加上原文本的长度,并预留5位,不够则补零,例如字符串DistributionLicense,那用于加密的就是00019DistributionLicense,因为字符串DistributionLicense的长度是19位,前面还有3个空位就补3个零。这样加密后的结果就是=,注意需要用[]分隔,FreeTextBox设计者出于方便使用正则匹配所以使用[]来分隔,第三部分就是你注册标识的加密文本,当然也有[],处理方式跟第二部分的一样,例如我的域名为Ycweb.Net,我想以此作为标识来生成License,于是对字符串00009Ycweb.Net进行DES加密,结果为tyn3Gf1Y5GH2VphAJ2U++g==,所以综合这个三个部分的内容,就构成了一个完整的License文件内容,整理一下就是: FreeTextBox License [=] [tyn3Gf1Y5GH2VphAJ2U++g==] 这是Distribution的License,如果是Professional的License,内容就是: FreeTextBox License [tyn3Gf1Y5GH2VphAJ2U++g==] 补充: 我现在是要加密的方法,求一个函数,将原文:00019DistributionLicense,加密为密文:=],不知所谓,连内容都不看就回答了 补充: 又多一个不看内容的,文章里面不是说了吗:
3. 用.net实现文件夹加密
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO ;
using System.Diagnostics ;
using System.Threading ;
namespace 伪装文件夹
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.FolderBrowserDialog foldeOpen;
private System.Windows.Forms.TextBox AfoldePath;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button AddPassword;
private System.Windows.Forms.ComboBox comboBox1;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.AddPassword = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.AfoldePath = new System.Windows.Forms.TextBox();
this.foldeOpen = new System.Windows.Forms.FolderBrowserDialog();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.BackColor = System.Drawing.Color.Transparent;
this.groupBox1.Controls.Add(this.comboBox1);
this.groupBox1.Controls.Add(this.AddPassword);
this.groupBox1.Controls.Add(this.button1);
this.groupBox1.Controls.Add(this.AfoldePath);
this.groupBox1.Location = new System.Drawing.Point(6, 6);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(276, 78);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "加密";
//
// comboBox1
//
this.comboBox1.Items.AddRange(new object[] {
"我的电脑",
"我的文档",
"拨号网络",
"控制面板",
"计划任务",
"打印机",
"记事本",
"网络邻居",
"回收站",
"公文包",
"字体 ",
"Web 文件夹"});
this.comboBox1.Location = new System.Drawing.Point(12, 48);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(174, 20);
this.comboBox1.TabIndex = 15;
this.comboBox1.Text = "伪装类型";
//
// AddPassword
//
this.AddPassword.BackColor = System.Drawing.Color.Transparent;
this.AddPassword.ForeColor = System.Drawing.Color.Red;
this.AddPassword.Location = new System.Drawing.Point(192, 48);
this.AddPassword.Name = "AddPassword";
this.AddPassword.TabIndex = 14;
this.AddPassword.Text = "伪装";
this.AddPassword.Click += new System.EventHandler(this.AddPassword_Click);
//
// button1
//
this.button1.Location = new System.Drawing.Point(192, 20);
this.button1.Name = "button1";
this.button1.TabIndex = 8;
this.button1.Text = "文件夹路径";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// AfoldePath
//
this.AfoldePath.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(255)), ((System.Byte)(224)), ((System.Byte)(192)));
this.AfoldePath.Location = new System.Drawing.Point(12, 20);
this.AfoldePath.Name = "AfoldePath";
this.AfoldePath.ReadOnly = true;
this.AfoldePath.Size = new System.Drawing.Size(174, 21);
this.AfoldePath.TabIndex = 7;
this.AfoldePath.Text = "";
//
// groupBox2
//
this.groupBox2.BackColor = System.Drawing.Color.Transparent;
this.groupBox2.Controls.Add(this.button2);
this.groupBox2.Controls.Add(this.button3);
this.groupBox2.Controls.Add(this.textBox1);
this.groupBox2.Location = new System.Drawing.Point(6, 90);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(276, 76);
this.groupBox2.TabIndex = 1;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "解密";
//
// button2
//
this.button2.ForeColor = System.Drawing.Color.Red;
this.button2.Location = new System.Drawing.Point(192, 48);
this.button2.Name = "button2";
this.button2.TabIndex = 14;
this.button2.Text = "解密";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.ForeColor = System.Drawing.Color.Red;
this.button3.Location = new System.Drawing.Point(192, 20);
this.button3.Name = "button3";
this.button3.TabIndex = 8;
this.button3.Text = "文件夹路径";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// textBox1
//
this.textBox1.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(128)), ((System.Byte)(255)), ((System.Byte)(128)));
this.textBox1.Location = new System.Drawing.Point(12, 24);
this.textBox1.Name = "textBox1";
this.textBox1.ReadOnly = true;
this.textBox1.Size = new System.Drawing.Size(174, 21);
this.textBox1.TabIndex = 7;
this.textBox1.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(288, 174);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "伪装文件夹";
this.groupBox1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
if(foldeOpen.ShowDialog ()==DialogResult.OK )
{
try
{
if(foldeOpen.SelectedPath .Substring (3,10)=="Documents ")
{
MessageBox.Show ("我不建议C盘下的文件夹伪装,这样可能会导致系统出问题");
}
else
{
AfoldePath.Text =foldeOpen.SelectedPath;
}
}
catch
{
if(foldeOpen.SelectedPath.Length >=4)
{
AfoldePath.Text =foldeOpen.SelectedPath;
}
else
{
MessageBox.Show ("无法对盘符进行伪装.");
}
}
}
}
private void AddPassword_Click(object sender, System.EventArgs e)
{
try
{
ProcessStartInfo p3=new ProcessStartInfo ("attrib.exe",@"-s -r -a -h "+AfoldePath.Text);
p3.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p3);
ProcessStartInfo p1=new ProcessStartInfo ("attrib.exe",@"-s -r -a -h "+AfoldePath.Text+@"\desktop.ini");
p1.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p1);
StreamWriter sw2=new StreamWriter (AfoldePath.Text+@"\desktop.ini" );
sw2.WriteLine (@"[.ShellClassInfo]" );
sw2.WriteLine ("CLSID="+GetPasType());
sw2.Close ();
ProcessStartInfo p =new ProcessStartInfo ("attrib.exe",@"+s +a +h +r "+AfoldePath.Text+@"\desktop.ini");
p.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p);
ProcessStartInfo p2=new ProcessStartInfo ("attrib.exe",@"+s +r "+AfoldePath.Text);
p2.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p2);
}
catch(Exception ee)
{
MessageBox.Show (ee.Message .ToString ());
}
}
private string GetPasType()
{
int index=comboBox1.SelectedIndex;
switch (index)
{
case 0: return @"{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
case 1: return @"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
case 2: return @"{992CFFA0-F557-101A-88EC-00DD010CCC48}";
case 3: return @"{21EC2020-3AEA-1069-A2DD-08002B30309D}";
case 4: return @"{D6277990-4C6A-11CF-8D87-00AA0060F5BF}";
case 5: return @"{2227A280-3AEA-1069-A2DE-08002B30309D}";
case 6: return @"{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}";
case 7: return @"{208D2C60-3AEA-1069-A2D7-08002B30309D}";
case 8: return @"{645FF040-5081-101B-9F08-00AA002F954E}";
case 9: return @"{85BBD920-42A0-1069-A2E4-08002B30309D}";
case 10: return @"{BD84B380-8CA2-1069-AB1D-08000948F534}";
case 11: return @"{BDEADF00-C265-11d0-BCED-00A0C90AB50F}";
}
return @"{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
}
private void button3_Click(object sender, System.EventArgs e)
{
if(foldeOpen.ShowDialog ()==DialogResult.OK )
{
textBox1.Text =foldeOpen.SelectedPath;
}
}
private void button2_Click(object sender, System.EventArgs e)
{
try
{
ProcessStartInfo p2=new ProcessStartInfo ("attrib.exe",@"-s -r -a -h "+textBox1.Text);
p2.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p2);
ProcessStartInfo p1=new ProcessStartInfo ("attrib.exe",@"-s -h -r "+textBox1.Text+@"\desktop.ini");
p1.WindowStyle= System.Diagnostics.ProcessWindowStyle.Hidden;
Process.Start (p1);
System.Threading.Thread.Sleep(1000);
File.Delete (textBox1.Text+@"\desktop.ini");
MessageBox.Show ("解密成功.");
}
catch(Exception ee)
{
MessageBox.Show (ee.Message.ToString ());
}
}
}
}
4. .NET中的密码学--对称加密
介绍
在 net之前 使用非托管的Win APIs加密解密数据是一件非常痛苦的事情 为了这个加密解密的目的 NET配置了一组类(和命名空间) 现在你有很多类可以使用每种不同的算法保护你的数据 在 NET里面Crypttography命名空间下又定义了 种类型的加密方法 他们是AsymmetricAlgorithm SymmetricAlgorithm和HashAlgorithm 所有的这些类(和 NET密码学类型)都是抽象类 我们今天将要描述SymmetricAlgorithm 剩下的将在以后的文章中陆续讲解
注意 虽然大多数托管代码里的加密类实现使用了很多CryptoAPI库
SymmetricAlgorithms基础
对称算法使用用户的密钥(密码)工作 它的意思是 任何时候你都可以实现它而且可以使用对称算法加密或者解密你的数据 为了加密或者解密你的数据你必须定义一个密码或者一个密钥 下面描述了对称加密的特性
加密的强度依赖于你的密钥(密码) 如果你配置一个长的密钥 它将是非常难破解的 意思是他将要花费很长的时间让黑客找到密钥
对称加密的一个风险是密码应该让第二个人知道(这个人必须用你的密钥来解密数据)
这种加密算法是基于简单的数学操作 因此它工作的非常快 因此当你要加密的数据量非常大的时候它是最好的选择
基于对称的加密可以被黑客暴力破解 但是如果你定义一个非常好的密码(足够长) 这个破解的过程将需要很长的时间
一旦用户定义了密钥 黑客可以使用暴力破解或者字典来编码或者解密你的信息 但是长的密钥可以在黑客破解你的密码的时候保护你的数据更长的时间
另外在使用密钥或者密码对称加密过程中有一件非常重要的事情 就是初始化向量(IV) IV被使用在最初的编码中(加密或者解密) 在所有的对称算法类中我们有一个名叫Mode的属性 这是被IV使用的 如果我们设置Mode属性为CipherMode CBC(Cipher Block Chaining) 则使用这个模式 每个数据块使用来自前一个块的值来处理 意思是如果系统在处理第三块数据 则它会从第二块中取一些信息(处理第三块数据) 接着它会取第一块数据中的信息用来处理第二块数据 但是在第一块数据之前没有可以用的块 因此它将使用IV来处理第一块 这个技术确保没有两个相同的块产生相同的输出并且因此使得数据更安全 然而如果你使Mode=CipherModer ECB(Electronic codebook mode) 则他不会使用上面的方法(使用前面的处理的块信息处理后面的块) 如果你想用很少的资源和时间处理大量的消息那么这个方法对于你来说就很有用 他也可以让你从数据的中间开始处理
应此 上面我们包含了在对称加密中的两间非常重要的事情 他们是密钥和初始化向量 现在让我们看看对称加密支持哪些算法
对称算法和对称算法类
下面是对称算法和他们的类的关键信息
算法名称算法类(抽象)有效密钥大小(Bit)默认密钥大小(Bit)默认实现类
DESDES DESCryptoServiceProvider
TripleDESTripleDES
RC RC RC CryptoServiceProvider
RijnDaelRijnDael RijnDaelManaged
这里需要注意的是所有的算法类都是继承于抽象类SymmetricAlgorithm 并且你可以看到每个类都支持不同的密钥大小 相同的情况下 他们也支持不同的初始化向量的大小 正如我刚才所说的他们所有的类都是抽象类 因此我们不能直接创建这些抽象类的任何实例 但是SymmetricAlgorithm类(也是抽象类)有一个共享的方法叫Create可以不用操心它是如何实现来创建一个类的具体实例 意思是 你可以通过下面的方式使用它
RC mRC = RC Create()
它将为您返回一个RC 默认实现的一个实例 而不用去关心具体如何实现RC 这个类 如果你想在微软以后更新RC 类的实现还能共享代码(成为可能) 这个技术是非常有用的 在那种情况下 你的代码将自动适应它们的改变并且正确的工作 或者可能在将来RC 类用托管代码写 你的代码依然可以接受它 在相同的情况下 你同样可以使用下面的语句
RC mCrypto = SymmetricAlgorithm Create( RC )
这也可以给你返回一个RC 的对象(默认实现) 在这种情况下你要使用重裁Create方法用算法的名字设置参数来返回算法的对象 这个Create方法来自SymmetricAlgorithm类 并且向我前面说的所有的使用对称算法的其它类都继承于SymmetricAlgorithm 因此你可以在上面所有的类里面找到Create这个方法 意思是如果你使用RC Create( DES )则它也能工作并且将返回一个DES的对象 但是不能使用RC 类得到DES对象
上面的机制看起来很有用 我们可以用同样的方法使用我们自己的算法定义自己的类 但是要想这样 我们必须要对nfig文件作一些小的改动 我在这里不详细描述 你可以参考Wrox关于密码学的书得到更多的信息
现在让我们看看SymmetricAlgorithm类里面的一些方法和属性
BlockSize 分开处理的数据块的大小 大的数据将被分成小的数据块来处理 如果数据小于块大小 则被追加(使用一些默认值填充)
Key 在处理数据的时候将要使用密钥 这个密钥被配置成使用字节数组
IV 数据处理的时候使用初始化向量(上面已经描述) 配置成字节数组
KeySize 密钥的所有位的大小
LegalBlockSize 返回BlockSize的枚举告诉你判断包括最大值 最小值和跳跃值在内的块的大小 跳跃值意思是还有多少值应该添加判断值得到下一个值 比如如果最小值是 跳跃值是 那么下一个判断值就是 等等 (Returns the BlockSize Enumeration which tells you legal values for block size including max value min value and Skip value Skip value means that how much value should be added to last legal value to get next value Like if min value is and Skipvalue is it means next legal values will be and so on )
Mode 位操作得到或者设置模式 见上面描述 值是CipherMode枚举中的一个
Padding 得到或者设置PaddingMode枚举中的一个追加值 (填充块中空余的区域)
LegalKeySize 和LegalBlockSize一样 但是处理的是KeySize
Create 上面已经描述 使用它创建默认算法实现的类的实例
CreateEncryptor 返回一个可以手动加密数据的IcryptoTransform对象 一会将仔细描述
CreateDecryptor 返回一个可以手动解密数据的IcryptoTransform对象 一会将仔细描述
GeneratrKey and GenerateIV 在加密或者解密的过程中如果Key和IV是null则这些方法可以产生默认的密钥和IV
VaildKeySize 检查给定的密钥是不是算法的有效的密钥
Clear 清除和消除所有的资源以及象密钥和IV这样的内存信息
在写代码之前 让我们说几件对我们理解代码非常用帮助的事情
CreateEncryptor和CreateDecryptor
SymmetricAlgorithm类的CreateEncryptor和CreateDecryptor方法返回ICryptoTransform对象 IcryptoTransform是一个想要处理数据块的类来实现的接口 这个过程可以是加密 解密 散列 基于 的编码和解码等等 这个接口的基本目的是完成数据处理分块(The basic purpose of this Interface is to perform Blockwize processing of data ) 你可以直接使用它的实例 但是在大多数情况下 为了方便 我们通过其他的名叫CryptoStream来完成 让我们看一个例子是如何使用它的
DES mCrypt = new SymmetricAlgorithm Create( DES )
ICryptoTransform mTransform = mCrypt CreateEncryptot()
CreateEncryptor或者CreateDecryptor是两个重裁的方法 如果你没有任何参数传入其中 那么将使用默认的密钥和IV(使用SymmetricAlgoruthm类里面的GenerateKey和GenerateIV方法) 另一方面 你可以通过传入一个IV和密钥到CreateEncryptor和CreateDecryptor的对象中 以致加密和解密将使用我们自己定义的IV和密钥
CryptoStream 类
CryptoStream类通常被使用来读写数据同时也在读或者写的时候加密或者解密数据 它是简单的包装了一下原始流类Stream It uses the buffered Access taking all worries from you to manage buffer block sizes padding etc 你可以使用下面的代码得到它的实例
DES mCrypt = SymmetricAlgorithm Create( DES )
IcryptoTransform mTransform = mCrypt CreateEncryptor()
CryptoStream mStream = new CryptoStream(fileStream mTransform CryptoStramMode Read)
fileStream是请求从硬盘或者内存中读取数据的原始文件的流(或者是MemoryStream) 现在通过使用mStream对象和StreamReader/StreamWriter对象读写数据 当你将要读写时 你的加密解密信息将依赖IcryptoTransform对象
代码例子
现在我们有足够关于SymmetricAlgorithm的信息 最后 让我们看看将要编码和解码的代码片断 我假设你拥有一个包含txtData和命令按钮控件的窗体 在命令按钮的代码事件里写如下代码 这个代码将要加密TextBox里面的文本并用MessageBox显示 在将加密结果写回到TextBox中
SymmetricAlgorithm mCryptProv
MemoryStream mMemStr
// 加密txtData中的数据 然后将加密结果用MessageBox显示并且回写到TextBox中
// 这里你可以配置任何 net支持的类
DES mCryptProv = SymmetricAlgorithm Create( Rijndael )
// 加密数据将要以流的形式存储在内存中因此我们需要内存Stream对象
mMemStr = new MemoryStream()
// 创建ICryptTransform对象 (在这里我们使用默认的密钥和初始向量)
ICryptTramsform mTransform = mCryptProv CreateEncryptor()
CryptoStream mCSWriter = new CryptoStream(mMemStr mTransform CryptoStreamMode Write)
StreamWriter mSWriter = StreamWriter(mCSWriter)
mSwriter Writer(this txtData Text)
mSWriter Flush()
mCSWriter FlushFinalBlock()
有一件事情在这里需要注意我们没有在代码的任何地方使用IV和密钥 事实上 在我们在代码里面没有指定他们的时候 NET Framework将为我们自动产生 但是本文包含的例子代码使用的是用户指定的密钥和IV 我们将加密以后的数据使用MemoryStream写到内存中 现在让我们从内存中得到数据的代码
// 数据已经写入内存但是我们需要回显它到TextBox和MessageBox中 因此要做下面的工作
// 为接受数据创建字节数组
byte[] mBytes = new byte[mMemStr Length ]
mMemStr Position =
mMemStr Read(mBytes mMemStr Length)
Text UTF Encoding mEnc = new Text UTF Encoding()
String mEncData = mEnc GetString(mBytes)
MessageBox Show( 加密数据为 +mEncData)
This txtData Text = mEncData
从字节转换为字符串必须要编码 在这里我使用了UTF Encoding 最后 让我们将解密后的数据再次显示在MessageBox和TextBox中
// 现在让我们从内存中得到解密后的数据
// 因为我们的数据在内存中 所以我们需要重新使用MemoryStream对象
// 将内存点置
mMemStr Position =
mTransform = mCryptProv CreateDecryptor()
CryptoStream mCSReader = new CryptoStream(mMemStr mTransform CryptoStreamMode Read)
StreamReader mStrReader = new StreamReader(mCSReader)
String mDecData = mStrReader ReadToEnd()
MessageBox( 解密数据为 +mDecData)
This txtData Text = mDecData
这是所有的工作 解密那些数据我们使用了相同的内存流 为了能从流的其实部分读数据我们首先将它置为开始 然后我们用SymmetricAlgorithm对象的CreateDecryptor方法创建IcryptoTransform对象 我们在上面的代码中为了解密重复使用了对象(mMemStr) 你可以创建新的对象(使用新的变量) 然后我们为了从内存中读取数据需要StreamReader对象 While reading that it will also decrypt that data since we passed CryptoStream object ring the creation of StreamReader object
最后的话
NET为我们提供了一个非常好的托管途径保护我们的数据 我们可以使用 NET内建的一组类来加密我们的数据 虽然很多的类后台依然使用Crypto APIs技术 我们使用老的Crypto APIs没有任何问题 但是我们可以不用担心那些类的具体实现来安全的使用这些类 在后面的文章我将描述非对称加密算法的神话和用途
关于例子
lishixin/Article/program/net/201311/13972