【问题标题】:Python AES decryptionPython AES 解密
【发布时间】:2014-12-27 18:43:58
【问题描述】:

我想在 Python 中复制以下 Java 代码。

public class AESDecryption {

    protected SecretKeySpec getPublicKey() {

        try {
            byte[] key = "MuidKeibimbtjph9".getBytes("UTF-8");
            key = MessageDigest.getInstance("SHA-256").digest(key);
            key = Arrays.copyOf(key, 32);
            return new SecretKeySpec(key, "AES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String decrypt(byte[] data) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES/CBC/NoPadding");
            cipher.init(2, new SecretKeySpec(getPublicKey().getEncoded(), "AES"), new IvParameterSpec(new byte[cipher.getBlockSize()]));
            byte decryptedBytes[] = cipher.doFinal(data);
            return new String(Arrays.copyOf(decryptedBytes, decryptedBytes.length - decryptedBytes[-1 + decryptedBytes.length]));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void main(String[] args) {
        try {
            byte[] content = Files.readAllBytes(Paths.get("/tmp/dump.gzip"));
            AESDecryption aesDecryption = new AESDecryption();
            System.out.println(aesDecryption.decrypt(content));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

此代码来自客户端应用程序。我在生成加密内容的服务器端没有电源。对于这个问题,我更改了对称密钥以及如何检索内容(在此示例中来自文件,但实际上来自 https 响应)

我想使用 PyCrypto 库在 python 脚本中复制此功能。这就是我的初始代码的样子:

from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random

BLOCK_SIZE = 16
unpad = lambda s: s[0:-ord(s[-1])]

hash = SHA256.new()
hash.update('MuidKeibimbtjph9')
symmetric_key = hash.digest()
symmetric_key = symmetric_key[:32]

bytes_store = None
with open('/tmp/dump.gzip','r') as f:
    bytes_store = f.read()

rndfile = Random.new()
aes_decryptor = AES.new(symmetric_key, AES.MODE_CBC, rndfile.read(BLOCK_SIZE))
print unpad(aes_decryptor.decrypt(bytes_store))

在加密文件上运行 java 代码就可以了。结果看起来像:

{"code":200,"status":"ok","api_version":"0.0.0","data":[.....],"notifications":{}}

但是,python 复制会转储“半解密”文本。好吧。。

=c�q[A�$�dl�tus":"ok","api_version":"0.0.0","data":[.....],"notifications":{}}

我什么也做不了。查看Java代码很明显cipter块中没有填充,所以我认为可能服务器端的数据已经是cipher块大小的倍数。在 python 输出的末尾还有很多 ▯▯▯ 字符,但我很快通过取消填充解密数据来消除它们。尽管如此,我还是无法弄清楚我做错了什么,即有效载荷的第一部分被打乱了。 我对数据加密的了解非常基础,因此我向您寻求知识:)

【问题讨论】:

    标签: java python encryption cryptography aes


    【解决方案1】:

    问题是服务器代码使用了一个固定的 IV(这很糟糕),其中包含零,但是在您的 python 代码中,您将一个新的随机生成的 IV 传递给AES.new

    您可以将rndfile.read(BLOCK_SIZE) 替换为"\x00"*BLOCK_SIZE

    【讨论】:

    • 我同意 Python 代码使用随机 IV,而 Java 代码似乎没有,但如果这是问题所在,那么“半解密”文本难道不是完全乱码吗?
    • @unutbu:在 CBC 模式下,解密方向只会影响第一个块。 P_n = D(C_n) xor C_n-1。
    • 太棒了,谢谢。现在,在更仔细地阅读了关于 CBC 模式的维基百科文章之后 - 它确实说 IV 必须对 CBC 正确,否则第一个明文块将被损坏,但随后的明文块将是正确的。
    猜你喜欢
    • 2019-11-04
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2020-09-08
    • 2019-01-31
    • 1970-01-01
    相关资源
    最近更新 更多