使用OpenSSL从SecKey生成CSR

问题描述:

我创建了一个公钥/私钥对(椭圆曲线),其中包含SecKeyGeneratePair使用OpenSSL从SecKey生成CSR

如何使用SecKey实例在Swift中使用OpenSSL生成CSR?

+1

[相关](https://stackoverflow.com/questions/13456237/generating-an-openssl-certificate-signing-request-in-ios-with-keychain-stored-ke?rq=1)但不是迅速。 –

据我可以告诉苹果自己的安全框架没有API当前暴露f或生成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版本支持的曲线列表。 Read more

步骤1生成密钥

ecparam告诉我们,我们在sslsource /应用/ OpenSSL的/ ecparam.c先看看。

来源给我们3个步骤: 设置BIO进行写入,设置组参数并最终生成密钥。

步骤2生成CSR

按照同样的原则,但这次在寻找req.capps.c一些代码,包含req.c

使用的一些样板代码我用这个方法来创建粗但是运行速度很快的工作概念证明,您可以在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%正确的实现。始终保持谨慎的代码,尤其是加密代码,从网上下载。