Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.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
Android 如何处理;解密中的最后一个块未完成”;_Android_Encryption_Aes - Fatal编程技术网

Android 如何处理;解密中的最后一个块未完成”;

Android 如何处理;解密中的最后一个块未完成”;,android,encryption,aes,Android,Encryption,Aes,我有一个简单的类来尝试包装加密,以便在我的程序中的其他地方使用 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(Stri

我有一个简单的类来尝试包装加密,以便在我的程序中的其他地方使用

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“last block Completed in decryption”。以下是堆栈跟踪:

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) 位置:com.xxxxxx.android.StupidSimpleEncrypter.decrypt ln:49 解密中的最后一个块未完成 javax.crypto.IllegalBlockSizeException:解密中的最后一个块未完成 位于org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:711) 位于javax.crypto.Cipher.doFinal(Cipher.java:1090) 位于com.xxxxxx.android.StupidSimpleEncrypter.decrypt(StupidSimpleEncrypter.java:44) 位于com.xxxxxx.android.StupidSimpleEncrypter.decrypt(StupidSimpleEncrypter.java:34) 我已经做了大量的工作,我的头撞在我的桌子上,试图找出这个问题,但如果我有任何进展,它最终是一个不同的例外。通过搜索,我似乎也找不到什么


我错过了什么?非常感谢您的帮助。

我不知道这是否是
非法BlockSizeException
的问题,但您不应该将密钥编码为
字符串,尤其是在未指定字符编码的情况下。如果您想这样做,请使用Base-64之类的代码,它设计用于对任何“二进制”数据进行编码,而不是字符编码,它只将某些字节映射到字符

通常,密钥将包含与默认平台编码中的字符不对应的字节值。在这种情况下,当您创建
字符串时,字节将被转换为“替换字符”,U+FFFD(�), 正确的值将无法挽回地丢失

稍后尝试使用损坏的键的
字符串
表示将阻止恢复明文;这可能会导致
非法块大小异常
,但我怀疑更可能出现无效填充异常


另一种可能性是源平台和目标平台字符编码不同,并且“解码”密文导致字节太少。例如,源编码为UTF-8,将输入中的两个字节解释为单个字符,而目标编码为ISO-Latin-1,将该字符表示为单个字节。

您的
getKeySpec()
方法错误。您为加密和解密方向生成了一个新的随机密钥。您必须为这两个方向使用相同的密钥。您应该注意到,您没有使用该方法的
key
参数。

如果您使用的是字节数组,则必须使用相同的缓冲区大小。例如,有一个bytearray,其大小为1000。加密后,此大小变为2000。(这些不是实际值)。
如果您使用缓冲区读取所有加密文件,那么您应该选择buffersize为2000。我用这种方法解决了相同的问题。

对于我来说,当要解密的数据被破坏(缺少1个字符)时,我注意到了这个问题。这可能是由于通过WiFi传输数据造成的。

我当时正为此焦头烂额“坏基64”和“最后一个块未完成”错误…当然,这是不对称的。下面是我最终如何做的要点,希望这比我试图解释的内容更能增加讨论的内容:

public String crypto(SecretKey key, String inString, boolean decrypt){
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    byte[] inputByte = inString.getBytes("UTF-8");
    if (decrypt){
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String (cipher.doFinal(Base64.decode(inputByte, Base64.DEFAULT)));
    } else {
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return new String (Base64.encode(cipher.doFinal(inputByte), Base64.DEFAULT));
    }
}

这是问题的一部分,我可能会花一段时间才注意到。谢谢。这是我问题的根本原因,但在我的情况下,是有效负载而不是始终是标准字符串的密钥。我更改了它,因此在string encrypt方法中,返回的密文从字节数组编码到Base64,然后在decrypt方法中,密文字符串被Base64解码为字节数组。这意味着数据不再丢失,代码现在可以正常工作。加密字符串本身也是如此。它必须存储为字节[]。仅用于撕下的头发。