iOS CryptoSwift AES加密到Python解密可以工作-但反过来不行

ovfsdjhp  于 2022-12-01  发布在  iOS
关注(0)|答案(1)|浏览(164)

我正在使用CryptoSwift 1.4.1、iOS 15.2、PyCryptodome 3.12.0和XCode 13.2.1对通过BLE发送到Raspberry Pi Linux设备的小字符串消息进行加密。当iOS对消息进行加密并将其发送到Raspberry Pi时,它就可以正常工作。Pi可以成功解密它。现在我想做相反的事情。在Pi上加密一条消息,然后让iOS应用程序读取并解密它。然而,这是行不通的,解密后的值不是我在Pi上加密的消息。
工作中的iOS加密:

func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
    let data = stringToEncrypt.data(using: String.Encoding.utf8)
    let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
    return encrypted.toHexString()
}

let ivString = "4198816658388141"
let keyString = "9004786896524916"

let key = [UInt8](keyString.utf8)
let iv = [UInt8](ivString.utf8)

let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)

在Python中工作Raspberry Pi解密:

KEY = b'9004786896524916'
IV = b'4198816658388141'
MODE = AES.MODE_CFB

def decrypt(key, iv, encrypted_text):
    logger.info(f"Encrypted: {encrypted_text}")
    aes = AES.new(key, MODE, iv, segment_size=128)
    encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
    decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
    logger.info(f"Decrypted: {decrypted_text}")
    return decrypted_text

我试着用下面的代码加密Pi上的一条消息:

KEY = b'9004786896524916'
IV = b'4198816658388141'
MODE = AES.MODE_CFB

def encrypt(key, decrypted_text):
    # Create cipher object and encrypt the data
    logger.info(f"Decrypted: {decrypted_text}")
    cipher = AES.new(key, MODE, segment_size=128)  # Create a AES cipher object with the key using the mode CBC
    #encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size))  # Pad the input data and then encrypt
    encrypted_text = cipher.encrypt(decrypted_text)  # Pad the input data and then encrypt
    logger.info(f"Encrypted: {encrypted_text}")
    return encrypted_text
    ...
    encrypt(KEY, returnString('utf-8'))

但是,iOS App无法使用此方法正确解密:

func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
    let data = stringToDecrypt.data(using: String.Encoding.utf8)
    let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt((data?.bytes)!)
    return decrypted.toHexString()
}
let ivString = "4198816658388141"
let keyString = "9004786896524916"

let key = [UInt8](keyString.utf8)
let iv = [UInt8](ivString.utf8)
var message = try! aesDecrypt(stringToDecrypt: charString, key: key, iv: iv)

当消息在Pi上加密时,如何在iOS应用程序中正常解密?

u5rb5r59

u5rb5r591#

encrypt()方法中不考虑IV。与在aesEncrypt()中一样,在创建AES对象时必须传递和使用IV。
此外,编码中存在缺陷:明文必须采用UTF8编码,密文必须采用十六进制编码:

from Crypto.Cipher import AES
import binascii

def encrypt(key, iv, plaintext):
    cipher = AES.new(key, MODE, iv, segment_size=128)  
    plaintext_bytes = plaintext.encode("utf-8")
    ciphertext = cipher.encrypt(plaintext_bytes)
    ciphertext_hex = binascii.b2a_hex(ciphertext)  
    return ciphertext_hex

这个函数是decrypt()的对应函数,也就是说,encrypt()可以用来产生一个密文,而这个密文可以用decrypt()(或aesDecrypt())来解密。
在iOS代码中有两个错误,都与编码有关:密文不能是UTF8编码,而是十六进制解码。解密数据不能是十六进制编码,而是UTF-8解码。
可能的解决方法是:

func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
    let data = Array<UInt8>(hex: stringToDecrypt)
    let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt(data)
    return String(bytes: decrypted, encoding: .utf8)!
}

这个函数是aesEncrypt()的对应函数,也就是说,aesDecrypt()可以用来解密用aesEncrypt()(或encrypt())生成的密文。
关于安全:静态IV是不安全的。相反,应该为每次加密随机生成IV。由于解密需要(非机密IV),因此它与密文一起传递(通常是串联的)。

相关问题