iOS 中的 CommonCrypto 对 openssl 命令行产生不同的结果
CommonCrypto in iOS producing different results to openssl command line
我在我的应用程序中使用 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="
所以,我的问题是:为什么它们不一样?我怎样才能得到相同的输出?
AD
第一个问题是你没有用 AES-128-EBC 编码,你实际上用 AES-256-EBC 编码。 With 是因为你的密钥长度是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 位。
我在我的应用程序中使用 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="
所以,我的问题是:为什么它们不一样?我怎样才能得到相同的输出?
AD
第一个问题是你没有用 AES-128-EBC 编码,你实际上用 AES-256-EBC 编码。 With 是因为你的密钥长度是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 位。