Android - IllegalBlockSizeException:解密时最后一个块不完整

时间:2016-08-31 05:46:24

标签: java android encryption

我正在使用像这样的服务

String value = "test@example.com"
String encrypedValue = EncrypterService get().encrypt(value.getBytes())
String decryptedValue = EncrypterService get().decrypt(encrypedValue .getBytes())



public final class EncrypterService {

    private static Key keySpec;
    private static Cipher encryptCipher;
    private static Cipher decryptCipher;
    private static String passphrase = "IU1ZaypiTiVYc3AtPXMxNWNMYGUmVUF8YUAtUSMuKVI=";
    private static final String KEY_ALGORIGHT = "HmacSHA256";
    private static final String CIPHER_ALGORITHM = "AES";
    private static final String MD5_ALGORITH = "MD5";
    private static EncrypterService service;

    private EncrypterService(){

    }

    private static synchronized void initialize() {
        if (service == null) {
            service = new EncrypterService();
            service.init();
        }
    }

    public static EncrypterService get() {
        initialize();
        return service;
    }


    public String encrypt (byte[] plaintext){
        //returns byte array encrypted with key
        try {

            byte[] encode = encryptCipher.doFinal(plaintext);
            return new String(encode);
        }catch(Exception e){
            throw new RuntimeException("Unable to decrypt data" + e);
        }
    }

    public  String decrypt (byte[] ciphertext) {
        //returns byte array decrypted with key
        try {
            byte[] decode = decryptCipher.doFinal(ciphertext);
            return new String(decode);
        }catch(Exception e){
            throw new RuntimeException("Unable to decrypt data" + e);
        }
    }

    private static void init(){
       try {
           if (encryptCipher == null && decryptCipher == null) {
               byte[] bytesOfMessage = Base64.decode(passphrase, Base64.NO_WRAP);
               MessageDigest md = MessageDigest.getInstance(MD5_ALGORITH);
               byte[] thedigest = md.digest(bytesOfMessage);
               keySpec = new SecretKeySpec(thedigest, KEY_ALGORIGHT);
               encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
               encryptCipher.init(Cipher.ENCRYPT_MODE, keySpec);
               decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
               decryptCipher.init(Cipher.DECRYPT_MODE, keySpec);
           }
       }catch(Exception e){
           throw new RuntimeException("Unable to initialise encryption", e);
       }
    }

}

栈跟踪

java.lang.RuntimeException·Unable to decrypt datajavax.crypto.IllegalBlockSizeException: last block incomplete in decryption
Full TraceRaw
EncrypterService .java:59 EncrypterService .decrypt

2 个答案:

答案 0 :(得分:0)

String

问题出在这里。 byte[]不是二进制数据的容器。 Stringbyte[]之间的往返行程无法保证。您应该只是传递原始groupByKey或其他hex-或base64-编码。

答案 1 :(得分:0)

问题#1:

java.security.MessageDigest将提供MD5摘要的实例。

为此,您需要导入以下内容

import java.security.*;

问题#2:

对于encrypedValue,您使用的是value.getBytes()和 对于decryptedValue,您使用的是encrypedValue .getBytes()

以下是使用getBytes()的一些限制。它与平台无关。 因此,您应该使用getBytes("UTF-8")代替getBytes()

byte[] bytesOfMessage = yourString.getBytes("UTF-8");

MessageDigest md = MessageDigest.getInstance(MD5_ALGORITH);
byte[] thedigest = md.digest(bytesOfMessage);

资源链接:How can I generate an MD5 hash?

问题#3:编码和解码

先生。 Andrea建议如下:

  

在Java 8中,有一个官方支持的Base64编码API   和解码

     

使用“基本”编码的示例代码:

import java.util.Base64;

byte[] bytes = "Hello, World!".getBytes("UTF-8");
String encoded = Base64.getEncoder().encodeToString(bytes);
byte[] decoded = Base64.getDecoder().decode(encoded);

资源链接:Decode Base64 data in Java