背景:我正在使用OpenSSL库在Swift中创建PKCS12文件。我将证书和私钥存储在钥匙串中。
问题:我能够创建PKCS12文件并将其成功存储在应用程序捆绑包中。当我想使用PKCS12文件时(例如,从HTTPS服务器接收身份验证挑战),我可以使用Apple提供的SecPKCS12Import()
函数加载该文件。现在,我不想生成物理文件,而是想在需要时生成飞行中的PKCS12对象。它将存储在内存中。由于我是Swift的新手,因此我寻求从UnsafeMutablePointer转换为Data的帮助。
阅读以下代码,您将了解更多:
以前,我将createP12
函数实现为:
createP12(pemCert: String, pemPK: String) {
// .......
// Code to load certificate and private key Object..
guard let p12 = PKCS12_create(passPhrase, name, privateKey, certificate, nil, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 0, 0, 0) else {
ERR_print_errors_fp(stderr)
return
}
// Save p12 to file
let fileManager = FileManager.default
let tempDirectory = NSTemporaryDirectory() as NSString
let path = tempDirectory.appendingPathComponent("ssl.p12")
fileManager.createFile(atPath: path, contents: nil, attributes: nil)
guard let fileHandle = FileHandle(forWritingAtPath: path) else {
LogUtils.logError("Cannot open file handle: \(path)")
return
}
let p12File = fdopen(fileHandle.fileDescriptor, "w")
i2d_PKCS12_fp(p12File, p12)
fclose(p12File)
fileHandle.closeFile()
}
然后,当我想读取p12文件时,我可以调用
let p12Data = NSData(contentsOfFile: Bundle.main.path(forResource: mainBundleResource, ofType:resourceType)!)! as Data
var items: CFArray?
let certOptions: NSDictionary = [kSecImportExportPassphrase as NSString: passwordStr as NSString]
self.securityError = SecPKCS12Import(p12Data as NSData, certOptions, &items)
// Code to read attributes
通过
createP12()
函数,我首先获得了UnsafeMutablePointer<PKCS12>
类型的p12对象,然后将其存储在文件中。相反,现在我想直接将p12传递给pkcs12阅读器函数。为此,我必须首先将p12对象转换为Data / NSData对象,因为这是SecPKCS12Import()
函数所需要的。所以,长话短说,我怎么能从
UnsafaMutablePointer<PKCS12>
类型的p12对象构造一个Data / NSData对象,然后将其传递给SecPKCS12Import()
呢? 最佳答案
这应该工作(它可以编译,但我无法对其进行测试)。想法是将PKCS12对象写入内存缓冲区,然后创建Data
从缓冲区:
func p12ToData(p12: UnsafeMutablePointer<PKCS12>) -> Data {
// Write PKCS12 to memory buffer:
let mbio = BIO_new(BIO_s_mem())
i2d_PKCS12_bio(mbio, p12)
// Get pointer to memory buffer and number of bytes. The
// # define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
// macro is not imported to Swift.
var ptr = UnsafeRawPointer(bitPattern: 1)!
let cnt = BIO_ctrl(mbio, BIO_CTRL_INFO, 1, &ptr)
// Create data from pointer and count:
let data = Data(bytes: ptr, count: cnt)
// Release memory buffer:
BIO_free(mbio)
return data
}