您可以使用Security.framework 生成证书。您需要手动添加 x509 标头。
我将在下面发布的 sn-ps 是简化的示例。确保您负责任地处理 nil 值。
以下代码将生成证书:
func obtainKeyData(_ tag: String) -> Data {
var keyRef: AnyObject?
let query: Dictionary<String, AnyObject> = [
String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
String(kSecReturnData): kCFBooleanTrue as CFBoolean,
String(kSecClass): kSecClassKey as CFString,
String(kSecAttrApplicationTag): tag as CFString,
]
switch SecItemCopyMatching(query as CFDictionary, &keyRef) {
case noErr:
return keyRef as! Data
default:
fatalError("Error")
}
}
现在您需要为其添加一个 x509 标头。您可以使用Data 类别:
extension Data {
public func dataByPrependingX509Header() -> Data {
let result = NSMutableData()
let encodingLength: Int = (self.count + 1).encodedOctets().count
let OID: [CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00]
var builder: [CUnsignedChar] = []
// ASN.1 SEQUENCE
builder.append(0x30)
// Overall size, made of OID + bitstring encoding + actual key
let size = OID.count + 2 + encodingLength + self.count
let encodedSize = size.encodedOctets()
builder.append(contentsOf: encodedSize)
result.append(builder, length: builder.count)
result.append(OID, length: OID.count)
builder.removeAll(keepingCapacity: false)
builder.append(0x03)
builder.append(contentsOf: (self.count + 1).encodedOctets())
builder.append(0x00)
result.append(builder, length: builder.count)
// Actual key bytes
result.append(self)
return result as Data
}
}
最后,将两者结合起来创建 x509 格式的证书:
let x509Key = obtainKeyData(keyTag).dataByPrependingX509Header()
作为参考,我从 Heimdall 项目中获得了这段代码,这是一个用于 Swift 的 Security 框架包装器,它目前正在一个私有应用程序中使用。