Cifre y descifre mediante el algoritmo AES tanto en python como en android

Tengo Python y código de Android para el cifrado AES. Cuando cifro un texto en Android, se descifra en Python con éxito, pero no se puede descifrar en el lado de Android. ¿Alguien tiene una idea?

Código Python:

import base64 import hashlib from Crypto import Random from Crypto.Cipher import AES class AESCipher: def __init__(self, key): self.bs = 16 self.key = hashlib.sha256(key.encode()).digest() def encrypt(self, message): message = self._pad(message) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(message)).decode('utf-8') def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8') def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) @staticmethod def _unpad(s): return s[:-ord(s[len(s)-1:])] 

Código de Android:

 import java.io.IOException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Arrays; import android.annotation.SuppressLint; import android.location.Criteria; import android.util.Base64; import android.util.Log; @SuppressLint("NewApi") public class Crypt { private static final String tag = Crypt.class.getSimpleName(); private static final String characterEncoding = "UTF-8"; private static final String cipherTransformation = "AES/CBC/PKCS5Padding"; private static final String aesEncryptionAlgorithm = "AES"; private static final String key = "this is my key"; private static byte[] ivBytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; private static byte[] keyBytes; private static Crypt instance = null; Crypt() { SecureRandom random = new SecureRandom(); Crypt.ivBytes = new byte[16]; random.nextBytes(Crypt.ivBytes); } public static Crypt getInstance() { if(instance == null){ instance = new Crypt(); } return instance; } public String encrypt_string(final String plain) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException { return Base64.encodeToString(encrypt(plain.getBytes()), Base64.DEFAULT); } public String decrypt_string(final String plain) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, ClassNotFoundException, IOException { byte[] encryptedBytes = decrypt(Base64.decode(plain, 0)); return Base64.encodeToString( encryptedBytes, Base64.DEFAULT); } public byte[] encrypt( byte[] mes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException { keyBytes = key.getBytes("UTF-8"); Log.d(tag,"Long KEY: "+keyBytes.length); MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(keyBytes); keyBytes = md.digest(); Log.d(tag,"Long KEY: "+keyBytes.length); AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes); SecretKeySpec newKey = new SecretKeySpec(keyBytes, aesEncryptionAlgorithm); Cipher cipher = null; cipher = Cipher.getInstance(cipherTransformation); SecureRandom random = new SecureRandom(); Crypt.ivBytes = new byte[16]; random.nextBytes(Crypt.ivBytes); cipher.init(Cipher.ENCRYPT_MODE, newKey, random); // cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec); byte[] destination = new byte[ivBytes.length + mes.length]; System.arraycopy(ivBytes, 0, destination, 0, ivBytes.length); System.arraycopy(mes, 0, destination, ivBytes.length, mes.length); return cipher.doFinal(destination); } public byte[] decrypt( byte[] bytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException { keyBytes = key.getBytes("UTF-8"); Log.d(tag,"Long KEY: "+keyBytes.length); MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(keyBytes); keyBytes = md.digest(); Log.d(tag,"Long KEY: "+keyBytes.length); byte[] ivB = Arrays.copyOfRange(bytes,0,16); Log.d(tag, "IV: "+new String(ivB)); byte[] codB = Arrays.copyOfRange(bytes,16,bytes.length); AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivB); SecretKeySpec newKey = new SecretKeySpec(keyBytes, aesEncryptionAlgorithm); Cipher cipher = Cipher.getInstance(cipherTransformation); cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec); byte[] res = cipher.doFinal(codB); return res; } } 

Cuando ejecuté este código en Android:

 String str = "this is local test"; Log.i("myTag", "step1: " + str); String a = aesCrypt.encrypt_string(str); Log.i("myTag", "step2: " + a); String b = aesCrypt.decrypt_string(a); Log.i("myTag", "step3: " + b); 

Entonces obtuve esta respuesta:

 step1: this is local test step2: a0F8MhzkSpRlM+aM1MKzUdVCoXIE5y5hh4PRuwPfAhofKwLJjTUbBvmJzTsKJDqF step3: dGhpcyBpcyBsb2NhbCB0ZXN0 

¿Alguien tiene idea de por qué sucede?

Estás codificando la salida después del descifrado.

 public String decrypt_string(final String plain) throws ... { byte[] encryptedBytes = decrypt(Base64.decode(plain, 0)); return Base64.encodeToString( encryptedBytes, Base64.DEFAULT); // ^--------------------| this } 

Si solo cifra los datos imprimibles, puede eliminar de forma segura la llamada Base64.encodeToString del código anterior. Para devolver el tipo correcto, puedes hacer

 return new String(encryptedBytes);