【问题标题】:IllegalBlocksizeException - How to use Base64 to solveIllegalBlocksizeException - 如何使用Base64解决
【发布时间】:2023-03-06 05:09:02
【问题描述】:

我在使用以下代码时遇到了一些问题 - 我似乎遇到了 IllegalBlocksizeException 并且不确定我在这里可能做错了什么?能否得到一些建议/指点?

谢谢

    public class Encryption
    {
        private SecretKeyFactory factory;
        private SecretKey tmp;
        private SecretKey secret;
        private Cipher cipher;

        private byte[] iv;
        private byte[] cipherText;

        private final KeySpec spec = new PBEKeySpec("somepassword".toCharArray(), SALT, 65536, 256);
        private static final byte[] SALT = {(byte)0xc3, (byte)0x23, (byte)0x71, (byte)0x1c, (byte)0x2e, (byte)0xc2, (byte)0xee, (byte)0x77};

        public Encryption()
        {
            try
            {
                factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
                tmp = factory.generateSecret(spec);
                secret = new SecretKeySpec(tmp.getEncoded(), "AES");
                cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, secret);
                iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        public String encrypt(String valueToEncrypt) throws Exception
        {
            cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
            cipherText = cipher.doFinal(Base64.decodeBase64(valueToEncrypt.getBytes()));
            return Base64.encodeBase64String(cipherText);
        }

        public String decrypt(String encryptedValueToDecrypt) throws Exception
        {
            cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
            return new String(cipher.doFinal(new Base64().encode(encryptedValueToDecrypt.getBytes())));
        }

        public static void main(String[] args ) throws Exception
        {
            Encryption manager = new Encryption();
            String encrypted = manager.encrypt("this is a string which i would like to encrypt");
            System.out.println(encrypted);
            String decrypted = manager.decrypt(encrypted);
            System.out.println(decrypted);
            System.out.println(encrypted.equals(decrypted));
        }
}

异常如下

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at encrypt.Encryption.decrypt(Encryption.java:52)
    at encrypt.Encryption.main(Encryption.java:60)

【问题讨论】:

  • 我不认为 base64 是您问题的根源,但您可以将堆栈跟踪添加到问题中吗? (或者,至少,指定您在哪一行遇到问题)。
  • 嗨 Sergio - 添加了堆栈跟踪

标签: java security cryptography aes


【解决方案1】:

从功能的角度来看,从实现加密算法开始的唯一方法是(请记住,工作代码不一定是安全的,应该在这个方向上进行很多思考)是增量:首先尝试使用固定密钥的原始 AES,然后添加由 PBKDF2 生成的密钥,然后再添加 Base64。后者只是一个编码工具,应该是这个过程中最简单的部分。

但是让我们看一下代码: 1. 如果您的目标是从密码中生成密钥,那么初始化似乎很好。 2.解密过程中,这条线不亮:

 cipherText = cipher.doFinal(Base64.decodeBase64(valueToEncrypt.getBytes()));

valueToEncrypt 是一个可读的字符串,但您正在尝试解密它。由于它只有小写字母和空格,因此可能不会触发错误,但您正在尝试对未经过 base64 编码的内容进行 base64 解码。尝试一下会更有意义:

cipherText = cipher.doFinal(valueToEncrypt.getBytes());

那么cipherText就可以base64编码了。

对于解密部分,以相反的顺序撤消加密中的操作。如果先加密后base64编码,则先base64解码再解密。

作为最后的建议:考虑模块化。在一行中编码并在另一行中加密,因此如果要删除或添加层,只需在一行中切换 cmets。

【讨论】:

    【解决方案2】:

    您已反转 base-64 编码和解码操作。 Base-64 获取原始字节并将它们转换为可打印的文本。您可以对加密操作的输出进行编码以使其可打印。但是,您需要在尝试解密之前对该文本进行 base-64 解码。

    您的decrypt() 方法的这一部分导致了问题:

    cipher.doFinal(new Base64().encode(encryptedValueToDecrypt.getBytes()))
    

    应该是:

    cipher.doFinal(Base64.decodeBase64(encryptedValueToDecrypt.getBytes()))
    

    要求“指针”是非常开放的。我能给你的最好的指示:不要自己编写这段代码。选择提供更高级别 API 的包,选择高安全性算法并根据最佳实践应用它们。你不知道自己在做什么,也无法编写安全代码。但是使用高质量的开源库可能会帮助您开始了解有关加密的更多信息。

    【讨论】:

    【解决方案3】:

    您可能应该在解密之前对 encryptedValueToDecrypt 进行 base64 解码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-30
      • 2017-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多