【问题标题】:CommonCrypto in iOS producing different results to openssl command lineiOS中的CommonCrypto对openssl命令行产生不同的结果
【发布时间】:2019-11-08 23:02:23
【问题描述】:

我在我的应用程序中使用 CommonCrypto 来解密一些使用 openssl 加密的数据。为了测试加密,我尝试加密一些示例数据,令人惊讶的是我的加密输出(即 aes ecb)与使用 openssl 命令生成的不同。

我也尝试过 CryptoSwift 等其他框架,但结果是一样的。

这是我用来加密的代码:

class AESEncryptor {

    static func encrypt(text: String, key: String) -> String? {

        guard let encryptingData = text.data(using: .utf8), let keyData = key.data(using: .utf8) else {
            return nil
        }

        var outLength = Int(0)
        var outBytes = [UInt8](repeating: 0, count: encryptingData.count + kCCBlockSizeAES128)
        var status: CCCryptorStatus = CCCryptorStatus(kCCSuccess)
        encryptingData.withUnsafeBytes { (encryptingBytes: UnsafePointer<UInt8>!) -> () in
            keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>!) -> () in
                status = CCCrypt(CCOperation(kCCEncrypt),
                                 CCAlgorithm(kCCAlgorithmAES),            // algorithm
                    CCOptions(kCCOptionECBMode | kCCOptionPKCS7Padding),           // options
                    keyBytes,                                   // key
                    keyData.count,                                  // keylength
                    nil, //ivBytes,                                    // iv
                    encryptingBytes,                             // dataIn
                    encryptingData.count,                                // dataInLength
                    &outBytes,                                  // dataOut
                    outBytes.count,                             // dataOutAvailable
                    &outLength)                                 // dataOutMoved
            }
        }
        guard status == kCCSuccess else {
            return nil
        }

        let encryptedData =  Data(bytes: UnsafePointer<UInt8>(outBytes), count: outLength)
        return encryptedData.base64EncodedString()

    }
}

调用上述函数:

let key = "4f0fbad47141ef9616ce4d71b459eea9"
let plain = "ThisIsASuperSecurePassword"
let digest = AESEncryptor.encrypt(text: plain, key: key)

摘要是“4ebhUO+Rma34MR4iBTT04AS6rXX+Jy2U97rwC2HGmz0="

同时,openssl 命令行,输入相同:

echo -n "ThisIsASuperSecurePassword" | openssl enc -e -aes-128-ecb -K "3466306662616434373134316566393631366365346437316234353965656139" -a

(“3466306662616434373134316566393631366365346437316234353965656139”是“4f0fbad47141ef9616ce4d71b459eea9”的十六进制字符串)

给我“zPO4jNrMbbZp4WXNPgkX1RuBIpNXZqe0XNqNMFPTt/Q="

所以,我的问题是:为什么它们不一样?如何获得相同的输出?

广告

【问题讨论】:

    标签: swift encryption openssl aes commoncrypto


    【解决方案1】:

    第一个问题是您没有使用 AES-128-EBC 进行编码,而实际上是使用 AES-256-EBC 进行了编码。是因为您的密钥长度是 256 位,而不是 128 位。

    因此,如果我们使用具有正确密钥长度的 openssl 进行编码,我会得到:

    (请注意,我使用的是 powershell,出于某种原因,通过管道将文本传递到命令会添加 CRLF,因此我通过文件将其添加到它)

    "ThisIsASuperSecurePassword" | Set-Content -NoNewLine plaintext.txt
    openssl enc -e -aes-256-ecb -K 3466306662616434373134316566393631366365346437316234353965656139 -a -in plaintext.txt
    

    我明白了:

    4ebhUO+Rma34MR4iBTT04AS6rXX+Jy2U97rwC2HGmz0=

    这和你得到的一样。

    解密输出再次产生明文:

    "4ebhUO+Rma34MR4iBTT04AS6rXX+Jy2U97rwC2HGmz0=" | openssl enc -d -aes-256-ecb -K 3466306662616434373134316566393631366365346437316234353965656139 -a -p
    

    产生输出:

    ThisIsASuperSecurePassword

    如果您确实需要 AES-128,则需要将密钥长度减少到 128 位。

    【讨论】:

    • 一样;您似乎正在使用 powershell,其中“abc”输出 abc 后跟 CRLF
    • 不确定您所说的 CRLF 评论是什么意思。如果我将解码结果输出到一个文件,这两个文件是相同的,我在输出文件中看不到 CRLF。
    • 我刚刚仔细检查了我的结果,你是对的。我的末尾有一个 CRLF,这是两者之间的区别。
    • 感谢@dave_thompson_085 的输入。我已经更新了我的答案以反映相同的输出。如果最后没有换行符,我无法弄清楚如何使用 powershell 管道:(
    猜你喜欢
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 2017-06-24
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多