我已经使用SecKeyGeneratePair
创建了一个公共/私钥对(椭圆曲线(。
我如何使用SecKey
实例使用Swift中的OpenSSL?
据我所知,苹果自己的安全框架当前没有API或生成CSR的API。从技术上讲,它包裹了。因此,如果您确实有openssl(我个人更喜欢libressl,libtls使生活变得轻松(。
作为替代方案,您也可以使用CommunCrypto,我的答案不会涵盖,但是那里有很多示例
因此,让我们仔细研究了如何做到这一点的步骤。我发现使用OpenSSL
的最简单方法是完全忽略文档并直接转到阅读源。
要实现我们需要的东西,我们需要"复制"以下2个命令:
openssl ecparam -out server.key -name prime256v1 -genkey
openssl req -new -key server.key -out server.csr
重要说明:确保选择安全曲线。使用openssl ecparam -list_curves通过您的OpenSSL版本获取支持曲线的列表。阅读更多
步骤1 生成键
ecparam
告诉我们,我们必须查看SSLSource/apps/openssl/ecparam.c first。
来源为我们提供了3个步骤:设置用于写作,设置组参数并最终生成密钥的简历。
步骤2 生成CSR
遵循相同的原理,但是这次查看req.c
和apps.c
中的一些代码,其中包含req.c
中使用的一些样板代码
我使用此方法创建了一个粗略但有效的概念证明,该概念在Swift中运行,您可以在GitHub上查看此处:CERTIFERATETOOL该代码将在您可以编译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)
}
}
NOTE 此代码不包含任何与Bio相关的功能(尚未(将PEM数据写入文件或数据缓冲区的功能,但是它们确实很容易添加。
免责声明:我不是专业的密码学家,也不知道OpenSSL API的所有来龙去脉。我不能保证我提供的代码是100%正确的实施。始终对从网络下载的代码,尤其是加密代码。
尽管它不是直接的OpenSSL实现,但我遇到了Outfoxx的Shield库,这使得通过Swift创建CSR非常容易。