2017-03-17 67 views
1

背景:我使用OpenSSL庫在Swift中創建PKCS12文件。我有存儲在鑰匙串中的證書和私鑰。如何從UnsafeMutablePointer構造Data/NSData <T>

問題:我能夠創建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()函數所要求的。

因此,長話短說,我該如何構造一個來自p12對象的Data/NSData對象,該對象的類型爲UnsafaMutablePointer<PKCS12>,因此我可以將它傳遞給SecPKCS12Import()

回答

1

這應該工作(它編譯,但我無法測試它)。我們的想法是在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 
} 
+0

謝謝!它工作完美!我想過使用BIO_new創建緩衝區,但無法弄清楚如何獲取cnt以及如何構建數據。無論如何,非常感謝您的善意幫助! –

相關問題