gpt4 book ai didi

aes - Swift 5 + kCCDecrypt (CommonCrypto) : Failing to decrypt

转载 作者:行者123 更新时间:2023-12-05 00:58:56 25 4
gpt4 key购买 nike

尝试在 Swift 5 中编写我自己的加密/解密函数,基于大量其他类似的问题——结果惨遭失败。

我正在使用 CommonCrypto + CCCrypt 来加密/解密(AES,256 key ,随机 iv)。

我更喜欢 NSData.bytes 而不是 withUnsafeBytes(在 Swift 5 中只是 too confusing)。

我的 encrypt 函数是这样的:

func encrypt(_ string: String) throws -> Data {
guard let dataToEncrypt: Data = string.data(using: .utf8) else {
throw AESError.stringToDataFailed
}

// Seems like the easiest way to avoid the `withUnsafeBytes` mess is to use NSData.bytes.
let dataToEncryptNSData = NSData(data: dataToEncrypt)

let bufferSize: Int = ivSize + dataToEncryptNSData.length + kCCBlockSizeAES128
let buffer = UnsafeMutablePointer<NSData>.allocate(capacity: bufferSize)
defer { buffer.deallocate() }

let status: Int32 = SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
buffer
)
guard status == 0 else {
throw AESError.generateRandomIVFailed
}

var numberBytesEncrypted: Int = 0

let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCEncrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES), // alg: CCAlgorithm
options, // options: CCOptions
key.bytes, // key: the "password"
key.length, // keyLength: the "password" size
buffer, // iv: Initialization Vector
dataToEncryptNSData.bytes, // dataIn: Data to encrypt bytes
dataToEncryptNSData.length, // dataInLength: Data to encrypt size
buffer + kCCBlockSizeAES128, // dataOut: encrypted Data buffer
bufferSize, // dataOutAvailable: encrypted Data buffer size
&numberBytesEncrypted // dataOutMoved: the number of bytes written
)

guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.encryptDataFailed
}

return Data(bytes: buffer, count: numberBytesEncrypted + ivSize)
}

解密函数:

func decrypt(_ data: Data) throws -> String {

// Seems like the easiest way to avoid the `withUnsafeBytes` mess is to use NSData.bytes.
let dataToDecryptNSData = NSData(data: data)

let bufferSize: Int = dataToDecryptNSData.length - ivSize
let buffer = UnsafeMutablePointer<NSData>.allocate(capacity: bufferSize)
defer { buffer.deallocate() }

var numberBytesDecrypted: Int = 0

let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
options, // options: CCOptions
key.bytes, // key: the "password"
key.length, // keyLength: the "password" size
dataToDecryptNSData.bytes, // iv: Initialization Vector
dataToDecryptNSData.bytes + kCCBlockSizeAES128, // dataIn: Data to decrypt bytes
bufferSize, // dataInLength: Data to decrypt size
buffer, // dataOut: decrypted Data buffer
bufferSize, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)

guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.decryptDataFailed
}

let decryptedData = Data(bytes: buffer, count: numberBytesDecrypted)

guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}

return decryptedString
}

这些是基于 this awesome answer来自用户“@zaph”。

虽然 encrypt 似乎可以正常工作,但 decrypt 却失败了。

这一行具体:

guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}

所以我当然错过了一些东西,但我无法弄清楚它是什么。可以吗?

这里是包含完整代码的 pastebin,您可以将其复制/粘贴到 Playground 中并点击播放。 Swift 5 是必需的:https://pastebin.com/raw/h6gacaHX

Update
I'm now following @OOper's suggested approach. The final code can be seen here:
https://github.com/backslash-f/aescryptable

最佳答案

事实上,在 Swift 5 中使用 Data.withUnsafeBytes 有点乱,虽然 NSData.bytes 不是最简单的方法,因为使用它有时看似有效,但有时无效。

如果您想使用 Data 在 Swift 中编写始终有效的代码,则需要习惯使用 Data.withUnsafeBytes

struct AES {
private let key: Data //<- Use `Data` instead of `NSData`

private let ivSize: Int = kCCBlockSizeAES128
private let options: CCOptions = CCOptions(kCCOptionPKCS7Padding)

init(keyString: String) throws {
guard keyString.count == kCCKeySizeAES256 else {
throw AESError.invalidKeySize
}
guard let keyData: Data = keyString.data(using: .utf8) else {
throw AESError.stringToDataFailed
}
self.key = keyData
}
}

extension AES: Cryptable {

func encrypt(_ string: String) throws -> Data {
guard let dataToEncrypt: Data = string.data(using: .utf8) else {
throw AESError.stringToDataFailed
}

let bufferSize: Int = ivSize + dataToEncrypt.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)

let status: Int32 = buffer.withUnsafeMutableBytes {bytes in
SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
bytes.baseAddress!
)
}
guard status == 0 else {
throw AESError.generateRandomIVFailed
}

var numberBytesEncrypted: Int = 0

let cryptStatus: CCCryptorStatus = key.withUnsafeBytes {keyBytes in
dataToEncrypt.withUnsafeBytes {dataBytes in
buffer.withUnsafeMutableBytes {bufferBytes in
CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCEncrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES), // alg: CCAlgorithm
options, // options: CCOptions
keyBytes.baseAddress, // key: the "password"
key.count, // keyLength: the "password" size
bufferBytes.baseAddress, // iv: Initialization Vector
dataBytes.baseAddress, // dataIn: Data to encrypt bytes
dataToEncrypt.count, // dataInLength: Data to encrypt size
bufferBytes.baseAddress! + kCCBlockSizeAES128, // dataOut: encrypted Data buffer
bufferSize, // dataOutAvailable: encrypted Data buffer size
&numberBytesEncrypted // dataOutMoved: the number of bytes written
)
}
}
}

guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.encryptDataFailed
}

return buffer[..<(numberBytesEncrypted + ivSize)]
}

func decrypt(_ data: Data) throws -> String {

let bufferSize: Int = data.count - ivSize
var buffer = Data(count: bufferSize)

var numberBytesDecrypted: Int = 0

let cryptStatus: CCCryptorStatus = key.withUnsafeBytes {keyBytes in
data.withUnsafeBytes {dataBytes in
buffer.withUnsafeMutableBytes {bufferBytes in
CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
options, // options: CCOptions
keyBytes.baseAddress, // key: the "password"
key.count, // keyLength: the "password" size
dataBytes.baseAddress, // iv: Initialization Vector
dataBytes.baseAddress! + kCCBlockSizeAES128, // dataIn: Data to decrypt bytes
bufferSize, // dataInLength: Data to decrypt size
bufferBytes.baseAddress, // dataOut: decrypted Data buffer
bufferSize, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)
}
}
}

guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.decryptDataFailed
}

let decryptedData = buffer[..<numberBytesDecrypted]

guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}

return decryptedString
}

}

关于aes - Swift 5 + kCCDecrypt (CommonCrypto) : Failing to decrypt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55484384/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com