【问题标题】:How to decrypt the encrypted string coming from python?如何解密来自python的加密字符串?
【发布时间】:2017-11-09 23:06:31
【问题描述】:

我从 python 得到一个加密的 base64 字符串。格式为 AES 256 CBC。但是当我尝试使用 iOS Swift 解密时,它会将解密后的字符串返回为 nil。

# coding=utf-8
import base64
from random import choice
from string import letters

try:
    from Crypto import Random
    from Crypto.Cipher import AES
except ImportError:
    import crypto
    import sys

    sys.modules['Crypto'] = crypto
    from crypto.Cipher import AES
    from crypto import Random


class AESCipher(object):
    def __init__(self, key):
        self.bs = 32
        self.key = key

    def encrypt(self, raw):
        _raw = raw
        raw = self._pad(raw)

        print raw, ';'
        print _raw, ';'

        iv = "".join([choice(letters[:26]) for i in xrange(16)])
        print " iv :", iv
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw))

    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):
        a = (self.bs - len(s) % self.bs)
        b = chr(self.bs - len(s) % self.bs)
        return s + a * b

    @staticmethod
    def _unpad(s):
        return s[:-ord(s[len(s) - 1:])]
def encrypt(k, t):
    o = AESCipher(k)
    return o.encrypt(t)


def decrypt(k, t):
    o = AESCipher(k)
    return o.decrypt(t)


def main():
    k = "qwertyuiopasdfghjklzxcvbnmqwerty"
    s1 = "Hello World!"

    d2 = encrypt(k, s1)

    print " Password :", k
    print "Encrypted :", d2
    print "    Plain :", decrypt(k, d2)

if __name__ == '__main__':
    main()

iOS

这里我使用 AES256CBC Lib https://github.com/SwiftyBeaver/AES256CBC

let decrypted = AES256CBC.decryptString("Ymdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbiXBBeO", password: "qwertyuiopasdfghjklzxcvbnmqwerty")

        print("decrypted: \(String(describing: decrypted))") // here I get nil

当 python 运行我得到这个日志

iv : bgjsvjvfuqwldmle
 Password : qwertyuiopasdfghjklzxcvbnmqwerty
Encrypted : Ymdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbiXBBeO
    Plain : Hello World!

我不知道为什么 AES 中的 python 和 iOS 不一样。任何人解决这个问题,请把答案放在下面。提前致谢。

【问题讨论】:

    标签: ios swift python-2.7 aes pycrypto


    【解决方案1】:

    我认为你需要先解码你的 base64 字符串。 也许这会起作用(只是用谷歌搜索了一下,我不是 iOS 开发人员,所以很抱歉最终出现错误)

    let decodedData = NSData("Ymdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbiXBBeO": base64String, options:NSDataBase64DecodingOptions.fromRaw(0)!)
    let decodedString = NSString(data: decodedData, encoding: NSUTF8StringEncoding)
    let decrypted = AES256CBC.decryptString(decodedString, password: "qwertyuiopasdfghjklzxcvbnmqwerty")
            print("decrypted: \(String(describing: decrypted))")
    

    documentation中也有说明

    【讨论】:

    • 其实我的代码和你的代码有什么区别?
    • 密文:bgjsvjvfuqwldmleYmdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbiXBBeO 是初始化向量 (bgjsvjvfuqwldmle) 和消息的加密块 (Ymdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbiXBBeO) 的串联。
    • 没关系,但我不知道如何利用你的想法,因为我是 iOS 的初学者。你能帮我测试一下吗?
    • 对不起,我错了!我没有看到您已经在base64.b64encode(iv + cipher.encrypt(raw)) 将 IV 添加到剩余的加密消息中。我正在寻找真正的问题。
    • Python 开发者。阅读 AES256CBC 的文档,我发现它会查找字符串的前 16 个字符来提取 IV。 Base64 编码将明文的每 3 个字节扩展为 4 个字节,因此,如果您有 64 个字节(Ymdqc3ZqdmZ1cXdsZG1sZenhgr4Xt0+ceARYRh1n40QkNDV/dyKbQjYLcbi‌​XBBeO),则解码后的明文长度为 48 个字节(IV 为 16 个字节,加密块为 32 个字节)。我认为您需要先将字符串从 base64 解码为 raw。
    最近更新 更多