java - python 和 android 之间的 AES 加密互操作

标签 java android python encryption aes

我在 python (Django) 服务器上获取了此代码,用于加密发送给 Java 客户端 (Android) 的消息。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
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, raw):
        raw = self._pad(raw)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        cTxt = (iv + cipher.encrypt(raw))
        return base64.b64encode(cTxt)

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        dPadded = cipher.decrypt(enc[AES.block_size:])
        return self._unpad(dPadded).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:])]

我用的是这种方式:

    phrase = "Prueba de Encryptado"
    key = "e8ffc7e56311679f12b6fc91aa77a5eb"

    cryp = AESCipher(key)
    eTxt = cryp.encrypt(phrase)
    dTxt = cryp.decrypt(eTxt)

在我的 Java-Android 客户端上;我尝试用此类解密:

 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 = "e8ffc7e56311679f12b6fc91aa77a5eb";
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;


private Crypt(){}



public static Crypt getInstance() {
    if(instance == null){
        instance = new Crypt();
    }

    return instance;
}



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, "AES");
    Cipher cipher = null;
    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    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, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
    return  cipher.doFinal(codB);

}

}

但是我无法像在 python 代码中那样解密;我不知道为什么,但每次我尝试;这些是我的异常(exception)情况:

javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
at com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:430)
at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:466)
at javax.crypto.Cipher.doFinal(Cipher.java:1340)
at net.kaimanden.testcrypt.Crypt.doDecryption(Crypt.java:75)

最佳答案

您忘记在 Java 代码中导出 key 。在 python 代码中,您使用密码 (key) 通过 SHA-256 派生实际的 256 位 key 。

另一方面,在 Java 中,您直接使用 key = "HolaQueTal" ,它甚至太短而无法用作正确的 key ,甚至与您的 python 示例中的 key 不同。 MessageDigest类支持 SHA-256。

关于java - python 和 android 之间的 AES 加密互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28171353/

相关文章:

java - 写入文件不会写入

java - 如何从数组的 ArrayList 转换为数组的数组

java - JDI、Java 字节代码检测和 Java 代理(JWDP、JVMTI)

java - JDBC setMaxRows 数据库使用

android - 在 Android 上使用 react-native 的简单登录屏幕

python - 如何让 android 模拟器与本地主机对话?

python - 如何显示 1 列的值相对于 Python 中 Excel 工作表中某些其他列中存在的特定值?

Python:list() 函数搞乱了 map()

python - 返回具有特定值 "1"的pandas数据框

java - 处理 Web 服务中的空指针异常