Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java密码非法BlockSizeException_Java_Exception_Encryption_Client Server - Fatal编程技术网

Java密码非法BlockSizeException

Java密码非法BlockSizeException,java,exception,encryption,client-server,Java,Exception,Encryption,Client Server,我刚刚有了一个“伟大”的想法,对来自客户端和服务器的发送/接收数据进行加密。但现在每次调用cipher.doFinal()时,我都会得到一个IllegalBlockSizeException(使用填充密码解密时,输入长度必须是16的倍数) 我的代码: 我创建了一个名为SecurityHandler的单例类,其中SecretKeySpec-keyspec、Cipher-Cipher和String-securitykey作为私有变量,在构造函数中初始化: private SecurityHandle

我刚刚有了一个“伟大”的想法,对来自客户端和服务器的发送/接收数据进行加密。但现在每次调用
cipher.doFinal()
时,我都会得到一个
IllegalBlockSizeException(使用填充密码解密时,输入长度必须是16的倍数)

我的代码:

我创建了一个名为
SecurityHandler
的单例类,其中
SecretKeySpec-keyspec
Cipher-Cipher
String-securitykey
作为私有变量,在构造函数中初始化:

private SecurityHandler()
{
    securitykey = "adnanyc83z43h1jbncxgsdfgs2134y";  // Example key

    try
    {
        keyspec = new SecretKeySpec(Arrays.copyOf(securitykey.getBytes("UTF-8"), 16), "AES");
        cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    }
    catch (final Exception e)
    {
        Logger.log("CipherInitializationException (" + e.getMessage() + ")", e);
    }
}
获取
算法参数spec
的方法:

public AlgorithmParameterSpec getIV()
{
    final byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    return new IvParameterSpec(iv);
}
以及我的加密/解密方法:

public String encrypt(final String text)
{
    try
    {
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, getIV());

        final byte[] encrypted = cipher.doFinal(text.getBytes("UTF-8"));  // Exception thrown here by doFinal()
        return Base64.encode(encrypted);
    }
    catch (final Exception e)
    {
        Logger.log("StringEncryptionException (" + e.getMessage() + ")", e);
    }

    return text;
}

public String decrypt(final String text)
{
    try
    {
        cipher.init(Cipher.DECRYPT_MODE, keyspec, getIV());

        final byte[] decoded = Base64.decode(text);
        final byte[] decrypted = cipher.doFinal(decoded);  // Exception thrown here by doFinal()

        return new String(decrypted);
    }
    catch (final Exception e)
    {
        Logger.log("StringDecryptionException (" + e.getMessage() + ")", e);
    }

    return text;
}
已解决

我创建了一个方法,将数组长度设置为16的倍数:

public static byte[] getBytesM16(final String text) throws UnsupportedEncodingException
{
    final byte[] bytes = text.getBytes("UTF-8");

    if (bytes.length % 16 == 0)
    {
        return bytes;
    }

    return Arrays.copyOf(bytes, bytes.length + (16 - (bytes.length % 16)));
}

public static byte[] getBytesM16(final byte[] bytes)
{
    if (bytes.length % 16 == 0)
    {
        return bytes;
    }

    return Arrays.copyOf(bytes, bytes.length + (16 - (bytes.length % 16)));
}

public String encrypt(final String text)
{
    try
    {
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, getIV());

        final byte[] encrypted = cipher.doFinal(StringHandler.getBytesM16(text));
        return Base64.getEncoder().encodeToString(encrypted);
    }
    catch (final Exception e)
    {
        Logger.log("StringEncryptionException (" + e.getMessage() + ")", e);
    }

    return text;
}

public String decrypt(final String text)
{
    try
    {
        cipher.init(Cipher.DECRYPT_MODE, keyspec, getIV());

        final byte[] decoded = Base64.getDecoder().decode(text);
        final byte[] decrypted = cipher.doFinal(StringHandler.getBytesM16(decoded));

        return new String(decrypted);
    }
    catch (final Exception e)
    {
        Logger.log("StringDecryptionException (" + e.getMessage() + ")", e);
    }

    return text;
}

在此之后,我遇到了一个问题,前16个字节没有正确解密,因为服务器在启动时创建了自己的随机
IVKey
。为了解决这个问题,我确保服务器和客户端
IVKey
是相同的,方法是在新客户端尝试连接时将密钥作为非加密数据包发送

正如错误所暗示的,您使用的密码的文本长度必须是16的倍数。text.getBytes(“UTF-8”)是多少字节?这个数字是16的倍数吗?文本是从套接字接收的字符串。如果我用0填充数组,使长度为16的倍数,则解密无法正常工作。无法工作,或包含那些0?无法工作,文本就像仍然加密一样。