c - swift (Linux) : Extract CMS/PKCS#7 Certs and Validate Container Signature?

标签 c swift openssl digital-signature pkcs#7

我正在用 Swift 4 编写一组将在 Linux 上运行的服务。我需要做的一件事是接收使用加密消息语法 (CMS) 格式进行数字签名的有效负载,提取用于对其进行签名的证书,然后验证签名。我知道 Linux 上的 Swift 不包含用于此类事情的 Security 或 CommonCrypto 框架,因此我已经链接到 OpenSSL 以尝试帮助解决这个问题。我已经离开我的 C/C++ 编程时代大约 2 年了,所以我欣然承认我在这部分代码上不知所措。

我有 2 个简单的类作为 OpenSSL 的包装器 BIOPKCS7数据结构。它们看起来像这样:

import Foundation
import OpenSSL

public final class BIOWrapper {

    public var bio = BIO_new(BIO_s_mem())

    public init(data: Data) {
        data.withUnsafeBytes { pointer -> Void in
            BIO_write(self.bio, pointer, Int32(data.count))
        }
    }

    public init() {}

    deinit {
        BIO_free(self.bio)
    }
}

public final class PKCS7Wrapper {

    public var pkcs7: UnsafeMutablePointer<PKCS7>

    public init(pkcs7: UnsafeMutablePointer<PKCS7>) {
        self.pkcs7 = pkcs7
    }

    deinit {
        PKCS7_free(self.pkcs7)
    }
}

我能够成功提取 PKCS#7 容器数据并验证数据类型代码值为 NID_pkcs7_signed使用此代码:

let reqData = Data(bytes: reqBytes)
        guard reqData.count > 0 else {
            print("Empty request body")
            return nil
        }

        let bioWrapper = BIOWrapper(data: reqData)
        guard let container = d2i_PKCS7_bio(bioWrapper.bio, nil) else {
            print("No container")
            return nil
        }

        let pkcs7Wrapper = PKCS7Wrapper(pkcs7: container)
        let dataTypeCode = OBJ_obj2nid((pkcs7Wrapper.pkcs7.pointee.d.sign).pointee.contents.pointee.type)
        print("dataTypeCode : \(dataTypeCode)")

        if dataTypeCode == NID_pkcs7_data {
            print("GOT DATA!")
        } else {
            print("Didn't get data")
            return nil
        }

       let pkcs7SignedTypeCode = OBJ_obj2nid(pkcs7Wrapper.pkcs7.pointee.type)
        if let signed = pkcs7SignedTypeCode == NID_pkcs7_signed {
            print("Signed : \(signed)")
        }

但是,我现在已经到了卡住的地步。如何从 PKCS#7 负载中获取 X.509 证书数据?我可以看到 pkcs7Wrapper.pkcs7.pointee.d.sign.pointee.cert数据结构应包含证书链数据。它的数据类型是UnsafeMutablePointer<stack_st_x509>我想我可以找出使用 OpenSSL 的 PKCS7_verify 的代码一旦我在内存中获得 X.509 证书数据。我只是不知道该怎么做。

我找到了 this resource讨论在 OSX/iOS 上验证收据,涉及很多相同的问题。他们从文件系统获取 X.509 证书并将数据传递到 PKCS7_verify方法。我只需要知道如何从 PKCS#7 容器中获取证书数据并传入即可。

谁能帮我解决这个问题?我认识到从 Swift 调用 C 并不理想,但由于 Swift 没有良好的安全/加密框架,我不知道有任何其他选择。

最佳答案

答案的核心部分在您链接的代码中:

let store = X509_STORE_new()
X509_STORE_add_cert(store, appleRootX509)
OpenSSL_add_all_digests()
let result = PKCS7_verify(receiptPKCS7, nil, store, nil, nil, 0)
if result != 1 {
    log.atLevelDebug(id: 0, source: "Main", message: "Receipt signature verification failed")
    exit(errorCode)
}

您似乎缺少的事实是您不必自己从 PKCS7 数据中提取 X509 证书。 PKCS7_verify function will do it作为验证的一部分:

An attempt is made to locate all the signer's certificates, first looking in the certs parameter (if it is not NULL) and then looking in any certificates contained in the p7 structure itself. If any signer's certificates cannot be located the operation fails.

因此,您需要自己加载的唯一证书是您观察到它们从 linked code 中的文件系统加载的根证书。 .

如果您出于某种原因仍然确实需要 Swift 解决方案来从 PKCS7 数据中提取证书,则必须为 PKCS7 构建一个 ASN.1 解析器。不确定这是否适用于 Swift,this simple code是快速搜索的结果,this是对 PKCS7 数据的很好描述。

关于c - swift (Linux) : Extract CMS/PKCS#7 Certs and Validate Container Signature?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49451395/

相关文章:

c - 从线程向我的主信号发出信号?

c - Labwindows 无法编译 - 表示缺少项目中已有的 dll

swift - 如何引用 UIPickerView 中选定的行?

linux - 使用 OpenSSL 创建证书颁发机构

encryption - 安全素数的产生

c - 在 C 中使用 OpenSSL 时 EVP_CIPHER_CTX_new() 中的段错误

c - 二维数组的无限 for 循环

c - DSP 处理器字大小

ios - AVFoundation:如何获取 AVURLAsset 流式传输的视频的视频尺寸?

swift - 在 tableView 上搜索多个对象