Java IllegalBlocksizeException-如何使用Base64解决

Java IllegalBlocksizeException-如何使用Base64解决,java,security,cryptography,aes,Java,Security,Cryptography,Aes,我在下面的代码中遇到了一些问题-我似乎得到了一个非法的BlockSizeException,并且不确定我在这里可能做得不正确是什么?有没有可能得到一些建议/建议 谢谢 public class Encryption { private SecretKeyFactory factory; private SecretKey tmp; private SecretKey secret; private Cipher ci

我在下面的代码中遇到了一些问题-我似乎得到了一个非法的BlockSizeException,并且不确定我在这里可能做得不正确是什么?有没有可能得到一些建议/建议

谢谢

    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)

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

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

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

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

 cipherText = cipher.doFinal(Base64.decodeBase64(valueToEncrypt.getBytes()));
valueToEncrypt是一个可读字符串,但您正在尝试对其进行解密。由于它只有小写字母和空格,因此可能不会触发错误,但您正在尝试对未进行base64编码的内容进行base64解码。尝试以下操作更有意义:

cipherText = cipher.doFinal(valueToEncrypt.getBytes());
然后可以对密文进行base64编码

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


最后一个建议是:考虑模块化。在一行中编码,在另一行中加密,因此如果要删除或添加层,只需在一行中切换注释。

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

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

 cipherText = cipher.doFinal(Base64.decodeBase64(valueToEncrypt.getBytes()));
valueToEncrypt是一个可读字符串,但您正在尝试对其进行解密。由于它只有小写字母和空格,因此可能不会触发错误,但您正在尝试对未进行base64编码的内容进行base64解码。尝试以下操作更有意义:

cipherText = cipher.doFinal(valueToEncrypt.getBytes());
然后可以对密文进行base64编码

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


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

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

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

cipher.doFinal(new Base64().encode(encryptedValueToDecrypt.getBytes()))
这应该是:

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

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

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

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

cipher.doFinal(new Base64().encode(encryptedValueToDecrypt.getBytes()))
这应该是:

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

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

我不认为base64是您问题的根源,但是您可以将堆栈跟踪添加到问题中吗?(或者,至少指定您在哪一行获得问题)。Hi Sergio-stack trace Added我不认为base64是您问题的根源,但是您可以将堆栈跟踪添加到问题中吗?(或者,至少指定您在哪一行获得问题).Hi Sergio-stack trace addedHaving看了一下我将在这里使用AES的bouncy castle实现-感谢您的支持help@Biscuit128这个网站并不是真的推荐图书馆,但我也会告诉你一些功能。BouncyCastle很好,因为它很全面,而且是由知识渊博的人编写的,但它很大而且是低级的,这使得它本身就更难使用。除此之外,文档很糟糕。Apache Shiro更高级,使用更具指导性,更易于使用。@128域名已经改变了,我将在这里使用AES的bouncy castle实现-感谢您的支持help@Biscuit128这个网站不是关于推荐图书馆,但我也会向您介绍一些功能。BouncyCastle很好,因为它是全面的,由知识渊博的人编写,但它又大又低,因此它是固有的