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?无法工作,文本就像仍然加密一样。