zoukankan      html  css  js  c++  java
  • .net加密

    加密概述:

    密可以帮助保护数据不被查看和修改,并且可以帮助在本不安全的信道上提供安全的通信方式。例如,可以使用加密算法对数据进行加密,在加密状态下传输数据,然后由预定的接收方对数据进行解密。如果第三方截获了加密的数据,解密数据是很困难的。

    在一个使用加密的典型场合中,双方(小红和小明)在不安全的信道上通信。小红和小明想要确保任何可能正在侦听的人无法理解他们之间的通信。而且,由于小红和小明相距遥远,因此小红必须确保她从小明处收到的信息没有在传输期间被任何人修改。此外,她必须确定信息确实是发自小明而不是有人模仿小明发出的。

    加密用于达到以下目的:

    • 保密性:帮助保护用户的标识或数据不被读取。

    • 数据完整性:帮助保护数据不更改。

    • 身份验证:确保数据发自特定的一方。

    为了达到这些目的,您可以使用算法和惯例的组合(称作加密基元)来创建加密方案。下表列出了加密基元及它们的用法。

     
    加密基元使用

    私钥加密(对称加密)

    对数据执行转换,使第三方无法读取该数据。此类型的加密使用单个共享的机密密钥来加密和解密数据。

    公钥加密(不对称加密)

    对数据执行转换,使第三方无法读取该数据。此类加密使用公钥/私钥对来加密和解密数据。

    加密签名

    通过创建对特定方唯一的数字签名来帮助验证数据是否发自特定方。此过程还使用哈希函数。

    加密哈希

    将数据从任意长度映射为定长字节序列。哈希在统计上是唯一的;不同的双字节序列不会哈希为同一个值。

    私钥加密

    私钥加密算法使用单个私钥来加密和解密数据。由于具有密钥的任意一方都可以使用该密钥解密数据,因此必须保护密钥不被未经授权的代理得到。私钥加密又称为对称加密,因为同一密钥既用于加密又用于解密。私钥加密算法非常快(与公钥算法相比),特别适用于对较大的数据流执行加密转换。

    通常,私钥算法(称为块密码)用于一次加密一个数据块。块密码(如 RC2、DES、TripleDES 和 Rijndael)通过加密将 n 字节的输入块转换为加密字节的输出块。如果要加密或解密字节序列,必须逐块进行。由于 n 很小(对于 RC2、DES 和 TripleDES,n = 8 字节;n = 16 [默认值];n = 24;对于 Rijndael,n = 32),因此必须对大于 n 的数据值一次加密一个块。

    基类库中提供的块密码类使用称作密码块链 (CBC) 的链模式,它使用一个密钥和一个初始化向量 (IV) 对数据执行加密转换。对于给定的私钥 k,一个不使用初始化向量的简单块密码将把相同的明文输入块加密为同样的密文输出块。如果在明文流中有重复的块,那么在密文流中将存在重复的块。如果未经授权的用户知道有关明文块的结构的任何信息,就可以使用这些信息解密已知的密文块并有可能发现您的密钥。若要克服这个问题,可将上一个块中的信息混合到加密下一个块的过程中。这样,两个相同的明文块的输出就会不同。由于该技术使用上一个块加密下一个块,因此使用了一个 IV 来加密数据的第一个块。使用该系统,未经授权的用户有可能知道的公共消息标头将无法用于对密钥进行反向工程。

    可以危及用此类型密码加密的数据的一个方法是,对每个可能的密钥执行穷举搜索。根据用于执行加密的密钥大小,即使使用最快的计算机执行这种搜索,也极其耗时,因此难以实施。使用较大的密钥大小将使解密更加困难。虽然从理论上说加密不会使对手无法检索加密的数据,但这确实极大增加了这样做的成本。如果执行彻底搜索来检索只在几天内有意义的数据需要花费三个月的时间,那么穷举搜索的方法是不实用的。

    私钥加密的缺点是它假定双方已就密钥和 IV 达成协议,并且互相传达了密钥和 IV 的值。并且,密钥必须对未经授权的用户保密。由于存在这些问题,私钥加密通常与公钥加密一起使用,来秘密地传达密钥和 IV 的值。

    假设小红和小明是要在不安全的信道上进行通信的双方,他们可能按以下方式使用私钥加密。小红和小明都同意使用一种具有特定密钥和 IV 的特定算法(如 Rijndael)。小红撰写一条消息并创建要在其上发送该消息的网络流。接下来,她使用该密钥和 IV 加密该文本,并通过 Internet 发送该文本。她没有将密钥和 IV 发送给小明。小明收到该加密文本并使用预先商定的密钥和 IV 对它进行解密。如果传输的内容被人截获,截获者将无法恢复原始消息,因为截获者并不知道密钥或 IV。在这个方案中,密钥必须保密,但 IV 不需要保密。在一个实际方案中,将由小红或小明生成私钥并使用公钥(不对称)加密将私钥(对称)传递给对方。有关更多信息,请参见本主题后面的有关公钥加密的部分。

    .NET Framework 提供以下实现私钥加密算法的类:

    公钥加密

    公钥加密使用一个必须对未经授权的用户保密的私钥和一个可以对任何人公开的公钥。公钥和私钥都在数学上相关联;用公钥加密的数据只能用私钥解密,而用私钥签名的数据只能用公钥验证。公钥可以提供给任何人;公钥用于对要发送到私钥持有者的数据进行加密。两个密钥对于通信会话都是唯一的。公钥加密算法也称为不对称算法,原因是需要用一个密钥加密数据而需要用另一个密钥来解密数据。

    公钥加密算法使用固定的缓冲区大小,而私钥加密算法使用长度可变的缓冲区。公钥算法无法像私钥算法那样将数据链接起来成为流,原因是它只可以加密少量数据。因此,不对称操作不使用与对称操作相同的流模型。

    双方(小红和小明)可以按照下列方式使用公钥加密。首先,小红生成一个公钥/私钥对。如果小明想要给小红发送一条加密的消息,他将向她索要她的公钥。小红通过不安全的网络将她的公钥发送给小明,小明接着使用该密钥加密消息。(如果小明在不安全的信道如公共网络上收到小红的密钥,则小明必须同小红验证他具有她的公钥的正确副本。)小明将加密的消息发送给小红,而小红使用她的私钥解密该消息。

    但是,在传输小红的公钥期间,未经授权的代理可能截获该密钥。而且,同一代理可能截获来自小明的加密消息。但是,该代理无法用公钥解密该消息。该消息只能用小红的私钥解密,而该私钥没有被传输。小红不使用她的私钥加密给小明的答复消息,原因是任何具有公钥的人都可以解密该消息。如果小红想要将消息发送回小明,她将向小明索要他的公钥并使用该公钥加密她的消息。然后,小明使用与他相关联的私钥来解密该消息。

    在一个实际方案中,小红和小明使用公钥(不对称)加密来传输私(对称)钥,而对他们的会话的其余部分使用私钥加密。

    公钥加密具有更大的密钥空间(或密钥的可能值范围),因此不大容易受到对每个可能密钥都进行尝试的穷举攻击。由于不必保护公钥,因此它易于分发。公钥算法可用于创建数字签名以验证数据发送方的身份。但是,公钥算法非常慢(与私钥算法相比),不适合用来加密大量数据。公钥算法仅对传输很少量的数据有用。公钥加密通常用于加密一个私钥算法将要使用的密钥和 IV。传输密钥和 IV 后,会话的其余部分将使用私钥加密。

    .NET Framework 提供以下实现公钥加密算法的类:

    数字签名

    公钥算法还可用于构成数字签名。数字签名验证发送方的身份(如果您信任发送方的公钥)并帮助保护数据的完整性。使用由小红生成的公钥,小红的数据的接收者可以通过将数字签名与小红的数据和小红的公钥进行比较来验证是否是小红发送了该数据。

    为了使用公钥加密对消息进行数字签名,小红首先将哈希算法应用于该消息以创建消息摘要。该消息摘要是数据的紧凑且唯一的表示形式。然后,小红用她的私钥加密该消息摘要以创建她的个人签名。在收到消息和签名时,小明使用小红的公钥解密签名以恢复消息摘要,并使用与小红所使用的相同的哈希算法来散列消息。如果小明计算的消息摘要与从小红那里收到的消息摘要完全一致,小明就可以确定该消息来自私钥的持有人,并且数据未被修改过。如果小明相信小红是私钥的持有人,则他知道该消息来自小红。

    请注意,由于发送方的公钥为大家所周知,并且它通常包含在数字签名格式中,因此任何人都可以验证签名。此方法不保守消息的机密;若要使消息保密,还必须对消息进行加密。

    .NET Framework 提供以下实现数字签名算法的类:

    哈希值

    哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希计算都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的。

    消息身份验证代码 (MAC) 哈希函数通常与数字签名一起用于对数据进行签名,而消息检测代码 (MDC) 哈希函数则用于数据完整性。

    双方(小红和小明)可按下面的方式使用哈希函数来确保数据的完整性。如果小红对小明编写一条消息并创建该消息的哈希,则小明可以在稍后散列该消息并将他的哈希与原始哈希进行比较。如果两个哈希值相同,则该消息没有被更改;如果值不相同,则该消息在小红编写它之后已被更改。为了使此系统发挥作用,小红必须对除小明外的所有人保密原始的哈希值。

    .NET Framework 提供以下实现数字签名算法的类:

    随机数生成

    随机数生成是许多加密操作不可分割的组成部分。例如,加密密钥需要尽可能地随机,以便使生成的密钥很难再现。加密随机数生成器必须生成无法以计算方法推算出(低于 < .05 的概率)的输出;即,任何推算下一个输出位的方法不得比随机猜测具有更高的成功概率。.NET Framework 中的类使用随机数生成器生成加密密钥。

    RNGCryptoServiceProvider 类是随机数生成器算法的实现。

    .NET Framework 加密模型:

    .NET Framework 提供许多标准加密算法的实现。这些算法易于使用并具有最安全的可能默认属性。此外,对象继承、流设计和配置的 .NET Framework 加密模型具有高度的可扩展性。

    对象继承

    .NET Framework 安全系统实现可扩展模式的派生类继承。层次结构如下所示:

    使用这种模式的派生类,很容易添加新算法或现有算法的新实现。例如,若要创建新的公钥算法,应从 AsymmetricAlgorithm 类继承。若要创建特定算法的新实现,应创建该算法的非抽象派生类。

    流设计

    公共语言运行库使用面向流的设计实现对称算法和哈希算法。该设计的核心是 CryptoStream 类,它派生自 Stream 类。基于流的加密对象全都支持用于处理对象的数据传输部分的单个标准接口 (CryptoStream)。由于所有对象都在标准接口上生成,所以可以将多个对象(如一个哈希对象后跟一个加密对象)链接在一起,并且可以对数据执行多个操作而不需要为数据提供任何中间存储。使用流模型时还可以用更小的对象生成对象。例如,可以将加密算法和哈希算法的组合视为单个流对象(即使该对象可能是从一组流对象生成的)。

    加密配置

    使用加密配置可以将算法的特定实现解析为算法名称,从而使 .NET Framework 加密类具有可扩展性。您可以添加自己的硬件或软件算法实现,并将该实现映射到您选择的算法名称上。如果未在配置文件中指定算法,则使用默认设置。有关加密配置的更多信息,请参见配置加密类

    代码:

    代码
    1 #region 使用散列方式加密 MD5加密
    2
    3 /// <summary>
    4 /// 使用MD5对字符串进行加密
    5 /// </summary>
    6 /// <param name="str">需要加密的字符串</param>
    7 /// <returns>加密后的字符串</returns>
    8   public static string MD5Encrypts(string str)
    9 {
    10 string result = string.Empty;
    11 //先将要加密的字符串转换成byte数组
    12   byte[] inputData = System.Text.Encoding.Default.GetBytes(str);
    13 //在通过MD5类加密,并得到加密后的byte[]类型
    14   byte[] data = System.Security.Cryptography.MD5.Create().ComputeHash(inputData);
    15
    16 StringBuilder strBuild = new StringBuilder();
    17 for (int i = 0; i < data.Length; i++)
    18 {
    19 //将每个byte数据转换成16进制。"X":表示大写16进制;"X2":表示大写16进制保留2位;"x":表示小写16进制
    20   strBuild.Append(data[i].ToString("X2"));
    21 }
    22 result = strBuild.ToString();
    23 return result;
    24 }
    25
    26 #endregion

    代码
    1 #region 使用对称加密、解密
    2
    3 /// <summary>
    4 /// 使用对称算法加密
    5 /// </summary>
    6 /// <param name="str"></param>
    7 /// <param name="encryptKey"></param>
    8 /// <returns></returns>
    9   public static string SymmetricEncrypts(string str, string encryptKey)
    10 {
    11 string result = string.Empty;
    12 byte[] inputData = System.Text.Encoding.UTF8.GetBytes(str);
    13 byte[] IV = { 0x77, 0x70, 0x50, 0xD9, 0xE1, 0x7F, 0x23, 0x13, 0x7A, 0xB3, 0xC7, 0xA7, 0x48, 0x2A, 0x4B, 0x39 };
    14 try
    15 {
    16 byte[] byKey = System.Text.Encoding.UTF8.GetBytes(encryptKey);
    17 //如需指定加密算法,可在Create()参数中指定字符串
    18 //Create()方法中的参数可以是:DES、RC2 System、Rijndael、TripleDES
    19 //采用不同的实现类对IV向量的要求不一样(可以用GenerateIV()方法生成),无参数表示用Rijndael
    20   SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create();//产生一种加密算法
    21   MemoryStream msTarget = new MemoryStream();
    22 //定义将数据流链接到加密转换的流。
    23   CryptoStream encStream = new CryptoStream(msTarget, Algorithm.CreateEncryptor(byKey, IV), CryptoStreamMode.Write);
    24 encStream.Write(inputData, 0, inputData.Length);
    25 encStream.FlushFinalBlock();
    26 result = Convert.ToBase64String(msTarget.ToArray());
    27 }
    28 catch (Exception)
    29 {
    30 return null;
    31 }
    32 return result;
    33 }
    34
    35
    36 /// <summary>
    37 /// 使用对称算法解密
    38 /// </summary>
    39 /// <param name="encryptStr"></param>
    40 /// <param name="encryptKey"></param>
    41 /// <returns></returns>
    42   public static string SymmectricDecrypts(string encryptStr, string encryptKey)
    43 {
    44 string result = string.Empty;
    45 //加密时使用的是Convert.ToBase64String(),解密时必须使用Convert.FromBase64String()
    46   try
    47 {
    48 byte[] encryptData = Convert.FromBase64String(encryptStr);
    49 byte[] byKey = System.Text.Encoding.UTF8.GetBytes(encryptKey);
    50 byte[] IV = { 0x77, 0x70, 0x50, 0xD9, 0xE1, 0x7F, 0x23, 0x13, 0x7A, 0xB3, 0xC7, 0xA7, 0x48, 0x2A, 0x4B, 0x39 };
    51 SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create();
    52 MemoryStream msTarget = new MemoryStream();
    53 CryptoStream decStream = new CryptoStream(msTarget, Algorithm.CreateDecryptor(byKey, IV), CryptoStreamMode.Write);
    54 decStream.Write(encryptData, 0, encryptData.Length);
    55 decStream.FlushFinalBlock();
    56 result = System.Text.Encoding.Default.GetString(msTarget.ToArray());
    57 }
    58 catch (Exception)
    59 {
    60 return null;
    61 }
    62 return result;
    63 }
    64
    65 #endregion

    代码
    #region 使用非对称算法加密、解密

    /// <summary>
    /// 在非对称加密时,产生“公钥”和“私钥”
    /// </summary>
    public static void GeneratePrivateKey()
    {
    RSACryptoServiceProvider RSA
    = new RSACryptoServiceProvider();

    //产生私钥
    string privatekey = RSA.ToXmlString(true);

    //产生公钥
    string publicKey = RSA.ToXmlString(false);
    }

    /// <summary>
    /// 非对称加密
    /// </summary>
    /// <param name="str">要加密的数据</param>
    /// <param name="publicKey">公钥</param>
    /// <returns>加密结果</returns>
    public static string AsymmectricEncrypts(string str, string publicKey)
    {
    string result = string.Empty;

    RSACryptoServiceProvider RSA
    = new RSACryptoServiceProvider();
    byte[] data = System.Text.Encoding.UTF8.GetBytes(str);
    //设置公钥
    RSA.FromXmlString(publicKey);
    byte[] btResult = RSA.Encrypt(data, true);
    result
    = Convert.ToBase64String(btResult);
    return result;
    }

    /// <summary>
    /// 非对称加密后的解密
    /// </summary>
    /// <param name="strcode">加密后的字符串</param>
    /// <param name="privateKey">密钥(私钥)</param>
    /// <returns>解密后的结果</returns>
    public static string AsymmectricDecrypts(string strcode, string privateKey)
    {
    string result = string.Empty;
    byte[] bydata = Convert.FromBase64String(strcode);
    RSACryptoServiceProvider RSA
    = new RSACryptoServiceProvider();
    //私钥
    RSA.FromXmlString(privateKey);
    byte[] byR = RSA.Decrypt(bydata, true);
    result
    = System.Text.Encoding.UTF8.GetString(byR);
    return result;
    }

    #endregion
  • 相关阅读:
    nginx负载均衡代理配置脚本
    想查看下编译安装的nginx默认都带有哪些模块
    docker安装mysql8.0.18
    Reached target Basic System
    layer iframe的一些操作记录:
    微信JSAPI支付
    用go和python实现在图片里藏图片
    go反射优化
    go图片灰度化
    golang 创建发送邮件服务
  • 原文地址:https://www.cnblogs.com/zxhoo/p/1949126.html
Copyright © 2011-2022 走看看