有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android IllegalBlockSizeException:解密中最后一个块未完成

我正在使用这样的服务

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) 个答案

  1. # 1 楼答案

    return new String(encode);
    

    问题就在这里String不是二进制数据的容器。无法保证byte[]String之间的往返。您应该只传递原始的byte[],或者对其进行十六进制或base64编码

  2. # 2 楼答案

    问题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先生建议如下:

    In Java 8, there is an officially supported API for Base64 encoding and decoding

    Sample code using the "basic" encoding:

    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