首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CommonCrypto加密解密不匹配

CommonCrypto加密解密不匹配
EN

Stack Overflow用户
提问于 2021-08-21 16:59:05
回答 2查看 253关注 0票数 1

是否有人看到以下代码的错误所在,因为下面的代码在加密和发送到服务器时运行良好(这意味着我的加密功能很好),但是,我的解密逻辑似乎存在一些问题,无法正确地解密信息。

注意:服务器端enc/dec逻辑与其他语言(如Java )工作良好

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

MyEncDec.swift

代码语言:javascript
复制
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
}
}
EN

回答 2

Stack Overflow用户

发布于 2021-08-25 13:58:02

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

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

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

代码语言:javascript
复制
// 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
        }
    }

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

票数 2
EN

Stack Overflow用户

发布于 2021-08-25 13:24:48

我只是尝试运行您的客户端代码,加密和解密一个示例数据,而且它似乎正常工作。是否只有在试图解密来自服务器的数据缓冲区时才会出现此问题?

我以以下方式测试了您的代码:

代码语言:javascript
复制
    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和数据的字符串组合。

代码语言:javascript
复制
let final_encrypted = iv.toString('hex') + ':' + encrypted.toString('hex');

因此,来自服务器的字符串必须在解密前进行解析,以便检索iv和数据。

代码语言:javascript
复制
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)
                }
            }
        }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68875067

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档