AI智能
改变未来

C#学习笔记——加密解密


C#数据流与数据的加密和解密

1. 数据编码和解码:
  1. 常见的字符集编码方式:
    (1)每个国家都有自己的字符编码方式。
    (2)要想正确打开一个文件,必须知道它采用的是哪种编码方式,否则就可能会出现乱码。
    (3)常见的字符集编码方式:

①ASCII:

ASCII字符集由128个字符组成,包括大小写字母、数字0~9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)。

②Unicode:

Unicode是国际通用的编码方式,可以表示地球上绝大部分地区的文字。这种编码每个字符都占2个字节,例如一个英文字符占2个字节,一个汉字也是2个字节。
C#中的字符和字符串默认采用的都是Unicode编码。

③UTF-8:

UTF-8是在因特网上使用最广泛的一种编码格式。它是Unicode的一种变长字符编码,用1~4个字节表示一个Unicode字符。例如,每个英文字母都占1个字节,每个汉字都占4个字节。

④GB2312和GB18030:

对于简体中文来说,国家规定的编码标准(国标)有两种,一种是GB2312(1980年公布),另一种是GB18030(2000年公布)
GB2312每个汉字的编码长度都占2个字节,这种编码方式最多支持6千多个汉字的编码;
GB18030编码长度为1~4个字节,可支持两万多个汉字的编码。

2. 利用Encoding类实现编码和解码:
  1. Encoding类位于System.Text命名空间下
  2. 该类主要用于对字符集进行编码和解码以及将一种编码格式转换为另一种编码格式。
  3. Encoding类提供的常用属性和方法:
属性和方法 解释
Default属性 获取系统的当前ANSI代码页的编码
BodyName属性 获取可与邮件正文标记一起使用的编码名称。如果当前Encoding无法使用,则为空字符串
HeaderName属性 获取可与邮件标题标记一起使用的编码名称。如果当前Encoding无法使用,则为空字符串
Unicode属性 获取Unicode格式的编码(UTF-16)
UTF8属性 获取Unicode格式的编码(UTF-8)
ASCII属性 获取ASCII字符集的编码
Convert方法 将字节数组从一种编码转换为另一种编码
GetBytes方法 将一组字符编码为一个字节序列
GetString方法 将一个字节序列解码为一个字符串
GetEncoding方法 返回指定格式的编码
  1. Encoding类的基本用法:
    (1)获取所有编码名称及其描述信息
    (2)获取指定编码名称及其描述信息
    (3)不同编码之间的转换
    (4)利用Encoding类实现字符串的编码和解码
举例编码:
  1. 获取所有编码名称及其描述信息:
    (1)使用Encoding类静态的GetEncodings方法可得到一个包含所有编码的EncodingInfo类型的数组。
    (2)EncodingInfo类同位于System.Text命名空间下,提供有关编码的基本信息。
