javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是 16 的倍数 [英] javax.crypto.IllegalBlockSizeException : Input length must be multiple of 16 when decrypting with padded cipher

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

问题描述

我在 java 类中遇到解密错误:

I'm getting a decrypting error in java class:

javax.crypto.IllegalBlockSizeException : 
    Input length must be multiple of 16 when decrypting with padded cipher.

我该怎么做才能解决这个问题?

What can I do to solve this problem?

更新:

我忘了提到它正在工作一次,当我第二次尝试再次执行它时,它会抛出上述错误.

I forgot to mention it is working once and when the second time im trying to execute it again its throwing the above mentioned error.

package com.tb.module.service;
import java.security.Key;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.*;

/**
 * This class is used for encrypt and decrypt the  password field.
 *
 */
public class PswdEnc {

    private static final String ALGO = "AES";
    private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't','S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey(); 
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }


    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }

}

推荐答案

您使用的算法AES"是AES/ECB/NoPadding"的简写.这意味着您正在使用具有 128 位密钥大小和 块大小,带有ECBa> 操作模式无填充.

The algorithm you are using, "AES", is a shorthand for "AES/ECB/NoPadding". What this means is that you are using the AES algorithm with 128-bit key size and block size, with the ECB mode of operation and no padding.

换句话说:您只能加密 128 位或 16 字节块中的数据.这就是您收到 IllegalBlockSizeException 异常的原因.

In other words: you are only able to encrypt data in blocks of 128 bits or 16 bytes. That's why you are getting that IllegalBlockSizeException exception.

如果您想以不是 16 字节倍数的大小加密数据,您将不得不使用某种填充或密码流.例如,您可以使用 CBC 模式(一种有效转换块的操作模式通过指定AES/CBC/NoPadding"作为算法,将密码转换为流密码),或者通过指定AES/ECB/PKCS5",它将以非常特定的格式在数据末尾自动添加一些字节,以使密文的大小成为 16 字节的倍数,并且解密算法将理解它必须忽略一些数据.

If you want to encrypt data in sizes that are not multiple of 16 bytes, you are either going to have to use some kind of padding, or a cipher-stream. For instance, you could use CBC mode (a mode of operation that effectively transforms a block cipher into a stream cipher) by specifying "AES/CBC/NoPadding" as the algorithm, or PKCS5 padding by specifying "AES/ECB/PKCS5", which will automatically add some bytes at the end of your data in a very specific format to make the size of the ciphertext multiple of 16 bytes, and in a way that the decryption algorithm will understand that it has to ignore some data.

无论如何,我强烈建议你现在停止你正在做的事情,去学习一些关于密码学的非常介绍性的材料.例如,检查 Coursera 上的加密货币 I.您应该非常了解选择一种或另一种模式的含义,它们的优势是什么,最重要的是,它们的劣势是什么.如果没有这些知识,就很容易构建很容易被破坏的系统.

In any case, I strongly suggest that you stop right now what you are doing and go study some very introductory material on cryptography. For instance, check Crypto I on Coursera. You should understand very well the implications of choosing one mode or another, what are their strengths and, most importantly, their weaknesses. Without this knowledge, it is very easy to build systems which are very easy to break.

更新:根据您对问题的评论,在将密码存储在数据库中时永远不要加密!!!!!你永远不应该这样做.您必须散列密码,适当加盐,这与加密完全不同.真的,请不要做你想做的事......通过加密密码,它们可以被解密.这意味着您作为数据库管理员并且知道密钥,您将能够读取存储在数据库中的每个密码.要么你知道这一点并且正在做一些非常非常糟糕的事情,要么你不知道这一点,应该感到震惊并停止它.

Update: based on your comments on the question, don't ever encrypt passwords when storing them at a database!!!!! You should never, ever do this. You must HASH the passwords, properly salted, which is completely different from encrypting. Really, please, don't do what you are trying to do... By encrypting the passwords, they can be decrypted. What this means is that you, as the database manager and who knows the secret key, you will be able to read every password stored in your database. Either you knew this and are doing something very, very bad, or you didn't know this, and should get shocked and stop it.

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

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