CommonCrypto Encryption解密不匹配



有没有人看到下面的代码出了什么问题,因为下面的代码在加密和发送到服务器时工作得很好(这意味着我的加密功能是好的),但是我的解密逻辑似乎有一些问题,不能正确解密信息。

注意:服务器端enc/dec逻辑可以很好地与其他语言一起工作,例如Java

服务器端实现示例:Nodejs Crypto to Swift commonCrypto

MyEncDec.swift

import Foundation
import CommonCrypto
struct AES256 {
private var key: Data
private var iv: Data
public init(key: Data, iv: Data) throws {
guard key.count == kCCKeySizeAES256 else {
throw Error.badKeyLength
}
guard iv.count == kCCBlockSizeAES128 else {
throw Error.badInputVectorLength
}
self.key = key
self.iv = iv
}
enum Error: Swift.Error {
case keyGeneration(status: Int)
case cryptoFailed(status: CCCryptorStatus)
case badKeyLength
case badInputVectorLength
}
func encrypt(_ digest: Data) throws -> Data {
return try crypt(input: digest, operation: CCOperation(kCCEncrypt))
}
func decrypt(_ encrypted: Data) throws -> Data {
return try crypt(input: encrypted, operation: CCOperation(kCCDecrypt))
}
private func crypt(input: Data, operation: CCOperation) throws -> Data {
var outLength = Int(0)
var outBytes = [UInt8](repeating: 0, count: input.count + kCCBlockSizeAES128)
var status: CCCryptorStatus = CCCryptorStatus(kCCSuccess)
input.withUnsafeBytes { rawBufferPointer in
let encryptedBytes = rawBufferPointer.baseAddress!
iv.withUnsafeBytes { rawBufferPointer in
let ivBytes = rawBufferPointer.baseAddress!
key.withUnsafeBytes { rawBufferPointer in
let keyBytes = rawBufferPointer.baseAddress!
status = CCCrypt(operation,
CCAlgorithm(kCCAlgorithmAES128),            // algorithm
CCOptions(kCCOptionPKCS7Padding),           // options
keyBytes,                                   // key
key.count,                                  // keylength
ivBytes,                                    // iv
encryptedBytes,                             // dataIn
input.count,                                // dataInLength
&outBytes,                                  // dataOut
outBytes.count,                             // dataOutAvailable
&outLength)                                 // dataOutMoved
}
}
}
guard status == kCCSuccess else {
throw Error.cryptoFailed(status: status)
}
return Data(bytes: &outBytes, count: outLength)
}
static func createKey(password: Data, salt: Data) throws -> Data {
let length = kCCKeySizeAES256
var status = Int32(0)
var derivedBytes = [UInt8](repeating: 0, count: length)
password.withUnsafeBytes { rawBufferPointer in
let passwordRawBytes = rawBufferPointer.baseAddress!
let passwordBytes = passwordRawBytes.assumingMemoryBound(to: Int8.self)
salt.withUnsafeBytes { rawBufferPointer in
let saltRawBytes = rawBufferPointer.baseAddress!
let saltBytes = saltRawBytes.assumingMemoryBound(to: UInt8.self)
status = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2),                  // algorithm
passwordBytes,                                // password
password.count,                               // passwordLen
saltBytes,                                    // salt
salt.count,                                   // saltLen
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),   // prf
10000,                                        // rounds
&derivedBytes,                                // derivedKey
length)                                       // derivedKeyLen
}
}
guard status == 0 else {
throw Error.keyGeneration(status: Int(status))
}
return Data(bytes: &derivedBytes, count: length)
}
static func randomIv() -> Data {
return randomData(length: kCCBlockSizeAES128)
}
static func iV() -> Data {
let arr: [UInt8] = [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1]
return Data(arr)
}
static func randomSalt() -> Data {
return randomData(length: 8)
}
static func randomData(length: Int) -> Data {
var data = Data(count: length)
var mutableBytes: UnsafeMutableRawPointer!
data.withUnsafeMutableBytes { rawBufferPointer in
mutableBytes = rawBufferPointer.baseAddress!
}
let status = SecRandomCopyBytes(kSecRandomDefault, length, mutableBytes)
assert(status == Int32(0))
return data
}
}

我需要猜测一下,因为您没有提供运行encryptdecrypt的代码。但我认为你提供iv使用randomIV()在加密和解密方面,这将是一个问题。

您需要为解密和加密端提供相同的iv这意味着您需要将您的随机iv从加密端发送到解密端,并在解密过程中使用该iv。

我对Swift没有经验,但我认为你需要像这样使用你的代码才能正确工作:

// Encryption side
let keyData = Data("KEY01234567890123456789012345678".utf8)
let data = Data("TEST123".utf8)

let iv = AES256.randomIv()
if let aes = try? AES256.init(key: keyData, iv: iv) {
if let encryptedData = try? aes.encrypt(data) {
var resultData = iv
resultData.append(encryptedData)
// use resultData here
}
}
// Decryption side
let keyData = Data("KEY01234567890123456789012345678".utf8)
let data = resultData

let iv = data.subdata(in: ..<kCCBlockSizeAES128)
let encryptedPart = data.subdata(in: kCCBlockSizeAES128...)
if let aes = try? AES256.init(key: keyData, iv: iv) {
if let decryptedData = try? aes.decrypt(encryptedPart) {
// use decryptedData here
}
}

我使用crystal代码作为此代码的基础。

我只是试着运行您的客户端代码加密和解密样本数据,它似乎工作正常。是否只有当您试图解密来自服务器的数据缓冲区时才会出现该问题?

我用下面的方法测试了你的代码:

let keyData = Data("KEY01234567890123456789012345678".utf8)
let data = Data("TEST123".utf8)

let iv = AES256.randomIv()
if let aes = try? AES256.init(key: keyData, iv: iv), let aes2 = try? AES256.init(key: keyData, iv: iv) {
if let encriptedData = try? aes.encrypt(data) {
if let decryptedData = try? aes2.decrypt(encriptedData) {
let decryptedString = String(decoding: decryptedData, as: UTF8.self)
print(decryptedString)
}
}
}

我不确定你是如何使用AES256类,但看看服务器端代码:

加密函数生成iv和使用":"的数据组成的字符串。分离器。

let final_encrypted = iv.toString('hex') + ':' + encrypted.toString('hex');

所以来自服务器的字符串必须在解密之前被解析,以便检索iv和数据。

func parseAndDecrypt(encryptedString: String) {
let keyData = Data("KEY01234567890123456789012345678".utf8)
let substrings = encryptedString.split(separator: ":")
if let ivString = substrings.first, let dataString = substrings.last {
let iv = Data(ivString.utf8)
let encryptedData = Data(dataString.utf8)
if let aes = try? AES256.init(key: keyData, iv: iv) {
if let decryptedData = try? aes.decrypt(encryptedData) {
let decryptedString = String(decoding: decryptedData, as: UTF8.self)
print(decryptedString)
}
}
}
}

相关内容

  • 没有找到相关文章

最新更新