首页 > 解决方案 > Swift 加密和 NodeJS 解密产生不一致的结果

问题描述

我对 Crypto 不是很熟悉,但我确实确保 iv 长度缓冲区返回正确的长度,使用的加密密钥是相同的。

NodeJS 的预期结果是 16 个随机字节的预设 IV 长度 + encryptedText 生成的aes-256-cbc组合成长度为 64 的十六进制字符串。

在 Node 中测试加密并对其进行解密会产生预期的结果。但是,当 iOS 发送有效负载时,它会解密为未知字符串。

但是,当 iOS 加密并发送数据时。我无法解密它以获得预期的字符串。

对于 iOS,我正在使用 CommonCryto 库

import CommonCrypto

struct AES {

    private let key: String

    init?(key: String) {
        guard key.count == kCCKeySizeAES256 else {
            debugPrint("Error: Failed to set a key.")
            return nil
        }
        self.key = key
    }

    func encrypt(string: String) -> Data? {
        return crypt(data: string.data(using: .utf8), operation: kCCEncrypt)
    }

    private func crypt(data: Data?, operation: Int) -> Data? {
        guard let data = data else {
            return nil
        }

        var ivBytes: [UInt8]
        var inBytes: [UInt8]
        var outLength: Int

        if operation == kCCEncrypt {
            ivBytes = [UInt8](repeating: 0, count: kCCBlockSizeAES128)
            guard kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
                fatalError("IV creation failed!")
            }
            inBytes = Array(data)
            outLength = data.count + kCCBlockSizeAES128
        } else {
            ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128))
            inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128))
            outLength = inBytes.count
        }

        var outBytes = [UInt8](repeating: 0, count: outLength)
        var bytesMutated = 0

        guard kCCSuccess == CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), Array(key), key.count, &ivBytes, &inBytes, inBytes.count, &outBytes, outLength, &bytesMutated) else {
            fatalError("Cryptography operation \(operation) failed")
        }

        var outData = Data(bytes: &outBytes, count: bytesMutated)

        if operation == kCCEncrypt {
            ivBytes.append(contentsOf: Array(outData))
            outData = Data(ivBytes)
        }
        return outData
    }
}

以及我如何在 NodeJS 中解密:

const decrypt = functions.https.onCall(async (data, context) => {
    const uid = context && context.auth && context.auth.uid;
    if(!uid) {
        return sendErrorResponse({
            payload: 'Unauthorised',
            statusCode: 401,
        });
    }
    const { password } = data;

    const MID = password.length / 2;
    const textPart = [password.slice(0,MID),password.slice(MID)];
    const iv = Buffer.from(textPart.shift(),'hex');
    const encryptedText = Buffer.from(textPart.join(),'hex');
    const decipher = crypto.createDecipheriv('aes-256-cbc', encryptionKey, iv).setAutoPadding(false);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
});

标签: node.jsswiftencryption

解决方案


寻找跨板式AES 加密


推荐阅读