部分解密无意义

时间:2015-05-26 01:12:17

标签: java android encryption aes

我在android上聊天,在这里我使用下一个密钥生成,加密和解密消息的方法。问题是,当我在另一边发送例如“hola”的消息时,我得到“holgAAAAAAAAAAAAAAA”。你能帮忙解决这个问题吗?。

private byte[] K;
public void setK(){
    KeyGenerator KeyGen=KeyGenerator.getInstance("AES");
    KeyGen.init(128);
    SecretKey key=KeyGen.generateKey();
    K = key.getEncoded();
}
public String encrypt(byte[] input){
    try {
        IvParameterSpec iv = new IvParameterSpec(Base64.decode("Hola".getBytes(), Base64.DEFAULT));
        SecretKeySpec key = new SecretKeySpec(K, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
        ctLength += cipher.doFinal(cipherText, ctLength);
        return Base64.encodeToString(cipherText, Base64.DEFAULT);
    } catch (Exception e) {
        Log.e(JUAN, "failed to encrypt ", e);
    }
    return null;
}

public String decrypt(byte[] input){
    try {
        IvParameterSpec iv = new IvParameterSpec(Base64.decode("Hola".getBytes(), Base64.DEFAULT));
        SecretKeySpec key = new SecretKeySpec(K, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] plainText = new byte[cipher.getOutputSize(input.length)];
        int ctLength = cipher.update(input, 0, input.length, plainText, 0);
        ctLength += cipher.doFinal(plainText, ctLength);
        return Base64.encodeToString(plainText, Base64.DEFAULT);
    } catch (Exception e) {
        Log.e(JUAN, "failed to decrypt ", e);
    }
    return null;
}

修改 这是我的呼唤,例如加密“Hola”。

encrypt(Base64.decode("Hola".getBytes(), Base64.DEFAULT));
decrypt(Base64.decode(ciphertext, Base64.DEFAULT));

2 个答案:

答案 0 :(得分:3)

您的代码存在多个问题:

  1. 您的输入和输出类型的解密功能是相反的。如果您加密byte[],则在解密时应该获得一个。{1}}。如果您的密文是Base64 String,那么解密方法应该采用String而不是byte[]

    String encrypt(byte[] plaintext) {
        ...
        return Base64.encodeToString(cipher.doFinal(plaintext), Base64.DEFAULT);
    }
    
    byte[] encrypt(String ciphertext) {
        ...
        return cipher.doFinal(Base64.decode(ciphertext.getBytes("UTF-8"), Base64.DEFAULT));
    }
    
  2. 您将单个明文和密文传递到各自的方法中,然后使用cipher.update() cipher.doFinal()。这不是必需的。您应该在没有先前缓冲区的情况下使用单个cipher.doFinal()调用。加密示例:

    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] cipherText = cipher.doFinal(plaintext);
    
  3. 由于“Hola”应该是用户键入的内容,因此从Base 64中解码没有任何意义。并非所有人输入的字符串都是有效的64编码,以便它们可以被解码。您根本不应解码输入,而是直接将其传递到encrypt()函数。

  4. 使用String#getBytes()是不安全的,因为它使用系统的默认Charset。在接收系统上使用不同的默认字符集时,解密可能不会成功。您应该自己指定Charset并在解密后从byte[]获取字符串:

    String ciphertext = encrypt(plaintext.getBytes("UTF-8"));
    String recoveredPlaintext = new String(decrypt(ciphertext), "UTF-8");
    
  5. 您没有使用静电IV。

  6. 安全问题:

    1. 您正在使用ECB模式。不要这样做!它在语义上不安全。至少使用CBC模式和随机IV。 IV不必隐藏,因此您可以简单地将其添加到密文。
    2. 您没有验证密文。您的系统可能容易受到padding oracle攻击。您应该使用加密 - 然后 - MAC方法与强大的MAC(如HMAC-SHA256)或使用经过验证的操作模式(如GCM或EAX)。
    3. 例如this library使用Isaac Potoczny-Jones与Android兼容。它支持AES-CBC,并使用HMAC-SHA256进行随机IV和密文认证。

答案 1 :(得分:2)

假设您的input方法中的参数public String decrypt(byte[] input)成功通过调用者从密文解码Base64(因为您的加密返回Base64编码的密码字符串),您的代码就可以了。但是,在decrypt()方法中,您要按getOutputSize()方法创建byte数组plainText。这使plainText成为AES块大小(16)的倍数的数组。对于您的情况,plainText16 byte数组。因此,在解密并从密文中删除填充后,plainText包含带有一些零的解密文本,然后将这些零编码为AAA...As。 所以使用

return Base64.encodeToString(plainText, 0, ctLength, Base64.DEFAULT);

而不是

return Base64.encodeToString(plainText, Base64.DEFAULT);

注意:您使用的是ECB模式,因此您的IvParameterSpec无效。请改用CBC模式。

版本:您的通话不正常。试试这个

//Encryption side
String text = "hola, hi, anything u want";
byte[] plainText = text.getBytes("UTF-8");
String base64 = encrypt(plainText);

// Decryption side
byte[] cipherText = Base64.decode(base64, Base64.DEFAULT);
String plainEncodedText = decrypt(cipherText);
byte[] plainTextAsByte = Base64.decode(plainEncodedText, Base64.DEFAULT);
String plainTextAgain = new String(plainTextAsByte , "UTF-8");

现在打印plainTextAgain并希望这会有效!