Java解密 - 使用填充密码解密时,输入长度必须是8的倍数

时间:2015-12-05 19:48:35

标签: java security encryption cryptography

我有一个安全课程项目,但我遇到了问题。

基本上,我正在尝试加密,然后解密密码,但我得到了解密的错误。

“使用填充密码解密时,输入长度必须是8的倍数”

我是以正确的方式做到这一点的。我正在关注2012年的一篇文章。它还安全吗?

我也尝试更换算法,但似乎没有任何效果:

“AES”,“RSA / ECB / PKCS1Padding”,“PBEWithHmacSHA256AndDESede”......还有更多

我得到:

线程“main”中的异常java.security.NoSuchAlgorithmException:RSA / ECB / PKCS1Padding SecretKeyFactory不

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 java.util.Base64;

public class ProtectedConfigFile {

    private static final char[] PASSWORD = "ytfchchchgcv".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 Base64.getEncoder().encodeToString(pbeCipher.doFinal(property.getBytes("UTF-8")));
    }

    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));
        byte[] decode = Base64.getDecoder().decode(pbeCipher.doFinal(property.getBytes("UTF-8")));
        return decode.toString();
    }

}

返回:

Original password: secret
Encrypted password: eG+qiRan1Cw=
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.PBES1Core.doFinal(PBES1Core.java:416)
    at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(PBEWithMD5AndDESCipher.java:316)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at ProtectedConfigFile.decrypt(ProtectedConfigFile.java:43)
    at ProtectedConfigFile.main(ProtectedConfigFile.java:26)

1 个答案:

答案 0 :(得分:2)

您已将密文的base64编码放在Keep-Alive中。您需要首先 base64-decode该字符串,然后解密实际的密文。由于您的明文是UTF-8,您应该将解密的明文解释为UTF-8。

encryptedPassword

没有 DES不安全,事实上,根据攻击者的能力,实际上已经处于暴力范围至少十年。它自1999年左右开始被弃用,首先支持" triple-DES" (正式称为TDEA)然后是AES,我记得在2005年正式撤回。见https://en.wikipedia.org/wiki/Data_Encryption_Standard的第二段。 2012年建议使用DES的任何内容都是无能的。

MD5因冲突而中断,因此用于签名(或至少是证书签名)。据我所知,这并没有转化为对PBKDF的攻击,即使是旧的和已弃用的PBKDF1用于PBEwithMD5andDES,但它导致许多人禁止MD5的所有使用。

(已更新)所有最新Oracle Java中的内置提供程序包括更好的Cipher return new String( pbeCipher.doFinal(Base64.getDecoder().decode(property)), "UTF-8"); 和SecretKeyFactory PBEwithSHA1andDESede,您可以从中构建任何(合理的)PBES2密码。 (前者实际上是PKCS#12 pbeWithSHAAnd3-keyTripleDES-CBC,正式名称为1.2.840.113549.1.12.1.3。)Java 8(仅)将几个好的PBES2预先打包为密码PBKDF2WithHmacSHA1。任何一个都没问题,虽然使用SHA1你可能不得不向不知情的人解释SHA1现在被认为有发生冲突的风险并被禁止用于证书,但对于KDF和PBE仍然没问题,你可以通过去任何一个SHA2来避免,可能SHA256最受欢迎。另外,你绝对应该使用更多的迭代而不是20 ;甚至在1998年RFC2898推荐至少1000,而今天至少有数万,通常一百万或更多是受欢迎的。