Android 不返回原始文本的简单AES加密和解密

Android 不返回原始文本的简单AES加密和解密,android,security,encryption,aes,Android,Security,Encryption,Aes,我使用以下简单的加密和解密函数只是为了在使用更复杂的安全特性(如填充和哈希)之前看看它是否有效。由于某些原因,返回的明文与原始消息不相似。代码如下: public static byte[] encrypt(SecretKey secret, byte[] buffer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, Ille

我使用以下简单的加密和解密函数只是为了在使用更复杂的安全特性(如填充和哈希)之前看看它是否有效。由于某些原因,返回的明文与原始消息不相似。代码如下:

public static byte[] encrypt(SecretKey secret, byte[] buffer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException
{
    /* Encrypt the message. */
    cipher = Cipher.getInstance("AES/CTR/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secret);
    byte[] ciphertext = cipher.doFinal(buffer);

    return ciphertext;
}

public static byte[] decrypt(SecretKey secret, byte[] buffer) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException
{
    /* Decrypt the message. - use cipher instance created at encrypt */
    cipher.init(Cipher.DECRYPT_MODE, secret);
    byte[] clear = cipher.doFinal(buffer);

    return clear;
}
以及呼叫代码:

    SecretKey secret1 = null;
    byte[] ciphertext = null;
    byte[] message = "Hello, World!".getBytes();
    byte[] clear = null;

    try {
// aSecret is a shared secret generated with ECDH
        secret1 = Crypto.createAESKey(aSecret);
        ciphertext = Crypto.encrypt(secret1, message);
        clear = Crypto.decrypt(secret1, ciphertext);

        String s = new  String(clear);//clear.toString();

        keyAText.setText(new String(message));
        keyBText.setText(s);

        return;
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidParameterSpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

这几乎可以肯定是因为在初始化过程中没有使用
IvParameterSpec
提供IV。在JavaSE上,您的代码甚至不会运行,因为CTR需要设置这个参数。但是,其他提供商可能会以不同的方式实施,例如,他们可能会提供随机IV

当然,如果在加密和解密期间使用不同的随机IV,则解密结果可能与明文不匹配

尝试以下修改的方法:

public static byte[] encrypt(SecretKey secret, byte[] buffer) throws GeneralSecurityException
{
    /* Encrypt the message. */
    Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

    SecureRandom rng = new SecureRandom();
    byte[] ivData = new byte[cipher.getBlockSize()];
    rng.nextBytes(ivData);

    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivData));
    byte[] ciphertext = cipher.doFinal(buffer);

    return Arrays.concatenate(ivData, ciphertext);
}

public static byte[] decrypt(SecretKey secret, byte[] buffer) throws GeneralSecurityException
{
    /* Decrypt the message. - use cipher instance created at encrypt */
    Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

    int n = cipher.getBlockSize();
    byte[] ivData = Arrays.copyOf(buffer, n);

    cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivData));
    byte[] clear = cipher.doFinal(buffer, n, buffer.length - n);

    return clear;
}

在字节数组上调用
toString
,并不是按照您的想法进行的。看看
字符串的构造函数。看看这个Henry-即使字符串没有正确构建,我也希望两个字节数组生成相同的“字符串”。@Simon no,因为它不是同一个实例。默认的
toString
方法将对象的哈希代码显示为字符串的一部分。是否确实要使用AES计数器模式?如果是,则必须使用相同的IV值进行加密和解密。请注意,我没有在方法中添加任何参数检查,我将避免提供安全建议(例如使用GCM模式)。