新手问题 DES 加密问题 实现 Java 代码加密方式

scorpiusz · 2015年07月15日 · 最后由 glz1992 回复于 2017年09月15日 · 6349 次阅读

在实现 java 的 des 加密方式时 遇到一些问题
加密方式为"DES/CBC/PKCS5Padding" java 代码是这样的

public static String EncryptDES(String encryptString, String encryptKey)
{
    String ret = "";

    try
    {

        byte[] key = encryptKey.getBytes("UTF-8");
        DESKeySpec dks = new DESKeySpec(key);

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(dks);

        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        cipher.init(Cipher.ENCRYPT_MODE, securekey, iv);


        byte[] src = encryptString.getBytes("UTF-8");
        src = cipher.doFinal(src); 

        BASE64Encoder enc=new BASE64Encoder();
        ret = enc.encode(src);
    }
    catch(Exception ex)
    {
        System.out.println(ex.getMessage());
        System.out.println(ex.getStackTrace());

        ret = encryptString;
    }
    return ret;
}

文档写的是初始化向量是空向量 我查了查文档 用 ruby 实现的代码是

require 'openssl'
require 'base64'

def encrypt(str,key)
  cipher = OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC')
  cipher.encrypt
  cipher.pkcs5_keyivgen(key)
  result = cipher.update(str) + cipher.final
  Base64.encode64(result)
end


问题可能是 iv 设置上 ruby 和 java 有一些不同。。有没有什么建议的方式 实现这玩意啊。。

哦对了,测试 时 明文为 '123456' ,key 为'4B40A73D' 时,密文为‘2OdZEBDuPzQ=’

求建议。。。

cipher = OpenSSL::Cipher.new 'des-cbc'
cipher.encrypt
cipher.key = key
result = cipher.update(str) + cipher.final
Base64.encode64(result)

算法用错了。java 代码用了全 0 iv 所以 ruby 代码也不用设置

pkcs#5 padding 和 pkcs#5 不是一回事 pkcs#5 是通过 password 生成 key 和 iv 的规范 pkcs#5 padding 碰巧是这个规范里给的,补充明文使它可以被加密算法规定的长度整除的办法。OpenSSL 会按照加密算法自动采用 pkcs#5 / pkcs#7 padding

@luikore 哈哈谢谢你,搞定了。

@luikore 大神,搭车顺便问一下。我这段 java 代码翻译成 ruby 是怎样,没搞懂原理,试不出来 T_T

IvParameterSpec localIvParameterSpec = new IvParameterSpec(new byte[] { 12, 34, 34, 11, 64, 23, 89, 27 });

DESKeySpec localDESKeySpec = new DESKeySpec(paramString2.getBytes());

SecretKey localSecretKey = SecretKeyFactory.getInstance("DES").generateSecret(localDESKeySpec);

Cipher localCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

localCipher.init(1, localSecretKey, localIvParameterSpec);

return new String(Base64.encode(localCipher.doFinal(paramString1.getBytes()), 0));

感谢!

#3 楼 @kitkat

java 设置的 iv 相当于 ruby 的 cipher.iv = [12, 34, 34, 11, 64, 23, 89, 27].pack 'C*'

结果做个 base64 转换

@luikore 感谢指导!

@luikore

public static byte[] encrypt(String key_in, String mch_no) throws UnsupportedEncodingException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String key_str = mch_no + sdf.format(new Date());
        SecretKey key = null;
        try {
            key = makeDESKey(asc2bin(key_str));
        } catch (Exception e) {
            System.out.println("密钥生成失败"+e);
        }
        if (key == null) {
            System.out.println("密钥为空");
            return null;
        }
        System.out.println("----------key in -----------------"+key_in+"----------------key_str--------------"+key_str);
        byte[] key_byte = Base64.decodeToByteArray(key_in); //.decodeBase64(key_in);
        Cipher cipher;
        byte[] result = null;
        try {
            cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            result = cipher.doFinal(key_byte);
        } catch (Exception e) {
            System.out.println("加密失败。"+e);
        }
        return result;
    }


    private static byte[] asc2bin(String hexString) {
        byte[] hexbyte = hexString.getBytes(); // 得到系统默认编码的字节数组
        byte[] bitmap = new byte[hexbyte.length / 2];
        for (int i = 0; i < bitmap.length; i++) {
            hexbyte[i * 2] -= hexbyte[i * 2] > '9' ? 7 : 0;
            hexbyte[i * 2 + 1] -= hexbyte[i * 2 + 1] > '9' ? 7 : 0;
            bitmap[i] = (byte) ((hexbyte[i * 2] << 4 & 0xf0) | (hexbyte[i * 2 + 1] & 0x0f));
        }
        return bitmap;
    }

private static SecretKey makeDESKey(byte[] keybyte) throws Exception {
        DESKeySpec deskeyspec = new DESKeySpec(keybyte);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DES");
        return keyfactory.generateSecret(deskeyspec);
    }

麻烦问下,这种 java 代码用 ruby 如何写呢,现在写的 ruby 代码

def encryption_des(key, data_text)
  des = OpenSSL::Cipher.new("DES")
  des.encrypt
  des.key = [key].pack('H*')
  result = des.update(data_text)
  result << des.final
  result
end

用 ruby 转换出来的结果和 java 出来的结果只有部分一致,不知道问题出在哪里,麻烦帮忙看下,谢谢

tianlitao 回复

已经解决了,用的这种方式

cipher = OpenSSL::Cipher::DES.new("ECB")
cipher.encrypt
cipher.key = [key].pack('H*')
encrypted = cipher.update(text) + cipher.final
encrypted
tianlitao 回复

遇到个问题:

cipher.key= 这一步需要确保 key 是 8 bytes 的。

我的 key 是 "dzqdcps1602"

但是我执行后面的 [key].pack('H*') 始终是 6 bytes, 提示:ArgumentError: key must be 8 bytes

找到原因了,原来 ruby 2.4 做了修改,要开发者来截取固定长度的 key. 参考

需要 登录 后方可回复, 如果你还没有账号请 注册新账号