密码函数:EVP_DecryptFinal_ex:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH

时间:2016-12-08 19:22:49

标签: android encryption aes

我试图在Android应用程序中实现AES。服务器是PHP服务器。

这是AES代码:

public class AES{

private String SecretKey = "89432hjfsd891787";
private String iv = "fedcba9876543210";
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;

public AES()
{
    ivspec = new IvParameterSpec(iv.getBytes());
    keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
    try {
        cipher = Cipher.getInstance("AES/CBC/NoPadding");
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public byte[] encrypt(String text) throws Exception
{
    if(text == null || text.length() == 0)
        throw new Exception("Empty string");

    byte[] encrypted = null;

    try {
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

        encrypted = cipher.doFinal(padString(text).getBytes());
    } catch (Exception e)
    {
        throw new Exception("[encrypt] " + e.getMessage());
    }

    return encrypted;
}

public byte[] decrypt(String code) throws Exception
{
    if(code == null || code.length() == 0)
        throw new Exception("Empty string");

    byte[] decrypted = null;

    try {
        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

        decrypted = cipher.doFinal(hexToBytes(code));
    } catch (Exception e)
    {
        throw new Exception("[decrypt] " + e.getMessage());
    }
    return decrypted;
}



public static String bytesToHex(byte[] data)
{
    if (data==null)
    {
        return null;
    }
    int len = data.length;
    String str = "";
    for (int i=0; i<len; i++) {
        if ((data[i]&0xFF)<16)
            str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
        else
            str = str + java.lang.Integer.toHexString(data[i]&0xFF);
    }
    return str;
}


public static byte[] hexToBytes(String str) {
    if (str==null) {
        return null;
    } else if (str.length() < 2) {
        return null;
    } else {
        int len = str.length() / 2;
        byte[] buffer = new byte[len];
        for (int i=0; i<len; i++) {
            buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
        }
        return buffer;
    }
}

private static String padString(String source)
{
    char paddingChar = ' ';
    int size = 16;
    int x = source.length() % size;
    int padLength = size - x;
    for (int i = 0; i < padLength; i++) {
        source += paddingChar;
    }
    return source;
}
}

解密传入字符串时出错:Cipher functions:EVP_DecryptFinal_ex:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH

我该怎么做?

1 个答案:

答案 0 :(得分:0)

用空格手动填充明文的String表示不是一个好的填充机制。相反,您应该使用AES/CBC/PKCS5Padding来处理PKCS#5 /#7中规定的填充。

您还应该:

  1. 为每个加密操作生成唯一的IV,而不是为所有消息重复使用相同的值
  2. 使用经过身份验证的操作模式(GCMHMAC/SHA-256 MAC over cipher text等。)
  3. 将密钥存储为原始字节的十六进制表示,而不是ASCII / UTF-8字符串编码(未在代码中指定)
  4. 在序列化/传输之前,将密码文本编码为Base64或Hex。编码错误可能导致解密期间的填充异常。