使用OpenSSL从SecKey生成CSR

8
我已经使用SecKeyGeneratePair创建了一对公钥/私钥(椭圆曲线)。
如何使用SecKey实例在Swift中使用OpenSSL生成CSR?

1
相关内容,但不是使用Swift。 - Ben Aubin
2个回答

4
据我所知,苹果的安全框架目前没有公开API生成CSR。它在技术上是OpenSSL包装的;因此,如果您有OpenSSL(我个人更喜欢LibreSSL,libtls使生活更轻松),则可以使用它。
作为替代方案,您还可以使用Commoncrypto,但我的答案不涉及此内容,但有很多示例可供参考。
因此,让我们通过以下步骤找出如何做到这一点。我发现使用OpenSSL的最简单方法是完全忽略文档,直接阅读源代码。
为了实现我们所需的内容,我们需要“复制”以下两个命令:
openssl ecparam -out server.key -name prime256v1 -genkey
openssl req -new -key server.key -out server.csr 重要提示:务必选择一个安全的曲线。使用openssl ecparam -list_curves获取您的openssl版本支持的曲线列表。阅读更多 第一步 生成密钥

ecparam告诉我们首先要查看sslsource/apps/openssl/ecparam.c。

源代码给出了三个步骤:设置BIO以进行写入,设置组参数,最后生成密钥。

第二步 生成CSR

遵循相同的原则,但这次要查看req.c和一些包含在req.c中使用的样板代码的apps.c代码。

我使用了这种方法创建了一个简单但有效的概念证明,可以在Swift中运行,您可以在GitHub上检查它:CertificateTool。该代码将在您可以编译Swift4+工具链和某个版本的openSSL的任何系统上运行。

编辑:

生成EC秘密密钥:

//
//  ECKey.swift
//  CertificateToolPackageDescription
//
//  Created by Antwan van Houdt on 10/01/2018.
//
import CLibreSSL

public class ECKey {
    internal let secretKey: OpaquePointer
    private let group: OpaquePointer

    public init() {
        group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)
        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE)
        EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_COMPRESSED)

        secretKey = EC_KEY_new()
        EC_KEY_set_group(secretKey, group)
        EC_KEY_generate_key(secretKey)
    }

    deinit {
        EC_KEY_free(secretKey)
        EC_GROUP_free(group)
    }
}

创建签名请求:
//
//  CertificateRequest.swift
//  CertificateToolPackageDescription
//
//  Created by Antwan van Houdt on 10/01/2018.
//
import CLibreSSL

public enum NIDType: String {
    case email    = "emailAddress"
    case hostName = "CN"
    case organizationalUnit = "OU"
    case organization      = "O"
    case city        = "L"
    case state       = "ST"
    case countryCode = "C"
}

public class CertificateSigningRequest {
    private let request: UnsafeMutablePointer<X509_REQ>
    private let key:     ECKey
    private let name:    UnsafeMutablePointer<X509_NAME>

    public init(key: ECKey, email: String, hostName: String, organizationalUnit: String, organization: String, countryCode: String, state: String, city: String) {
        request = X509_REQ_new()
        self.key = key

        name = X509_NAME_new()
        X509_REQ_set_version(request, 2)

        self.add(name: email, type: .email)
        self.add(name: hostName, type: .hostName)
        self.add(name: organizationalUnit, type: .organizationalUnit)
        self.add(name: organization, type: .organization)
        self.add(name: countryCode, type: .countryCode)
        self.add(name: city, type: .city)
        self.add(name: state, type: .state)

        X509_REQ_set_subject_name(request, name)

        self.setPublicKey()
    }

    deinit {
        X509_REQ_free(request)
        X509_NAME_free(name)
    }

    private func add(name: String, type: NIDType) {
        var buff = Array(name.utf8)
        X509_NAME_add_entry_by_NID(self.name, OBJ_txt2nid(type.rawValue), MBSTRING_UTF8, &buff, Int32(buff.count), 0, 0)
    }

    private func setPublicKey() {
        let certKey = EVP_PKEY_new()
        EVP_PKEY_set1_EC_KEY(certKey, key.secretKey)

        X509_REQ_set_pubkey(request, certKey)
        X509_REQ_sign(request, certKey, EVP_sha256())

        EVP_PKEY_free(certKey)
    }
}

注意:此代码不包含任何与BIO相关的函数(但是),将PEM数据写入文件或数据缓冲区非常容易添加。

免责声明:我不是专业的密码学家,也不知道OpenSSL API的所有细节。我不能保证我提供的代码是100%正确的实现。始终谨慎对待从网络下载的代码,尤其是加密代码。


0

虽然这不是纯粹的OpenSSL实现,但我发现 outfoxx's Shield library 让通过Swift创建证书签名请求变得非常容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接