iOS中的CommonCrypto与openssl命令行产生不同的结果

时间:2019-06-26 23:57:13

标签: swift encryption openssl aes commoncrypto

我在我的应用程序中使用CommonCrypto来解密一些使用openssl加密的数据。为了测试加密,我尝试对一些示例数据进行加密,这让我感到惊讶,我的加密输出(即es 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 =“

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

AD

1 个答案:

答案 0 :(得分:2)

第一个问题是您没有使用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位。