Java Cipher IllegalBlockSizeException

时间:2018-04-16 09:40:45

标签: java exception encryption client-server

我刚刚拥有了#34;伟大的"想法加密来自我的客户端和服务器的发送/接收数据。但现在每次拨打IllegalBlockSizeException (Input length must be multiple of 16 when decrypting with padded cipher)时,我都会收到cipher.doFinal()

我的代码:

我创建了一个名为SecurityHandler的单例类,SecretKeySpec keyspecCipher cipherString 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);
    }
}

获取AlgorithmParameterSpec的方法:

public AlgorithmParameterSpec getIV()
{
    final byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    return new IvParameterSpec(iv);
}

我的enrypt / decrypt方法:

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是相同的,通过将密钥作为非加密数据包发送,就在新客户端尝试连接时。

0 个答案:

没有答案