使用 Swift OpenSSL 3 的 CMAC 在初始化时失败

问题描述 投票:0回答:1

我尝试在 Swift 中使用 OpenSSL 3 EVP_MAC API 计算 CMAC,但我陷入了 EVP_MAC_init 调用,该调用总是失败。我尝试了很多不同的组合,但没有成功。

如果有人设法做到这一点,请告诉我,这让我发疯,因为 ERR_get_error() 调用也没有给我任何结果,失败后也返回 0。

这是函数:

static func generateAESCMAC(key: [UInt8], message: [UInt8] ) throws -> [UInt8] {
    guard let lib = OSSL_LIB_CTX_new()
    else {
        throw OpenSSLError.cmac("Cannot setup lib ctx")
    }
    defer { OSSL_LIB_CTX_free(lib) }
    
    guard let macAlgo = EVP_MAC_fetch(lib, "CMAC", nil)
    else {
        throw OpenSSLError.cmac("Cannot fetch CMAC algo")
    }
    defer { EVP_MAC_free(macAlgo) }

    guard let ctx = EVP_MAC_CTX_new(macAlgo)
    else {
        throw OpenSSLError.cmac("Cannot create CMAC ctx")
    }
    defer { EVP_MAC_CTX_free(ctx) }

    var params: [OSSL_PARAM] = []
    var cipherString = "aes-128-cbc".cString(using: .utf8)!
    let cipherParam = OSSL_PARAM_construct_utf8_string(
        OSSL_MAC_PARAM_CIPHER,
        &cipherString,
        0
    )
    params.append(cipherParam)
    params.append(OSSL_PARAM_construct_end())
    var keyValue = key
    guard EVP_MAC_init(ctx, &keyValue, key.count, params) == 1
    else {
        throw OpenSSLError.cmac("Cannot init CMAC")
    }
    
    guard EVP_MAC_update(ctx, message, message.count) == 1
    else {
        throw OpenSSLError.cmac("Cannot update CMAC")
    }
    
    var cmacResult = [UInt8](repeating: 0, count: Int(EVP_MAX_MD_SIZE))
    var cmacLength: size_t = 0
    guard EVP_MAC_final(ctx, &cmacResult, &cmacLength, cmacResult.count) == 1
    else {
        throw OpenSSLError.cmac("Cannot final CMAC")
    }
    
    return Array(cmacResult[0..<cmacLength])
}
swift openssl cmac
1个回答
0
投票

找到解决方案,OSSL_PARAM 的处理在内存方面不正常,导致 OSSL_PARAM 无效。这并不能解释为什么 init 调用从未生成错误,当使用无效参数列表调用时,它可能应该会生成错误。

以下代码有效:

static func generateAESCMAC(key: [UInt8], message: [UInt8]) throws -> [UInt8] {
    guard let lib = OSSL_LIB_CTX_new()
    else {
        throw OpenSSLError.cmac("Cannot setup lib ctx")
    }
    defer { OSSL_LIB_CTX_free(lib) }
    
    guard let macAlgo = EVP_MAC_fetch(lib, "CMAC", nil)
    else {
        throw OpenSSLError.cmac("Cannot fetch CMAC algo")
    }
    defer { EVP_MAC_free(macAlgo) }

    guard let ctx = EVP_MAC_CTX_new(macAlgo)
    else {
        throw OpenSSLError.cmac("Cannot create CMAC ctx")
    }
    defer { EVP_MAC_CTX_free(ctx) }

    var cipherString = "AES-128-CBC".cString(using: .utf8)!
    try OSSL_MAC_PARAM_CIPHER.withCString { cipherKey in
        try cipherString.withUnsafeMutableBytes { cipherBytes in
            let cipherParam = OSSL_PARAM_construct_utf8_string(
                cipherKey,
                cipherBytes.baseAddress,
                0
            )
            let params = [cipherParam, OSSL_PARAM_construct_end()]
            guard EVP_MAC_init(ctx, key, key.count, params) == 1
            else {
                throw OpenSSLError.cmac("Cannot init CMAC")
            }
        }
    }
            
    guard EVP_MAC_update(ctx, message, message.count) == 1
    else {
        throw OpenSSLError.cmac("Cannot update CMAC")
    }
    
    var cmacResult = [UInt8](repeating: 0, count: Int(EVP_MAX_MD_SIZE))
    var cmacLength: size_t = 0
    
    if EVP_MAC_final(ctx, &cmacResult, &cmacLength, cmacResult.count) == 1 {
        return Array(cmacResult[0..<cmacLength])
    } else {
        throw OpenSSLError.cmac("Cannot final CMAC")
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.