Java解密 - 使用填充密码解密时,输入长度必须是8的倍数 [英] Java Decryption - Input length must be multiple of 8 when decrypting with padded cipher

查看:500
本文介绍了Java解密 - 使用填充密码解密时,输入长度必须是8的倍数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a project for a security course but i'm having an issue.

基本上,我正在尝试加密然后解密密码但我是为解密获取此错误。

basically , i'm trying to encrypt then decrypt a password but i'm getting this error for the decryption .

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

"Input length must be multiple of 8 when decrypting with padded cipher"

我这样做是对的办法 。我正在关注2012年的一篇文章。它仍然安全吗?

Am i doing this the right way . I was following an article from 2012 . Is it still secure ?

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

Also i tried replacing the algorithm but nothing seems to work :

AES ,RSA / ECB / PKCS1Padding,PBEWithHmacSHA256AndDESede..以及更多

"AES" , "RSA/ECB/PKCS1Padding" , "PBEWithHmacSHA256AndDESede"..and many more

我得到:

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

Exception in thread "main" java.security.NoSuchAlgorithmException: RSA/ECB/PKCS1Padding SecretKeyFactory not

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)


推荐答案

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

You've put the base64 encoding of the ciphertext in encryptedPassword. You need to first base64-decode that string and then decrypt the actual ciphertext. And since your plaintext was in UTF-8, you should interpret the decrypted plaintext as UTF-8.

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

没有 DES不安全,实际上一直都是粗暴的-force范围至少十年,具体取决于攻击者的能力。它自1999年左右开始被弃用,首先是三重DES(正式的TDEA),然后是AES,并在我回忆起于2005年左右正式撤销。请参阅 https://en.wikipedia.org/wiki/Data_Encryption_Standard 的第二段。 2012年建议使用DES的任何内容都是无能的。

And no DES is not secure, and in fact has been in brute-force range for at least a decade depending on attacker capabilities. It has been deprecated since about 1999, in favor first of "triple-DES" (formally TDEA) and then AES, and was officially withdrawn about 2005 as I recall. See the second paragraph of https://en.wikipedia.org/wiki/Data_Encryption_Standard . Anything written in 2012 that advised using DES was incompetent.

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

MD5 is broken for collision, and thus for signature (or at least certificate signature). As far as I know this doesn't translate into an attack on PBKDF, even the older and deprecated PBKDF1 used for PBEwithMD5andDES, but it has led many to prohibit all uses of MD5.

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

(updated) The builtin providers in all recent Oracle Java include Cipher PBEwithSHA1andDESede which is much better, and SecretKeyFactory PBKDF2WithHmacSHA1 from which you can construct any (reasonable) PBES2 cipher. (That former is actually PKCS#12 pbeWithSHAAnd3-keyTripleDES-CBC and formally known as 1.2.840.113549.1.12.1.3 .) Java 8 (only) adds several good PBES2 prepackaged as Cipher PBEWithHmacSHA{1,224,256,384,512}AndAES_{128,256}. Any of those is fine, although with SHA1 you might have to explain to uninformed people that SHA1 is now considered at risk for collision and prohibited for certificates but still fine for KDF and PBE, which you could avoid by just going to any of the SHA2, probably SHA256 as the most popular. Plus you should definitely use more iterations than 20; even in 1998 RFC2898 recommended at least 1000, and today at least 10s of thousands and usually a million or more is popular.

这篇关于Java解密 - 使用填充密码解密时,输入长度必须是8的倍数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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