Swift AES 通用加密 - AES 解密过程中的前 16 个字符被省略
Swift AES Common crypto - First 16 characters during AES decryption gets omitted
尝试在 swift 中使用 AES(普通密码)执行加密和解密,由于某些原因,解密前 16 个字符被删除。任何人都可以看看下面的游乐场代码并提出这里可能出了什么问题吗?。 decodedString 变量在解密过程中删除原始 payloadString 的前 16 个字符。
游乐场代码
import UIKit
import CommonCrypto
class AESNew {
enum MyError: LocalizedError {
case first(message: String)
case second(message: String)
var errorDescription: String? { return "Some description here!" }
}
func encrypt(plainText: String, keyData:Data, iv: Data, options:Int = kCCOptionPKCS7Padding) -> Result<Data, Error> {
let plainData = Data(plainText.utf8)
if let cryptData = NSMutableData(length: Int((plainData.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
//let value = iv.withUnsafeBytes { [=11=].load(as: UInt32.self) }
let cryptResult = iv.withUnsafeBytes { (dataBytes : UnsafePointer<UInt8>) -> Result<Data, Error> in
print(dataBytes)
print(UnsafeRawPointer(dataBytes))
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes,
keyLength,
UnsafeRawPointer(dataBytes),
(plainData as NSData).bytes, plainData.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
print("base64cryptString: \(base64cryptString)")
return .success(cryptData as Data)
} else {
print("failure")
return .failure(MyError.first(message: "crypt failed"))
}
}
return cryptResult
}
return .failure(MyError.second(message: "no value failure"))
}
// The iv is prefixed to the encrypted data
func decrypt(data: Data, keyData: Data) throws -> Data? {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if validKeyLengths.contains(keyLength) == false {
print("validKeyLengths does not match")
}
let ivSize = kCCBlockSizeAES128
let clearLength = size_t(data.count - ivSize)
var clearData = Data(count: clearLength)
var numBytesDecrypted: size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes,
keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128,
clearLength,
cryptBytes,
clearLength,
&numBytesDecrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
} else {
print("Decryption failed")
}
return clearData
}
}
func randomGenerateBytes(count: Int) -> Data? {
let bytes = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1)
defer { bytes.deallocate() }
let status = CCRandomGenerateBytes(bytes, count)
guard status == kCCSuccess else { return nil }
return Data(bytes: bytes, count: count)
}
var ivBytesNew = Data()
if let ivBytes = randomGenerateBytes(count: 16) {
ivBytesNew = ivBytes
} else {
print("randomGenerateBytes failed")
}
let keyString = "keyData890123456"
let keyData = "keyData890123456".data(using:String.Encoding.utf8)!
let payloadString = "asdflkasfdkaslfd12345"
let aesObject = AESNew()
let encrytedObject = aesObject.encrypt(plainText: payloadString, keyData: keyData, iv: ivBytesNew, options: kCCOptionPKCS7Padding)
var encryptedData = Data()
switch encrytedObject {
case .success(let encData):
print(encData)
encryptedData = encData
case .failure(let error):
print(error)
default:
print("enc failed")
}
if let decrypedData = try? aesObject.decrypt(data: encryptedData, keyData: keyData) {
if let decodedString = String(data: decrypedData, encoding: .utf8) {
print(decodedString) // 1234, first 16 characters are omitted.
} else {
print("conversion from data to string failed")
}
} else {
print("decryption failed")
}
看来你选择了两种不同的加密和解密。
您是否看到您的 decrypt
没有 AES 解密所需的参数 iv
?
您的 decrypt
期望 data
的前 16 个字节为 iv
,其余为加密数据。但是你的encrypt
returns只是加密数据。
请尝试按如下方式更改调用 decrypt
的线路:
if let decrypedData = try? aesObject.decrypt(data: ivBytesNew + encryptedData, keyData: keyData) {
通常,您的 encrypt
使用 NSMutableData
和处理 bytes
不当。这是脆弱的,它可能会在某些不同的上下文中崩溃。我强烈建议您不要使用当前的 encrypt
.
无论如何,你应该使 encrypt
和 decrypt
一致,或者说是对称的,目前它们不是。
尝试在 swift 中使用 AES(普通密码)执行加密和解密,由于某些原因,解密前 16 个字符被删除。任何人都可以看看下面的游乐场代码并提出这里可能出了什么问题吗?。 decodedString 变量在解密过程中删除原始 payloadString 的前 16 个字符。
游乐场代码
import UIKit
import CommonCrypto
class AESNew {
enum MyError: LocalizedError {
case first(message: String)
case second(message: String)
var errorDescription: String? { return "Some description here!" }
}
func encrypt(plainText: String, keyData:Data, iv: Data, options:Int = kCCOptionPKCS7Padding) -> Result<Data, Error> {
let plainData = Data(plainText.utf8)
if let cryptData = NSMutableData(length: Int((plainData.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
//let value = iv.withUnsafeBytes { [=11=].load(as: UInt32.self) }
let cryptResult = iv.withUnsafeBytes { (dataBytes : UnsafePointer<UInt8>) -> Result<Data, Error> in
print(dataBytes)
print(UnsafeRawPointer(dataBytes))
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes,
keyLength,
UnsafeRawPointer(dataBytes),
(plainData as NSData).bytes, plainData.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
print("base64cryptString: \(base64cryptString)")
return .success(cryptData as Data)
} else {
print("failure")
return .failure(MyError.first(message: "crypt failed"))
}
}
return cryptResult
}
return .failure(MyError.second(message: "no value failure"))
}
// The iv is prefixed to the encrypted data
func decrypt(data: Data, keyData: Data) throws -> Data? {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if validKeyLengths.contains(keyLength) == false {
print("validKeyLengths does not match")
}
let ivSize = kCCBlockSizeAES128
let clearLength = size_t(data.count - ivSize)
var clearData = Data(count: clearLength)
var numBytesDecrypted: size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes,
keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128,
clearLength,
cryptBytes,
clearLength,
&numBytesDecrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
} else {
print("Decryption failed")
}
return clearData
}
}
func randomGenerateBytes(count: Int) -> Data? {
let bytes = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1)
defer { bytes.deallocate() }
let status = CCRandomGenerateBytes(bytes, count)
guard status == kCCSuccess else { return nil }
return Data(bytes: bytes, count: count)
}
var ivBytesNew = Data()
if let ivBytes = randomGenerateBytes(count: 16) {
ivBytesNew = ivBytes
} else {
print("randomGenerateBytes failed")
}
let keyString = "keyData890123456"
let keyData = "keyData890123456".data(using:String.Encoding.utf8)!
let payloadString = "asdflkasfdkaslfd12345"
let aesObject = AESNew()
let encrytedObject = aesObject.encrypt(plainText: payloadString, keyData: keyData, iv: ivBytesNew, options: kCCOptionPKCS7Padding)
var encryptedData = Data()
switch encrytedObject {
case .success(let encData):
print(encData)
encryptedData = encData
case .failure(let error):
print(error)
default:
print("enc failed")
}
if let decrypedData = try? aesObject.decrypt(data: encryptedData, keyData: keyData) {
if let decodedString = String(data: decrypedData, encoding: .utf8) {
print(decodedString) // 1234, first 16 characters are omitted.
} else {
print("conversion from data to string failed")
}
} else {
print("decryption failed")
}
看来你选择了两种不同的加密和解密。
您是否看到您的 decrypt
没有 AES 解密所需的参数 iv
?
您的 decrypt
期望 data
的前 16 个字节为 iv
,其余为加密数据。但是你的encrypt
returns只是加密数据。
请尝试按如下方式更改调用 decrypt
的线路:
if let decrypedData = try? aesObject.decrypt(data: ivBytesNew + encryptedData, keyData: keyData) {
通常,您的 encrypt
使用 NSMutableData
和处理 bytes
不当。这是脆弱的,它可能会在某些不同的上下文中崩溃。我强烈建议您不要使用当前的 encrypt
.
无论如何,你应该使 encrypt
和 decrypt
一致,或者说是对称的,目前它们不是。