zoukankan      html  css  js  c++  java
  • [转载]对称加密DES和TripleDES

    一、 对称加密 
    对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码)。因此,通信双方都必须获得这把钥匙,并保持钥匙的秘密。 
    单钥密码系统的安全性依赖于以下两个因素: 
    第一、加密算法必须是足够强的,仅仅基于密文本身去解密信息在实践上是不可能的。 
    第二、加密方法的安全性依赖于密钥的秘密性,而不是算法的秘密性,因此,我们没有必要确保算法的秘密性(事实上,现实中使用的很多单钥密码系统的算法都是公开的),但是我们一定要保证密钥的秘密性。 
    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字节的整数倍。

    本文测试源代码:http://files.cnblogs.com/files/chnking/TripleDESTest.rar

    二、 加密解密过程

    这里写图片描述

    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);

    出处:https://blog.csdn.net/yinhuaiya/article/details/52382741

  • 相关阅读:
    Spring中Model,ModelMap以及ModelAndView之间的区别
    ssm框架中Controller层的junit测试_我改
    Controller、Service、Dao进行Junit单元
    ssm controller层 junit单元测试
    spring常用注解
    Spring MVC测试框架
    ssm框架junit简单测试_我写
    spring注入时报错::No qualifying bean of type 'xxx.xxMapper'
    Eclipse 报 "The builder launch configuration could not be found" 错误
    IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)
  • 原文地址:https://www.cnblogs.com/AaronBear/p/8941707.html
Copyright © 2011-2022 走看看