zoukankan      html  css  js  c++  java
  • 对称加密DES和TripleDES

    原文地址: http://www.cnblogs.com/chnking/archive/2007/08/14/855600.html

    一、  对称加密

    对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码)。因此,通信双方都必须获得这把钥匙,并保持钥匙的秘密。

    单钥密码系统的安全性依赖于以下两个因素:

    第一、加密算法必须是足够强的,仅仅基于密文本身去解密信息在实践上是不可能的。

    第二、加密方法的安全性依赖于密钥的秘密性,而不是算法的秘密性,因此,我们没有必要确保算法的秘密性(事实上,现实中使用的很多单钥密码系统的算法都是公开的),但是我们一定要保证密钥的秘密性。

    DES(Data Encryption Standard)和TripleDES是对称加密的两种实现。

    DES和TripleDES基本算法一致,只是TripleDES算法提供的key位数更多,加密可靠性更高。

    DES使用的密钥key为8字节,初始向量IV也是8字节。

    TripleDES使用24字节的key,初始向量IV也是8字节。

    两种算法都是以8字节为一个块进行加密,一个数据块一个数据块的加密,一个8字节的明文加密后的密文也是8字节。如果明文长度不为8字节的整数倍,添加值为0的字节凑满8字节整数倍。所以加密后的密文长度一定为8字节的整数倍。

       本文测试源代码:/Files/chnking/TripleDESTest.rar

    二、  加密解密过程

     


    Figure 1. DES加密解密过程

     

    上图是整个DES和TripleDES算法的加密解密过程,下面以TripleDES为例,结合dotnet分析加密解密的各个步骤,并给出相关实现代码。

    1、 生成key和IV

    System.Security.Cryptography. TripleDESCryptoServiceProvider类是dotnet中实现TripleDES算法的主要的类。

    TripleDESCryptoServiceProvider类只有一个构造方法TripleDESCryptoServiceProvider(),这个方法把一些属性初始化:

    KeySize(加密密钥长度,以位为单位)= 192(24字节)

    BlockSize(加密处理的数据块大小,以位为单位)= 64(8字节)

    FeedbackSize(加密数据块后返回的数据大小,以位为单位)= 64(8字节)

    TripleDESCryptoServiceProvider构造方法同时会初始化一组随机的key和IV。

    默认的TripleDESCryptoServiceProvider的key为24字节,IV为8字节,加密数据块为8字节。

    生成key和IV的代码很简单:

    TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();

    byte[] keyArray = tDESalg.Key;

    byte[] IVArray = tDESalg.IV;

    生成的key和IV在加密过程和解密过程都要使用。

    2、 字符串明文转成某一代码页对应的编码字节流

    待加密的数据可能有两种形式,一种是二进制的数据,本身就是一组字节流,这样的数据可以跳过这一步,直接进入加密步骤。还有一种情况是字符串数据,字符串中同样的字符使用不同的代码页会生成不同的字节码,所以从字符串到字节流的转换是需要指定使用何种编码的。在解密之后,要从字节流转换到字符串就要使用相同的代码页解码,否则就会出现乱码。

    // 待加密的字符串

    string plainTextString = "Here is some data to encrypt. 这里是一些要加密的数据。";

    // 使用utf-8编码(也可以使用其它的编码)

    Encoding sEncoding = Encoding.GetEncoding("utf-8");

    // 把字符串明文转换成utf-8编码的字节流

    byte[] plainTextArray = sEncoding.GetBytes(plainTextString);

    3、 加密操作

    加密的原料是明文字节流,TripleDES算法对字节流进行加密,返回的是加密后的字节流。同时要给定加密使用的key和IV。

    // 把字符串明文转换成utf-8编码的字节流

    byte[] plainTextArray = sEncoding.GetBytes(plainTextString);

    public static byte[] EncryptString(byte[] plainTextArray, byte[] Key, byte[] IV)

    {

        // 建立一个MemoryStream,这里面存放加密后的数据流

        MemoryStream mStream = new MemoryStream();

        // 使用MemoryStream 和key、IV新建一个CryptoStream 对象

        CryptoStream cStream = new CryptoStream(mStream,

            new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),

            CryptoStreamMode.Write);

        // 将加密后的字节流写入到MemoryStream

        cStream.Write(plainTextArray, 0, plainTextArray.Length);

        //把缓冲区中的最后状态更新到MemoryStream,并清除cStream的缓存区

        cStream.FlushFinalBlock();

        // 把解密后的数据流转成字节流

        byte[] ret = mStream.ToArray();

        // 关闭两个streams.

        cStream.Close();

        mStream.Close();

        return ret;

    }

    4、 解密操作

    解密操作解密上面步骤生成的密文byte[],需要使用到加密步骤使用的同一组Key和IV。

    // 调用解密方法,返回已解密数据的byte[]

    byte[] finalPlainTextArray = DecryptTextFromMemory(Data, keyArray, IVArray);

    public static byte[] DecryptTextFromMemory(byte[] EncryptedDataArray, byte[] Key, byte[] IV)

    {

        // 建立一个MemoryStream,这里面存放加密后的数据流

        MemoryStream msDecrypt = new MemoryStream(EncryptedDataArray);

        // 使用MemoryStream 和key、IV新建一个CryptoStream 对象

        CryptoStream csDecrypt = new CryptoStream(msDecrypt,

            new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),

            CryptoStreamMode.Read);

        // 根据密文byte[]的长度(可能比加密前的明文长),新建一个存放解密后明文的byte[]

        byte[] DecryptDataArray = new byte[EncryptedDataArray.Length];

        // 把解密后的数据读入到DecryptDataArray

        csDecrypt.Read(DecryptDataArray, 0, DecryptDataArray.Length);

        msDecrypt.Close();

        csDecrypt.Close();

        return DecryptDataArray;

    }

    有一点需要注意,DES加密是以数据块为单位加密的,8个字节一个数据块,如果待加密明byte[]的长度不是8字节的整数倍,算法先用值为“0”的byte补足8个字节,然后进行加密。所以加密后的密文长度一定是8的整数倍。这样的密文解密后如果补了0值的byte,则解密后这些0值的byte依然存在。比如上例中要加密的明文是:

    “Here is some data to encrypt. 这里是一些要加密的数据。”

    转成明文byte[]后是66个字节,DES算法就会补上6个0值的byte,补到72个字节。这样加密后再解密回来的密文byte[]解码后的字符串就是这样的:

    "Here is some data to encrypt. 这里是一些要加密的数据。"

    5、 从编码字节流转成字符串明文

    // 使用前面定义的Encoding,utf-8的编码把byte[]转成字符串

    plainTextString = sEncoding.GetString(finalPlainTextArray);

  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/AloneSword/p/3316864.html
Copyright © 2011-2022 走看看