当前位置: 首页 > 知识库问答 >
问题:

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

商俊智
2023-03-14

我有一个安全课程的项目,但我有一个问题。

基本上,我试图加密然后解密一个密码,但我得到这个解密错误。

我这样做对吗。我在关注2012年的一篇文章。还安全吗?

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

“AES”、“RSA/ECB/PKCS1Padding”、“PbeWithHMACSHA256andDesede”..以及更多

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个答案

楚瑞
2023-03-14

您已经将密文的base64编码放入encryptedpassword中。您需要首先对该字符串进行base64解码,然后解密实际的密文。而且由于您的明文是UTF-8,您应该将解密的明文解释为UTF-8。

return new String( pbeCipher.doFinal(Base64.getDecoder().decode(property)), "UTF-8");

而且没有一个DES是不安全的,事实上,根据攻击者的能力,它至少已经在蛮力范围内运行了十年。它从1999年左右就被否决了,首先是“Triple-DES”(正式的TDEA)和后来的AES。据我回忆,大约在2005年被正式撤回。请参阅https://en.wikipedia.org/wiki/data_encryption_standard的第二段。2012年写的任何建议使用DES的东西都是不称职的。

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

(已更新)所有最新Oracle Java中的内置提供程序包括CipherPbeWithSha1andDesede和SecretKeyFactoryPbkdf2WithHMacSha1,前者要好得多,后者可以构造任何(合理的)PBES2密码。(前者实际上是PKCS#12PBEWITHSHAAND3-KeyTripleDS-CBC,正式名称为1.2.840.113549.1.12.1.3.)Java 8(仅)添加了几个好的PBES2预打包为CipherPBEWITHHMACSHA{1,224,256,384,512}和AES_{128,256}。其中任何一个都可以,尽管对于SHA1,您可能必须向不知情的人解释SHA1现在被认为有碰撞的危险,并且被禁止用于证书,但是对于KDF和PBE仍然可以,您可以通过使用任何SHA2,可能是最受欢迎的SHA256来避免。另外,您应该使用比20次更多的迭代;即使在1998年RFC2898建议至少1000个,而今天至少10个千个,通常100万或更多是流行的。

 类似资料: