zoukankan      html  css  js  c++  java
  • ◆JAVA加密解密-DES

    DES算法提供CBC, OFB, CFB, ECB四种模式,MAC是基于ECB实现的。

    一、数据补位

    DES数据加解密就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节(通常补00或者FF,根据实际要求不同)进行计算,之后按照顺序将计算所得的数据连在一起即可。

    这里有个问题就是为什么要进行数据补位?主要原因是DES算法加解密时要求数据必须为8个字节。

    二、ECB模式

    DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。

    三、CBC模式

    DES CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。其实现的机理如下:

    加密步骤如下:

    1)首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)

    2)第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)

    3)第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2

    4)之后的数据以此类推,得到Cn

    5)按顺序连为C1C2C3......Cn即为加密结果。

    解密是加密的逆过程,步骤如下:

    1)首先将数据按照8个字节一组进行分组得到C1C2C3......Cn

    2)将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)

    3)将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D2

    4)之后依此类推,得到Dn

    5)按顺序连为D1D2D3......Dn即为解密结果。

    这里注意一点,解密的结果并不一定是我们原来的加密数据,可能还含有你补得位,一定要把补位去掉才是你的原来的数据。

      1 **
      2 * DES算法
      3 */
      4 public class DES {
      5    /**
      6    *
      7    * @return DES算法密钥
      8    */
      9    public static byte[] generateKey() {
     10         try {
     11 
     12             // DES算法要求有一个可信任的随机数源
     13             SecureRandom sr = new SecureRandom();
     14 
     15             // 生成一个DES算法的KeyGenerator对象
     16             KeyGenerator kg = KeyGenerator.getInstance("DES");
     17             kg.init(sr);
     18 
     19             // 生成密钥
     20             SecretKey secretKey = kg.generateKey();
     21 
     22             // 获取密钥数据
     23             byte[] key = secretKey.getEncoded();
     24 
     25             return key;
     26         } catch (NoSuchAlgorithmException e) {
     27             System.err.println("DES算法,生成密钥出错!");
     28             e.printStackTrace();
     29         }
     30 
     31         return null;
     32    }
     33 
     34    /**
     35    * 加密函数
     36    *
     37    * @param data
     38    *            加密数据
     39    * @param key
     40    *            密钥
     41    * @return 返回加密后的数据
     42    */
     43    public static byte[] encrypt(byte[] data, byte[] key) {
     44 
     45         try {
     46 
     47             // DES算法要求有一个可信任的随机数源
     48             SecureRandom sr = new SecureRandom();
     49 
     50             // 从原始密钥数据创建DESKeySpec对象
     51             DESKeySpec dks = new DESKeySpec(key);
     52 
     53             // 创建一个密匙工厂,然后用它把DESKeySpec转换成
     54             // 一个SecretKey对象
     55             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
     56             SecretKey secretKey = keyFactory.generateSecret(dks);
     57 
     58             // using DES in ECB mode
     59             Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
     60 
     61             // 用密匙初始化Cipher对象
     62             cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);
     63 
     64             // 执行加密操作
     65             byte encryptedData[] = cipher.doFinal(data);
     66 
     67             return encryptedData;
     68         } catch (Exception e) {
     69             System.err.println("DES算法,加密数据出错!");
     70             e.printStackTrace();
     71         }
     72 
     73         return null;
     74    }
     75 
     76    /**
     77    * 解密函数
     78    *
     79    * @param data
     80    *            解密数据
     81    * @param key
     82    *            密钥
     83    * @return 返回解密后的数据
     84    */
     85    public static byte[] decrypt(byte[] data, byte[] key) {
     86         try {
     87             // DES算法要求有一个可信任的随机数源
     88             SecureRandom sr = new SecureRandom();
     89 
     90             // byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */;
     91 
     92             // 从原始密匙数据创建一个DESKeySpec对象
     93             DESKeySpec dks = new DESKeySpec(key);
     94 
     95             // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
     96             // 一个SecretKey对象
     97             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
     98             SecretKey secretKey = keyFactory.generateSecret(dks);
     99 
    100             // using DES in ECB mode
    101             Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
    102 
    103             // 用密匙初始化Cipher对象
    104             cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);
    105 
    106             // 正式执行解密操作
    107             byte decryptedData[] = cipher.doFinal(data);
    108 
    109             return decryptedData;
    110         } catch (Exception e) {
    111             System.err.println("DES算法,解密出错。");
    112             e.printStackTrace();
    113         }
    114 
    115         return null;
    116    }
    117 
    118    /**
    119    * 加密函数
    120    *
    121    * @param data
    122    *            加密数据
    123    * @param key
    124    *            密钥
    125    * @return 返回加密后的数据
    126    */
    127    public static byte[] CBCEncrypt(byte[] data, byte[] key, byte[] iv) {
    128 
    129         try {
    130             // 从原始密钥数据创建DESKeySpec对象
    131             DESKeySpec dks = new DESKeySpec(key);
    132 
    133             // 创建一个密匙工厂,然后用它把DESKeySpec转换成
    134             // 一个SecretKey对象
    135             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    136             SecretKey secretKey = keyFactory.generateSecret(dks);
    137 
    138             // Cipher对象实际完成加密操作
    139             Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    140             // 若采用NoPadding模式,data长度必须是8的倍数
    141             // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
    142 
    143             // 用密匙初始化Cipher对象
    144             IvParameterSpec param = new IvParameterSpec(iv);
    145             cipher.init(Cipher.ENCRYPT_MODE, secretKey, param);
    146 
    147             // 执行加密操作
    148             byte encryptedData[] = cipher.doFinal(data);
    149 
    150             return encryptedData;
    151         } catch (Exception e) {
    152             System.err.println("DES算法,加密数据出错!");
    153             e.printStackTrace();
    154         }
    155 
    156         return null;
    157    }
    158 
    159    /**
    160    * 解密函数
    161    *
    162    * @param data
    163    *            解密数据
    164    * @param key
    165    *            密钥
    166    * @return 返回解密后的数据
    167    */
    168    public static byte[] CBCDecrypt(byte[] data, byte[] key, byte[] iv) {
    169         try {
    170             // 从原始密匙数据创建一个DESKeySpec对象
    171             DESKeySpec dks = new DESKeySpec(key);
    172 
    173             // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
    174             // 一个SecretKey对象
    175             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    176             SecretKey secretKey = keyFactory.generateSecret(dks);
    177 
    178             // using DES in CBC mode
    179             Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    180             // 若采用NoPadding模式,data长度必须是8的倍数
    181             // Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
    182 
    183             // 用密匙初始化Cipher对象
    184             IvParameterSpec param = new IvParameterSpec(iv);
    185             cipher.init(Cipher.DECRYPT_MODE, secretKey, param);
    186 
    187             // 正式执行解密操作
    188             byte decryptedData[] = cipher.doFinal(data);
    189 
    190             return decryptedData;
    191         } catch (Exception e) {
    192             System.err.println("DES算法,解密出错。");
    193             e.printStackTrace();
    194         }
    195 
    196         return null;
    197    }
    198 
    199    public static void main(String[] args) {
    200         try {
    201             byte[] key = "11111111".getBytes();
    202             byte[] iv = "22222222".getBytes();
    203             byte[] data = DES.encrypt("ebc mode test".getBytes(), key);
    204             System.out.print("EBC mode:");
    205             System.out.println(new String(DES.decrypt(data, key)));
    206             System.out.print("CBC mode:");
    207             data = DES.CBCEncrypt("cbc mode test".getBytes(), key, iv);
    208             System.out.println(new String(DES.CBCDecrypt(data, key, iv)));
    209             
    210         } catch (Exception e) {
    211             e.printStackTrace();
    212         }
    213    }
    214 }

    DES的几种填补方式 
       DES是对64位数据的加密算法,如数据位数不足64位的倍数,需要填充,补充到64位的倍数。 

       NoPadding 
       API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充或者空格,然后trim 

       PKCS5Padding 
       加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8 
       解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文 

    因为DES是一种block cipher,一个block要8个字节,所以要加密的东西要分成8字节的整数倍,不足的就填充。
    PKCS5Padding这种填充,填的字节代表所填字节的总数:

  • 相关阅读:
    testng失败截图,注解方式调用。
    HttpURLConnection和HttpClient
    JDK中的URLConnection参数详解
    如何做好Web接口测试
    selenium webdriver定位不到元素的五种原因及解决办法
    Selenium(Webdriver)自动化测试常问到的问题解答(转自:潜龙0318)
    常用网址记录
    python set
    python 浅拷贝和深拷贝
    python 元组
  • 原文地址:https://www.cnblogs.com/wangjuneng/p/4727050.html
Copyright © 2011-2022 走看看