foreach ( EncodingInfo ei in Encoding.Ge1+tEncodings( )){Encoding en = ei.GetEncoding( );Console.WriteLine(\"编码名称:{0,-18},编码描述:{1}\", ei.Name, en.EncodingName);}
  1. 获取指定编码名称及其描述信息
    (1)Encoding类提供了UTF8、ASCII、Unicode等属性,通过这些属性可以获取某个字符集编码。
    (2)也可以利用Encoding类静态的GetEndcoing方法来获取。
Encoding ascii = Encoding.ASCII;Encoding gb2312 = Encoding.GetEncoding(\"GB2312\");Encoding gb18030 = Encoding.GetEncoding(\"GB18030\");

(3)得到Encoding对象后,即可利用HeaderName属性获取编码名称,利用EncodingName属性获取编码描述。

string s1 = \"GB2312的编码名称为:\" + gb2312.HeaderName;string s2 = \"GB2312的编码描述为:\" + gb2312.EncodingName;
  1. 不同编码之间的转换
    (1)利用Encoding类的Convert方法可将字节数组从一种编码转换为另一种编码,转换结果为一个byte类型的数组。
public static byte[] Convert(Encoding srcEncoding,  //源编码Encoding dstEncoding,  //目标编码byte[] bytes  //待转换的字节数)
string s = \"abcd\";Encoding unicode = Encoding.Unicode;Encoding utf8 = Encoding.UTF8;byte[] b = Encoding.Convert(unicode, utf8, unicode.GetBytes(s));string s1 = utf8.GetString(b);
3. 加密流 CryptoStream
  1. CryptoStream类位于System.Security.Cryptography命名空间下
  2. 该类可按加密流的方式加密或者解密数据,而且只能用于对称加密。
  3. 实现CryptoStream的任何被加密的对象都可以和实现Stream的任何对象链接起来,因此一个对象的流式处理输出可以馈送到另一个对象的输入,而不需要分别存储中间结果。
  4. 调用构造函数创建CryptoStream对象时,需用目标数据流、要使用的转换和流的模式初始化CryptoStream类的新实例。加密时为写访问模式,解密时为读访问模式。
  5. CryptoStream类的构造函数语法如下:
public CryptoStream(Stream stream,	//对其执行加密转换的流ICryptoTransform transform,  //要对流执行的加密转换CryptoStreamMode mode//CryptoStreamMode枚举,有Read和Write两种)
  1. 使用CryptoStream对象时,一般还要借助其他流进行处理。
    (1)比如使用FileStream作为目标数据流
    (2)再根据创建的CryptoStream对象生成StreamWriter对象
    (3)然后调用WriteLine方法,通过CryptoStream将加密后的数据写入FileStream
    (4)写入完成后,关闭创建的对象。
    (5)此时在文件中保存的就是加密后的数据。
  2. 解密时,使用和加密时相同的密钥创建CryptoStream实例,并在创建该实例时将构造函数的mode参数改为读模式,再将StreamWriter替换成StreamReader,即可将解密后的数据读取出来。
    举例
FileStream fStream = File.Open(FileName,FileMode.OpenOrCreate);AesManaged aes = new AesManaged();CryptoStream cStream = new CryptoStream(fStream, aes.CreateEncryptor(), CryptoStreamMode.Write);sw = new StreamWriter(cryptoStream);sw.WriteLine(\"被加密的字符串\");

注意:

写入完成后,关闭创建的对象,在fStream指向的文件中保存的就是加密后的数据。

//加密public class DBSecurity    {//sKey sIV这两个自己随意设定,不能外泄private const string sKey = \"11,22,33,43,34,56,65,78\";private const string sIV = \"12,23,21,34,65,56,85,96\";# region 加密解密//加密方法public static string Encrypt(string pToEncrypt)        {try            {DESCryptoServiceProvider des = new DESCryptoServiceProvider();//把字符串放到byte数组中byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);//建立加密对象的密钥和偏移量byte[] b_key = new byte[8];string[] s_keys = new string[8];s_keys = sKey.Split(\',\');for (int i = 0; i <= 7; i++)                {b_key[i] = Convert.ToByte(s_keys[i].ToString());}des.Key = b_key;byte[] b_iv = new byte[8];string[] s_ivs = new string[8];s_ivs = sIV.Split(\',\');for (int i = 0; i <= 7; i++)                {b_iv[i] = Convert.ToByte(s_ivs[i].ToString());}des.IV = b_iv;MemoryStream ms = new MemoryStream();CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);cs.Write(inputByteArray, 0, inputByteArray.Length);cs.FlushFinalBlock();StringBuilder ret = new StringBuilder();foreach (byte b in ms.ToArray())                {//Format as hexret.AppendFormat(\"{0:X2}\", b);}ret.ToString();return ret.ToString();}catch            {return \"\";}}
//解密方法public static string Decrypt(string pToDecrypt)        {try            {DESCryptoServiceProvider des = new DESCryptoServiceProvider();byte[] inputByteArray = new byte[pToDecrypt.Length / 2];for (int x = 0; x < pToDecrypt.Length / 2; x++)                {int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));inputByteArray[x] = (byte)i;}//建立加密对象的密钥和偏移量,此值重要,不能修改byte[] b_key = new byte[8];string[] s_keys = new string[8];s_keys = sKey.Split(\',\');for (int i = 0; i <= 7; i++)                {b_key[i] = Convert.ToByte(s_keys[i].ToString());}des.Key = b_key;byte[] b_iv = new byte[8];string[] s_ivs = new string[8];s_ivs = sIV.Split(\',\');for (int i = 0; i <= 7; i++)                {b_iv[i] = Convert.ToByte(s_ivs[i].ToString());}des.IV = b_iv;MemoryStream ms = new MemoryStream();CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);cs.Write(inputByteArray, 0, inputByteArray.Length);cs.FlushFinalBlock();//建立StringBuild对象,CreateDecrypt使用的是流对象,必须把解密后的文本变成流对象StringBuilder ret = new StringBuilder();return System.Text.Encoding.Default.GetString(ms.ToArray());}catch (Exception exp){string s = exp.Message.ToString();return \"\";}}#endregion}
4. 数据加密与数字签名
  1. 加密方法:
方法 简述
DES 1977年,美国国家标准局公布实施了“美国数据加密标准(DES)”,民间力量开始全面介入密码学的研究和应用中,采用的加密算法有DES、SHA等。
RC2 由著名密码学家Ron Rivest设计的一种传统对称分组加密算法
3DES 基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高
AES Rijndael被选中成为将来的AES
  1. 数据在网络传输过程中的保密性是网络安全中重点要考虑的问题之一。
  2. 命名空间:System.Security.Cryptography命名空间。
  3. 这些加密算法主要分为两大类:对称加密和不对称加密。

对称加密:

  1. 对称加密也称为私钥加密。
  2. 采用私钥算法,加密和解密数据使用的是同一个密钥。

由于具有密钥的任意一方都可以使用该密钥解密数据,因此必须保证该密钥不能被攻击者获取,否则就失去了加密的意义。

  1. 私钥算法以块为单位加密数据

以块为单位加密数据(称为块密码),该方法一次加密一个数据块(数据多于规定的块大小时,将数据分块处理,数据少于规定的块大小时,将其扩充到块大小) 。

  1. 对称加密优缺点:
    优点|缺点
    —-|—-
    保密强度高,加、解密速度快,适合加密大量数据。 |由于双方使用相同的密钥进行加密和解密。在网络传输中,如何传递密钥成为问题所在。如果攻击者截获了密钥,也就等于知道了如何解密数据。
  2. 常见的对称加密:
    (1)DES加密算法

DES是美国1977年公布的一种数据加密标准,该算法目前已经有多种破解方法,已被淘汰。

(2)TripleDES加密算法

TripleDES算法(也叫3DES算法)是美国国家标准技术研究所(NIST)1999年提出的数据加密标准。

该算法是DES的一个变形,使用DES算法的3次连续迭代,支持128位和192位的密钥长度,其安全性比DES算法高。

(3)RC2加密算法

RC2算法是Ron Rivest在1987年设计的一个块密码算法。该算法密钥长度为从40位~128位,以8位递增。

(4)SHA-1加密算法

SHA-1(安全哈希算法,也称为安全哈希标准)是由美国政府发布的一种加密哈希算法。
可以根据任意长度的字符串生成160位的哈希值。HMACSHA1接受任何大小的密钥,并产生长度为160位的哈希序列。

(5)AES加密算法

1997年美国国家标准技术协会(NIST)开始向全世界公开征集新的高级加密标准(Advanced Encryption Standard,AES)
Rijndael算法是由Vincent Rijmen和Joan Daemen两人提出的加密算法。
该算法作为新一代的数据加密标准,汇聚了强安全性、高性能、高效率、易用和灵活等优点。
算法支持128位(16个字节)、192位(24个字节)和256位(32个字节)的密钥长度,与DES算法相比,Rijndael的128位密钥比DES的56位密钥强1021倍。
由于Rijndael加密算法是AES选中的唯一算法,因此将其简称为AES算法。

  1. 对称加密的实现原理
    (1)所有对称加密(私钥加密)算法都是通过加密将n字节的输入块转换为加密字节的输出块。

加密和解密字节序列都必须逐块进行
而且读入的数据块必须符合私钥算法要求的块的大小,如果不符合应该填充至使其符合要求。

例如,RC2、DES和TripleDES每块均为8字节,AES为16字节(默认)、24字节或32字节。

如果被加密的数据块大于n,则逐块加密,即一次加密一个块。如果被加密的数据块小于n,则先将其扩展为n字节后再进行加密处理。

  1. 实现加密
    (1)用于加密的块密码模式:

块密码加密模式可以根据需要通过CipherMode枚举来选择

using (Aes aes = Aes.Create()){aes.Mode = CipherMode.CBC;......}

CipherMode枚举提供的可选值有CBC、CFB、CTS、ECB、OFB,如果不设置,默认为CBC模式。

CBC 密码块链模式

1 在该模式中,每个纯文本块在加密前,都和前一个块进行按位“异或”操作。
2 这样可确保即使纯文本包含许多相同的块,这些块中的每一个也会加密为不同的密码文本块。
3 在加密块之前,初始化向量(IV)通过按位“异或”操作与第一个纯文本块结合。
4 如果密码文本块中有一个位出错,相应的纯文本块也将出错。此外,后面的块中与原出错位的位置相同的位也将出错。

CFB 密码反馈模式

1 该模式将少量递增的纯文本处理成密码文本,而不是一次处理整个块。
2 这种模式将一个块分为几部分,每部分都用移位寄存器对其进行处理。

例如,如果块大小为8个字节,移位寄存器每次处理一个字节,则该块将被分为8个部分。

3 如果密码文本中有一个位出错,则将导致接下来若干次递增的纯文本也出错,直到出错位从移位寄存器中移出为止。
4 默认反馈大小可以根据算法而变,但通常是8位或块大小的位数。
5 支持CFB的算法可使用FeedbackSize属性设置反馈位数。

CTS 密码文本窃用模式

1 该模式可处理任何长度的纯文本并产生长度与纯文本长度相匹配的密码文本。
2 除了最后两个纯文本块外,对于所有其他块,此模式与CBC模式的行为相同。

ECB 电子密码本模式

1 该模式分别加密每个块。
2 任何纯文本块只要相同并且在同一消息中,或者在使用相同的密钥加密的不同消息中,都将被转换成同样的密码文本块。
3 需要特别注意的是,由于该模式存在多个安全隐患,不建议使用此模式。

这是因为如果要加密的纯文本包含大量重复的块,则逐块破解密码文本是可行的。
另外,攻击者还可以对块进行分析来确定加密密钥。
此外,随时准备攻击的对手甚至可能会在密文发送过程中悄悄插入、替代或交换个别的块,从而导致结果与预想的情况大相径庭。

OFB 输出反馈模式

1 该模式将少量递增的纯文本处理成密码文本,而不是一次处理整个块。
2 此模式与CFB相似;这两种模式的唯一差别是移位寄存器的填充方式不同。
3 如果密码文本中有一个位出错,纯文本中相应的位也将出错。但是,如果密码文本中有多余或者缺少的位,则那个位之后的纯文本都将出错。

(2)密钥Key和初始化向IV:

.NET类库中提供的块密码加密模式默认使用CBC模式。
该模式通过一个密钥Key和一个初始化向量(Initialization Vector,IV)对数据执行加密转换。
必须知道这个密钥和初始化向量才能加密和解密数据。

(3)IV的作用:

这是因为初始化向量默认是一个随机生成的字符集,使用它可以确保任何两个原始数据块都不会生成相同的加密后的数据块,从而可以尽可能防范穷举搜索而进行的攻击。
例如,对于给定的私钥Key,如果不用初始化向量IV,那么相同的明文输入块就会加密为同样的密文输出块。显然,如果在明文流中有重复的块,那么在密文流中也会存在重复的块。对于攻击者来说,就可以对这些重复的块进行分析或者通过穷举来发现密钥。
为了解决这个问题,加密时先使用初始化向量IV加密第一个纯文本块,然后每个后续纯文本块都会在加密前与前一个密码文本块进行按位“异或”(XOR)运算。因此,每个密码文本块都依赖于它前面的块。这样一来,两个相同的明文块的输出就会不同,从而使数据的安全系数大大提高。

(4)利用AES算法加密解密字符串:

  1. 加密和解密数据时,有两种实现思路:
    (1)一种是程序根据用户提供的密码,用某种对称加密算法实现加密和解密,这种方式适用于让用户去记忆密码的情况。
    (2)另一种是随机生成对称加密的密钥,然后用它加密和解密数据,这种方式适用于对本机中的重要数据或者对通过网络传输的数据进行加密和解密的场合。
  2. 在System.Security.Cryptography命名空间有一个Aes类
    (1)该类是高级加密标准(AES) 的所有实现都必须从中继承的抽象基类,利用它可直接实现基于AES算法的加密和解密。

不对称加密:

  1. 不对称加密也叫公钥加密。
  2. 这种技术使用不同的加密密钥与解密密钥

是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

  1. 不对称加密产生的主要原因有两个:

1 一是为了解决对称加密的密钥管理问题;
2 二是数字签名需要用不对称加密来实现。

  1. 不对称加密的实现原理。
    (1)不对称加密使用一个需要保密的私钥和一个可以对外公开的公钥,即使用“公钥/私钥”对来加密和解密数据。

公钥和私钥都在数学上相关联;
用公钥加密的数据只能用私钥解密,反之,用私钥加密的数据只能用公钥解密。
两个密钥对于通信会话都是唯一的。
公钥加密算法也称为不对称算法,原因是需要用一个密钥加密数据而需要用另一个密钥来解密数据。

(2)对称加密算法使用长度可变的缓冲区,而不对称加密算法使用固定大小的缓冲区,无法像私钥算法那样将数据链接起来成为流。
(3)不对称加密之所以不容易被攻击,关键在于对私钥的管理上。

在对称加密中,发送方必须先将解密密钥传递给接收方,接收方才能解密。
如果能通过某种处理,避免通过网络传递私钥,就可以解决这个问题,不对称加密的关键就在于此。

(4)使用不对称加密算法加密数据后,私钥不是发送方传递给接收方的,而是接收方先生成一个公钥/私钥对,在接收被加密的数据前,先将该公钥传递给发送方。
(5)由于从公钥推导出私钥是不可能的,所以不怕通过网络传递时被攻击者截获公钥从而推导出私钥。
(6)发送方得到此公钥后,使用此公钥加密数据,再将加密后的数据通过网络传递给接收方;接收方收到加密后的数据后,再用私钥进行解密。
(7)由于没有直接传递私钥,从而保证了数据的安全性。
5. 常用的不对称加密算法:
(1)RSA算法

1977年由当时在麻省理工学院的Ron Rivest、Adi Shamir和Leonard Adleman一起提出,RSA就是他们三人姓氏开头字母拼在一起组成的。
从1978年开始,该算法在公钥加密标准和电子商业中就已经被广泛使用。
速度是RSA的缺陷,该算法一般只适用于少量数据的加密。
在.NET框架中,System.Security.Cryptography命名空间下的RSACryptoServiceProvider类提供了RSA算法的实现,利用它可实现不对称加密、解密以及数字签名。

(2)ECC算法

ECC(Elliptic Curves Cryptography,椭圆曲线算法)是一种公钥加密算法
与RSA算法相比,ECC算法可以使较短的密钥达到相同的安全程度。
与ECC相关的算法包括ECDSA算法、ECDH算法等。
在.NET框架中,System.Security.Cryptography命名空间下的ECDiffieHellmanCng类提供了椭圆曲线ECDSA算法的下一代加密技术(CNG)的加密实现,利用该类可直接用ECDSA算法实现不对称加密和解密。

  1. 不对称加密(公钥加密)原理

使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
私钥是保密的,公钥是公开的。用公钥加密的数据只能用私钥解密,反之,用私钥加密的数据只能用公钥解密。
实现方法:接收方先生成一个公钥/私钥对,在接收被加密的数据前,先将该公钥传递给发送方;注意,从公钥推导出私钥是不可能的,所以不怕通过网络传递时被攻击者截获公钥。发送方得到此公钥后,使用此公钥加密数据,再将加密后的数据通过网络传递给接收方;接收方收到加密后的数据后,再用私钥进行解密。由于没有传递私钥,从而提高了数据的安全性。

  1. 不对称加密(也叫公钥加密)特点
优点 缺点
密钥位数多,而且无法根据加密密钥推导出解密密钥。从而使保密强度更高。 加、解密速度慢,不适合加密大量数据。
  1. NET Framework 提供了以下类来实现不对称加密算法:
    (1)DSACryptoServiceProvider:DSA算法的加密实现。
    (2)RSACryptoServiceProvider:RSA算法的加密实现。
    (3)ECDiffieHellmanCng
    椭圆曲线 Diffie-Hellman (ECDH) 算法的下一代加密技术 (CNG)加密实现,.NET Framework 3.5版开始提供。
    (4)ECDsaCng
    椭圆曲线数字签名算法 (ECDSA) 的下一代加密技术 (CNG) 实现 , .NET Framework 3.5版开始提供。
  2. RSACryptoServiceProvider类:

使用加密服务提供程序 (CSP) 提供的 RSA 算法的实现执行不对称加密和解密。
如果安装了 Microsoft Enhanced Cryptographic Provider,则 RSACryptoServiceProvider 支持长度从 384 位至 16384 位(增量为 8 位)的密钥。如果安装了 Microsoft Base Cryptographic Provider,则支持长度从 384 位至 512 位(增量为 8 位)的密钥。

  1. RSACryptoServiceProvider类的常用属性和方法:

密钥容器
  1. 不论是对称加密还是非对称加密,都有如何保存密钥的问题。
    (1)比如我们常见的让用户自己记忆密码的办法,如果攻击者也知道了该密码,那么攻击者也一样可以用它来进入系统或者利用它来解密数据,这样一来,加密也就失去了意义。
    (2)所以,网络传输中一般不使用让用户记忆密码的办法,而是自动产生密钥。
    (3)同时还必须有一种办法,来确保密钥存储的安全性,这就是密钥容器的用途。
  2. 用密钥容器保存不对称加密的密钥
    (1)密钥容器最直接的用途是用它来保存不对称加密的密钥
    (2)为了区分是哪一个密钥容器,还需要给每个密钥容器起一个名称。
    (3)在System.Security.Cryptography命名空间中,有一个CspParameters类,可以通过该类提供的属性设置获取密钥容器的名称。
    (4)保存RSA不对称加密的密钥到密钥容器中,以及从密钥容器中获取密钥信息。

注意,保存密钥信息和获取密钥信息使用的是同一段代码。

public static RSACryptoServiceProvider GenRSAFromContainer (string ContainerName){//创建CspParameters对象,指定密钥容器的名称,用于保存公钥/私钥对CspParameters cp = new CspParameters( );//如果不存在名为containerName的密钥容器,则创建它,并初始化cp//如果存在,则直接根据它原来保存的内容初始化cpcp.KeyContainerName = ContainerName;//使用CspParameters对象创建RSACryptoServiceProvider的实例RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);return rsa;}

(5)使用密钥容器保存密钥信息的优点是安全性高
(6)采用密钥容器保存密钥信息时,需要注意一个问题,即当操作系统被破坏时,比如硬盘损坏或者被病毒感染,密钥信息也会随之丢失。
(7)为了防止丢失密钥信息而导致原来被加密的数据无法解密,生成密钥信息后,最好先将其导出为XML文件保存到某个安全的地方,或者保存到某个数据库中,作为备用。
(8)当出现密钥信息丢失的情况时,再将XML文件保存的密钥信息导入到密钥容器中即可。这种保护措施和要求必须提供数据库数据备份功能的保护措施类似。
(9)可以用以下方法之一导出密钥信息。

方法 解释
ToXMLString方法 返回密钥信息的XML表示形式。
ExportParameters方法 返回保存密钥信息的RSAParameters结构。
ExportCspBlob方法 返回密钥信息的字节数组。

这3个方法都有一个布尔类型的参数,表示导出时是否包含私钥信息。

(10)当需要导入密钥信息时,可以使用FromXMLString方法或者ImportParameters方法初始化不对称加密类的实例。

注意,用单独的文件保存密钥信息,优点是方便灵活;缺点是没有密钥容器安全,因为一旦攻击者获取了该信息,被加密的数据也就无任何安全保障了。

  1. 用密钥容器保存对称加密的密钥
    (1)解决了不对称加密中密钥的保存问题,对于对称密钥的处理就容易了,只需要用不对称加密的密钥加密对称加密的密钥,然后将不对称加密的密钥保存到密钥容器中。
    (2)解密时,先从密钥容器中得到不对称加密的密钥,然后利用它解密的结果得到对称加密的密钥,最后再利用对称加密的密钥解密数据。
数字签名
  1. 存在目的:
    两个问题:
  1. 通过Internet下载文件后,怎样知道下载的文件是否和原始文件完全相同呢?
  2. 通过Internet下载文件后,怎样知道下载的文件是否和原始文件完全相同呢?

这就是数字签名的用途。
如果通信双方希望确保信息是来自对方而不是来自第三方,需要使用数字签名进行身份验证。另外,数字签名还可以防止特定一方否认曾发送过的信息
2. 数字签名实现原理

利用私钥加密必须用公钥解密这个原理实现。
在应用程序中,可以利用数字签名实现数据身份验证和数据完整性验证。
数据身份验证是为了验证数据是不是持有私钥的人发送的;数据完整性验证则用于验证数据在传输过程中是否被修改过。

  1. 实现思路

发送方先向该消息应用哈希函数以创建消息摘要。
然后,发送方用自己的私钥对消息摘要进行加密,以创建发送方的个人签名。
接收方收到消息和签名后,再使用发送方的提供的公钥解密该签名,以恢复消息摘要,并使用发送方所用的同一算法对该消息进行运算。
如果接收方计算的消息摘要与收到的消息摘要完全匹配,则接收方可以确保消息在传输过程中没有修改。
注意,因为公钥不是保密的,所以任何人都可以用它来验证数字签名。

  1. 常用的数字签名算法

.NET框架包含的类提供了以下实现数字签名的算法。

(1)RSA算法

RSA算法不仅可用于不对称加密和解密,还能用它实现数字签名。

(2)DSA算法

DSA(Digital Signature Algorithm)是Schnorr和ElGamal签名算法的变种,被美国NIST作为数字签名算法标准。
在.NET框架中,System.Security.Cryptography命名空间下的DSACryptoServiceProvider类提供了DSA算法的数字签名实现
注意该算法只能用于数字签名,即只能利用它验证发送方发送的数据完整性以及发送者的身份。
算法安全性与RSA相比差不多,但DSA的算法执行速度要比RSA快很多。

(3)ECDSA算法

椭圆曲线数字签名算法(ECDSA)
在.NET框架中,System.Security.Cryptography命名空间下的ECDsaCng类提供了基于ECDSA的下一代加密技术(CNG)实现,利用该类可直接实现数字签名。

  • 点赞
  • 收藏
  • 分享
  • 文章举报

Geng_Sir发布了5 篇原创文章 · 获赞 0 · 访问量 67私信关注

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » C#学习笔记——加密解密