我有一个简单的类来尝试包装加密以便在我的程序的其他地方使用。
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
public final class StupidSimpleEncrypter
{
public static String encrypt(String key, String plaintext)
{
byte[] keyBytes = key.getBytes();
byte[] plaintextBytes = plaintext.getBytes();
byte[] ciphertextBytes = encrypt(keyBytes, plaintextBytes);
return new String(ciphertextBytes);
}
public static byte[] encrypt(byte[] key, byte[] plaintext)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec spec = new SecretKeySpec(getRawKey(key), "AES");
cipher.init(Cipher.ENCRYPT_MODE, spec);
return cipher.doFinal(plaintext);
}
catch(Exception e)
{
// some sort of problem, return null because we can't encrypt it.
Utility.writeError(e);
return null;
}
}
public static String decrypt(String key, String ciphertext)
{
byte[] keyBytes = key.getBytes();
byte[] ciphertextBytes = ciphertext.getBytes();
byte[] plaintextBytes = decrypt(keyBytes, ciphertextBytes);
return new String(plaintextBytes);
}
public static byte[] decrypt(byte[] key, byte[] ciphertext)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec spec = new SecretKeySpec(getRawKey(key), "AES");
cipher.init(Cipher.DECRYPT_MODE, spec);
return cipher.doFinal(ciphertext);
}
catch(Exception e)
{
// some sort of problem, return null because we can't encrypt it.
Utility.writeError(e);
return null;
}
}
private static byte[] getRawKey(byte[] key)
{
try
{
KeyGenerator gen = KeyGenerator.getInstance("AES");
SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
rand.setSeed(key);
gen.init(256, rand);
return gen.generateKey().getEncoded();
}
catch(Exception e)
{
return null;
}
}
}
它似乎正确地处理了加密,但在解密时却没有那么多,这会在突出显示的行抛出 javax.crypto.IllegalBlockSizeException“解密中的最后一个 block 不完整”。这是堆栈跟踪:
Location:com.xxxxxx.android.StupidSimpleEncrypter.decrypt ln:49 last block incomplete in decryption javax.crypto.IllegalBlockSizeException: last block incomplete in decryption at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:711) at javax.crypto.Cipher.doFinal(Cipher.java:1090) at com.xxxxxx.android.StupidSimpleEncrypter.decrypt(StupidSimpleEncrypter.java:44) at com.xxxxxx.android.StupidSimpleEncrypter.decrypt(StupidSimpleEncrypter.java:34)
我已经用我的头撞了很多次 table 来尝试解决这个问题,但如果我有任何进展,它最终会成为一个不同的异常(exception)。我似乎也无法通过搜索找到很多东西。
我错过了什么?如果有任何帮助,我将不胜感激。
最佳答案
我不知道这是否是 IllegalBlockSizeException
的问题,但您不应将 key 编码为 String
,尤其是在未指定字符编码的情况下。如果要执行此操作,请使用 Base-64 之类的东西,它旨在对任何“二进制”数据进行编码,而不是仅将某些字节映射到字符的字符编码。
一般而言, key 将包含不对应于默认平台编码中的字符的字节值。在这种情况下,当您创建 String
时,字节将被转换为“替换字符”,U+FFFD (�),并且正确的值将无法挽回地丢失。
稍后尝试使用 key 的损坏 String
表示将阻止恢复明文;它可能会导致 IllegalBlockSizeException
,但我怀疑更有可能出现无效填充异常。
另一种可能是源平台和目标平台字符编码不同,“解码”密文导致字节太少。例如,源编码是 UTF-8,将输入中的两个字节解释为单个字符,而目标编码是 ISO-Latin-1,它将那个字符表示为单个字节。
关于android - 如何处理 "last block incomplete in decryption",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4598873/