Java中的openssl des3解密 [英] openssl des3 decrypting in java

查看:80
本文介绍了Java中的openssl des3解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法解密使用openssl -des3 enc命令.究竟openssl如何使用密码和盐作为密钥?

is there a way to decrypt files that have been encrypted using openssl -des3 enc command. Exactly how does openssl use the password and salt to make the key?

推荐答案

OpenSSL的 enc 实用程序对密码使用非标准(低质量)密钥派生算法.以下代码显示 enc 实用程序如何在给定salt和密码的情况下生成密钥和初始化向量.请注意,当指定 -salt 选项(并且对安全性至关重要)时, enc 将"salt"值存储在加密文件中.

OpenSSL's enc utility uses a non-standard (and low quality) key derivation algorithm for passwords. The following code shows how the enc utility generates the key and initialization vector, given salt and a password. Note that enc stores the "salt" value in the encrypted file when the -salt option is specified (and that is critical for security).

public InputStream decrypt(InputStream is, byte[] password)
  throws GeneralSecurityException, IOException
{
  /* Parse the "salt" value from the stream. */
  byte[] header = new byte[16];
  for (int idx = 0; idx < header.length;) {
    int n = is.read(header, idx, header.length - idx);
    if (n < 0)
      throw new EOFException("File header truncated.");
    idx += n;
  }
  String magic = new String(header, 0, 8, "US-ASCII");
  if (!"Salted__".equals(magic))
    throw new IOException("Expected salt in header.");

  /* Compute the key and IV with OpenSSL's non-standard method. */
  SecretKey secret;
  IvParameterSpec iv;
  byte[] digest = new byte[32];
  try {
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    md5.update(password);
    md5.update(header, 8, 8);
    md5.digest(digest, 0, 16);
    md5.update(digest, 0, 16);
    md5.update(password);
    md5.update(header, 8, 8);
    md5.digest(digest, 16, 16);
    iv = new IvParameterSpec(digest, 24, 8);
    DESedeKeySpec keySpec = new DESedeKeySpec(digest);
    SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
    secret = factory.generateSecret(keySpec);
  }
  finally {
    Arrays.fill(digest, (byte) 0);
  }

  /* Initialize the cipher. */
  Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
  cipher.init(Cipher.DECRYPT_MODE, secret, iv);
  return new CipherInputStream(is, cipher);
}

EVP_BytesToKey(3)文档. enc 命令使用 1 作为迭代 count (这是一个好主意,并记为我的 enc 版本的手册页中有一个bug),而MD5作为摘要算法-一种无效"算法.

This key and IV generation are described in the EVP_BytesToKey(3) documentation. The enc command uses 1 as the iteration count (which is a bad idea, and noted as a bug in the man page for my version of enc), and MD5 as the digest algorithm—a "broken" algorithm.

目前尚不清楚OpenSSL如何将文本密码转换为字节.我猜它使用默认的平台字符编码.因此,如果您使用的是 String 密码(不好,因为它不能归零"),则只需调用

It is not clear how a OpenSSL converts text password to bytes. I'm guessing it uses the default platform character encoding. So, if you are stuck with a String password (not good, since it can't be "zero-ized"), you can just call password.getBytes() to convert it to a byte[].

如果可以,请使用类似Java 6的 JPasswordField 来获取密码.它们返回一个数组,因此您可以在完成操作后从内存中删除"密码:

If you can, use something like Java 6's Console or Swing's JPasswordField to get a password. These return an array, so you can "delete" the password from memory when you are done with it: Arrays.fill(password, '\0');

这篇关于Java中的openssl des3解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