【问题标题】:How to prevent fatal errors from bad input into d2i_X509_REQ_bio in Swift with OpenSSL如何使用 OpenSSL 在 Swift 中防止因错误输入到 d2i_X509_REQ_bio 导致的致命错误
【发布时间】:2019-08-27 15:54:03
【问题描述】:

上下文:

我有以下代码将数据加载到 BIO 中,然后使用它获取 X509Req:

    let reqBIO = BIO_new(BIO_s_mem())
    let result = BIO_write(reqBIO, (reqData as NSData).bytes, Int32(reqData.count))
    let x509ReqContainer: UnsafeMutablePointer<X509_REQ> = d2i_X509_REQ_bio(reqBIO, nil)
    BIO_free(reqBIO) 

当输入是预期的 base64 编码 DER 时,此代码效果很好。但是,如果我传递一个 base64Encoded 垃圾字符串,它就会爆炸,而且丑陋,抛出一个致命的错误。

所以我的问题是:

  1. 我可以调用 OpenSSL 中的某些方法来确定 BIO 是否可以安全地发送到 d2i 函数,以便在这些情况下正常失败
  2. 有什么方法可以快速捕捉到 fatalError 吗? (我猜没有)
  3. 还有其他方法可以验证我的 base64 字符串是否包含 CSR

【问题讨论】:

    标签: ios swift error-handling openssl


    【解决方案1】:

    短版:d2i_X509_REQ_bio() 不会在输入无效时“引发错误”。它只是返回一个空指针。崩溃的原因是您(可能是无意中)在 Swift 中强制解包一个可选项。

    加长版: C 函数

    X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **x);
    

    返回无效输入的空指针。这个 C 函数映射到 Swift 为

    func d2i_X509_REQ_bio(...) -> UnsafeMutablePointer<X509_REQ>!
    

    以“隐式解包可选”(IUO)作为返回类型,空指针表示为nil。 IUO 几乎等同于“正常”(强)可选,唯一的区别是如果类型检查器需要,它会被强制解包。这就是任务中发生的事情

    let x509ReqContainer: UnsafeMutablePointer<X509_REQ> = d2i_X509_REQ_bio(reqBIO, nil)
    

    因为变量被声明为 非可选的。 如果 C 函数由于输入无效而返回空指针,则 Swift Optional.nil 被解包,程序因运行时错误而终止.

    解决方案:使用if let(或guard let)的可选绑定,让编译器自动推断类型:

    if let x509ReqContainer = d2i_X509_REQ_bio(reqBIO, nil) {
        // success ...
    } else {
        // failed ...
    }
    

    备注:您可以将Data 写入BIO

    let result = reqData.withUnsafeBytes {
        BIO_write(reqBIO, $0.baseAddress, Int32($0.count))
    }
    

    而不是将其转换为NSData

    【讨论】:

    • 写得很好的解释。今天下午我最终自己找到了同样的东西,你打破了科学的原因。我能够使用警卫保护语句,一切都很好。出于同样的原因,我在技术上可以使用 TYPE?作为变量也被分配,这也可以防止问题发生。
    • 跟进问题,相关。首先使用 IUO 的主要目的是什么?他们的正常用例是什么,因为在这种情况下很危险
    • @Unome:应该尽可能避免使用它们。有时需要它们用于无法立即初始化但已知在使用前已初始化的属性。一个典型的例子是 outlets (IBOutlet):它们没有在你的代码中初始化,但是当(例如)从故事板加载视图控制器时。 – Here Swift 导入器将 C 指针映射到 IUO 作为权衡,因为 C 声明没有 nullability annotations
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多