AES / CBC / PKCS5Padding加密在android和java中完成。加密的文本不匹配

时间:2018-02-14 10:25:00

标签: java android encryption aes password-encryption

我想在android应用程序中加密密码。所以我选择了AES / CBC / PKCS5Padding加密。下面是我在android中进行加密的代码。我在php中也需要相同的加密。所以我也有PHP的代码。但在android中完成的加密数据与用php完成的加密数据请帮助我是加密的新手。

    public class AESCrypt {
    private final String characterEncoding = "UTF-8";
    private final String cipherTransformation = "AES/CBC/PKCS5Padding";
    private final String aesEncryptionAlgorithm = "AES";

    public  byte[] bytedecrypt(byte[] cipherText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    {
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
        cipherText = cipher.doFinal(cipherText);
        return cipherText;
    }

    public byte[] byteencrypt(byte[] plainText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
    {
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        plainText = cipher.doFinal(plainText);
        return plainText;
    }

    private byte[] getKeyBytes(String key) throws UnsupportedEncodingException{
        byte[] keyBytes= new byte[16];
        byte[] parameterKeyBytes= key.getBytes(characterEncoding);
        System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
        return keyBytes;
    }


    public String encrypt(String plainText) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{
        byte[] plainTextbytes = plainText.getBytes(characterEncoding);
        byte[] keyBytes = getKeyBytes("9vYJNrqiHifDWGw6X9UHU5h7kBtb8TNB");
        return Base64.encodeToString(byteencrypt(plainTextbytes,keyBytes, keyBytes), Base64.DEFAULT);
    }


    public String decrypt(String encryptedText) throws KeyException, GeneralSecurityException, GeneralSecurityException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException{
        byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT);
        byte[] keyBytes = getKeyBytes("9vYJNrqiHifDWGw6X9UHU5h7kBtb8TNB");
        return new String(bytedecrypt(cipheredBytes, keyBytes, keyBytes), characterEncoding);
    }

}

以下是相同加密的php代码

$data_to_encrypt = $out;
$key128 = "9vYJNrqiHifDWGw6X9UHU5h7kBtb8TNB";
$iv = "0000000000000000";

$cc = $data_to_encrypt;
$key = $key128;
$iv =  $iv;
$length = strlen($cc);

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','cbc',$iv);

mcrypt_generic_init($cipher, $key, $iv);
$encrypted = base64_encode(mcrypt_generic($cipher,$cc));
mcrypt_generic_deinit($cipher);

mcrypt_generic_init($cipher, $key, $iv);
$decrypted = mdecrypt_generic($cipher,base64_decode($encrypted));
mcrypt_generic_deinit($cipher);

echo "encrypted: " . $encrypted;
echo "";
echo "length:".strlen($encrypted);
echo "<br />";
echo "decrypted: " . substr($decrypted, 0, $length);

2 个答案:

答案 0 :(得分:1)

确保使用相同的initialVector。

在PHP中,您使用$ iv =“0000000000000000”;

但是在java而不是initalVector中,你将keyBytes作为第三个参数传递。

byteencrypt(plainTextbytes,keyBytes, keyBytes)

答案 1 :(得分:0)

当您尝试在Android上使用zero padding解码信息时,

mcrypt会使用PKCS5Cipher不支持零填充。 从PHP 7.1.0开始,不推荐mcrypt使用OpenSSL。

另外,您的AES密钥不应在您的客户端上进行硬编码,因为黑客可以轻松访问它。使用Android KeyStore

其次,初始化向量(IV)必须是随机的。 加密后,将其附加到加密邮件的前面,然后在客户端上检索它。没有必要加密它,加密后它可以是公共的。

考虑使用GCM模式,因为它支持身份验证,而CBC默认不支持。