【问题标题】:Password-based encryption fails when salt value changed [closed]当盐值更改时,基于密码的加密失败[关闭]
【发布时间】:2013-06-07 07:30:43
【问题描述】:

以下代码使用 PBE 算法,我知道SALT 数组用于在提供的密码中添加几个字节。但是当我试图从该数组中删除几个元素并且当我运行程序时它给出错误。

我的问题是,下面程序中使用的SALT 数组是否可以修改?如果是,为什么我在修改它时会出错?

请查看此代码并帮助我理解它。非常感谢除了这个SALT 数组之外的程序的简要说明。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class ProtectedConfigFile {

private static final char[] PASSWORD = "enfldsgbnlsngdlksdsgm".toCharArray();
private static final byte[] SALT = {
    (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
    (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
};

public static void main(String[] args) throws Exception {
    String originalPassword = "secret";
    System.out.println("Original password: " + originalPassword);
    String encryptedPassword = encrypt(originalPassword);
    System.out.println("Encrypted password: " + encryptedPassword);
    String decryptedPassword = decrypt(encryptedPassword);
    System.out.println("Decrypted password: " + decryptedPassword);
}

private static String encrypt(String property) 
throws GeneralSecurityException, UnsupportedEncodingException {
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
    SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
    Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
    pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
    return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
}

private static String base64Encode(byte[] bytes) {
    // NB: This class is internal, and you probably should use another impl
    return new BASE64Encoder().encode(bytes);
}

private static String decrypt(String property) 
throws GeneralSecurityException,       IOException {
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
    SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
    Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
    pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
    return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
}

private static byte[] base64Decode(String property) throws IOException {
    // NB: This class is internal, and you probably should use another impl
    return new BASE64Decoder().decodeBuffer(property);
}

}

例外是:

Exception in thread "main" java.lang.Exception: java.security.InvalidAlgorithmParameterException: Salt must be 8 bytes long 
  at TransactionTokenUtility.encrypt(TransactionTokenUtility.java:80) 
  at TransactionTokenUtility.generateToken(TransactionTokenUtility.java:144) 
  at TransactionTokenUtility.main(TransactionTokenUtility.java:51) 
Caused by: java.security.InvalidAlgorithmParameterException: Salt must be 8 bytes long 
  at com.sun.crypto.provider.SunJCE_ab.a(DashoA13*..) 
  at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(DashoA13*..) 

【问题讨论】:

  • SALT 数组元素的最后一个是否需要逗号?
  • @user2310289 不,但不疼。
  • "当我运行程序时它给出错误" > 总是,总是,总是在编写 SO 问题时发布错误。请编辑您的问题并包含堆栈跟踪。
  • 不,程序在 SALT 结尾有无逗号都可以正常运行。
  • 线程“主”java.lang.Exception 中的异常:java.security.InvalidAlgorithmParameterException:在 TransactionTokenUtility.encrypt(TransactionTokenUtility.java:80) 的 TransactionTokenUtility.generateToken(TransactionTokenUtility. java:144) 在 TransactionTokenUtility.main(TransactionTokenUtility.java:51) 引起:java.security.InvalidAlgorithmParameterException: Salt 在 com.sun.crypto.provider.SunJCE_ab.a(DashoA13*..) 的长度必须为 8 个字节.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(DashoA13*..)

标签: java security encryption cryptography salt


【解决方案1】:

答案是根据旧的 v1.5 PKCS#5 标准和 PBKDF1,盐应该包含 8 个随机八位字节(读取:字节)。 Oracle Java 实现(从 2002 年开始!)遵循此标准。这可以(并且已经)使用 Oracle 提供的源代码进行验证。

需要 8 个八位字节的标准:

  • PKCS#5 v1.5
  • 从 PKCS#5 v2.0 开始的 PBKDF 版本 1(为与 PKCS#5 兼容而定义)

至少需要 8 个八位字节的标准(作为推荐):

  • PKCS#5 标准 v2.0 及更高版本中的 PBKDF2

最好的办法是迁移到 PBKDF2。您将拥有更安全(NIST 接受)的算法,并且在盐长度方面具有更大的灵活性。

请注意,PKCS#5 中有关 Salt 的章节(第 4 章)谈到了至少 8 个八位字节作为最低安全要求。然而,这被 PBKDF1 的定义所推翻,它精确定义了 8 个八位字节。

【讨论】:

  • PKCS#5 标准是否规定 SALT 应始终为 8 个字节?请尝试运行该程序 16,32 或 64 字节,我得到同样的异常。感谢您的回复。
  • 嗯,有趣,我会尽快尝试(可能在下周的某个地方)
  • 抱歉更改晚了,我只是没时间了......
  • +1 删除了我的答案,你的好多了:-)
猜你喜欢
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2016-09-09
  • 2010-10-15
相关资源
最近更新 更多