IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    常见DES实现陷阱

    蔡晓建 (mc02cxj@gmail.com)发表于 2014-12-29 00:00:00
    love 0

    DES要点说明

    • DES走的是分组加密,每次处理对象的是8位byte,所以对字符串加解密的时候,会涉及字符编码格式和补齐8位的问题。
    • DES的密钥是固定8位的byte的,其中前7位是加解密用的,最后一位是校验码。
    • 3DES的增强型的DES,带3个key,如果3个key一样,就是DES,也有一种变种是1、3是一样的。但都是固定8位的。
    • 3DES通常是EDE,就是先加密(k1)再解密(k2)再加密(k3)

    目前,项目代码中有3个和DES实现相关的类,下面看看他们有哪些问题:

    案例1

    • 从字符串到byte的转换,有指定编码格式GBK,这个是可以接受的。
    • 使用的是DESede,就是3DES的EDE加密方式,但是3个key是一样的,没有意义。
    • 加密时代码先自行进行了补齐操作(补\0),但是补齐是在字符串上操作的,不是在字节上操作,导致实际上可能没有对齐(中文情况)。
    • 调用加密API时,没有指定补齐方式,会采用默认补齐,造成重复补齐(当然也修复了上面的补齐操作)。
    • 解密指定NoPadding,和加密Padding方式不一样,造成解密结果最后会出现很多多余的字节。所以结果必须得trim一下才行。

    参考代码如下:

    补齐实现有误:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    public String encrypt(String in) throws Exception {
        String strIn = in;
        if (null == strIn || "".equals(strIn)) {
            return "";
        }
    
        int i = 0;
        i = strIn.length() % 8;
    
        if (0 == i) {
            for (i = 0; i < 8; i++) {
                strIn += "\0";
            }
        } else {
            while (i > 0) {
                strIn += "\0";
                i--;
            }
        }
        byte[] bytes = strIn.getBytes(CHARSET);
        byte[] enbytes = encryptCipher.doFinal(bytes);
        return byteArrToHexStr(enbytes);
    }
    

    key是一样的,补齐方式没对应上:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    public DESedeEncrypt() {
        byte[] buffer = new byte[] {
                0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
                0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
        };
    
        SecretKeySpec key = new SecretKeySpec(buffer, "DESede");
    
        try {
            encryptCipher = Cipher.getInstance(KEY_ALGORITHM);
            encryptCipher.init(Cipher.ENCRYPT_MODE, key);
            decryptCipher = Cipher.getInstance("DESede/ECB/NoPadding");
            decryptCipher.init(Cipher.DECRYPT_MODE, key);
        } catch (NoSuchAlgorithmException e) {
            Throwables.propagate(e);
        } catch (NoSuchPaddingException e) {
            Throwables.propagate(e);
        } catch (InvalidKeyException e) {
            Throwables.propagate(e);
        }
    }
    

    案例2

    • 从字符串到byte的转换,采用了系统默认编码,存在平台移植性问题。
    • 密钥key的长度布置8位,有多余字符(虽然只取前8位避免出错),造成混乱。

    key的格式不标准,有多余字符:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    private static String strDefaultKey = "mywebsite123456%";
    private Key getKey(byte[] arrBTmp) throws Exception {
        byte[] arrB = new byte[8];
        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }
    
        Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
    
        return key;
    }
    

    案例3

    • 从字符串到byte的转换,采用了系统默认编码,存在平台移植性问题。
    • 实现不是标准的DES,或3DES,是在DES基础上定义了一套加密。
    • 根据目前key的长度,比标准3DES都要慢很多,另外没有采用JDK带的API。

    key的长度不标准:

    1
    2
    3
    4
    5
    
    public class DesUtil {
        public static final String firstKey = "com.xxx.xxxpro";
        public static final String secondKey = "xxx_web";
        public static final String thirdKey = "xxxservice";
    }
    

    实现方式是对每个key补齐8位,再切割形成每组多个8位的key,再采用EEE的方式进行处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
                        for (x = 0; x < firstLength; x++) {
                            tempBt = enc(tempBt, (int[]) firstKeyBt.get(x));
                        }
                        for (y = 0; y < secondLength; y++) {
                            tempBt = enc(tempBt, (int[]) secondKeyBt.get(y));
                        }
                        for (z = 0; z < thirdLength; z++) {
                            tempBt = enc(tempBt, (int[]) thirdKeyBt.get(z));
                        }
    


沪ICP备19023445号-2号
友情链接