首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成P12文件Xcode?

生成P12文件Xcode?
EN

Stack Overflow用户
提问于 2016-07-11 23:24:29
回答 2查看 2.3K关注 0票数 2

我知道有一个名为SecPKCS12Import的函数允许您从p12文件中导入数据。然而,我想走相反的路线。我有一个SecCertificateRef和一个公共/私有SecKeyRef,我想使用它们来创建一个P12文件。有人知道如何在iPhone上这样做吗?

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-12 12:58:45

不幸的是,CommonCrypto没有提供任何方法来导出PKCS12容器,更不用说任何其他导出功能了(尽管它的OSX容器可以这样做)。有一些方法可以从密钥链中提取SecKeyRef原始数据,但是您仍然需要自己编写所有PKCS12包装。

我们也面临着一个类似的问题,于是我们选择了OpenSSL。

编译iOS的OpenSSL

集成OpenSSL需要做一些工作,因为您需要自己编译和链接OpenSSL源代码。幸运的是,有一些构建脚本可用,所以您不必自己做,例如,https://github.com/x2on/OpenSSL-for-iPhone。我建议您使用它们,因为您需要修补一些Makefile,这是有点淡褐色。这些构建脚本为iOS和tvOS生成静态链接库。您只需要将它们与您的项目链接起来,并相应地设置标头和库搜索路径。

CocoaPods

您还可以使用正式的OpenSSL CocoaPod。这为您节省了配置项目的麻烦。

出口PKCS12

您可能知道,OpenSSL是一个C库。这意味着您可能希望将所有C函数封装到一个目标-C或Swift包装器中。有一些开源包装器支持im-和导出PKCS12容器,但我还没有找到一个具有良好文档的包装器。不过,您应该能够从一些源派生出相关的片段。

https://github.com/microsec/MscX509Common/blob/master/src/MscPKCS12.m

您也可以看看这个例子,http://fm4dd.com/openssl/pkcs12test.htm

希望这能帮上忙!

票数 2
EN

Stack Overflow用户

发布于 2017-02-05 14:25:12

我同意这个任务只能使用OpenSSL执行。为iOS编译它有点棘手,但是使用OpenSSL换iPhone是很有可能的。

要解决从PKCS12SecCertificateSecKey创建Swift 3的给定任务,只需将静态库libssl.alibcrypto.a添加到项目中,并创建以下桥接头:

代码语言:javascript
复制
#import <openssl/err.h>
#import <openssl/pem.h>
#import <openssl/pkcs12.h>
#import <openssl/x509.h>

要创建密钥存储库,输入数据必须转换为OpenSSL数据结构,这需要一些创造性。SecCertificate可以直接转换为DER格式,然后读入X509结构。SecKey更难处理。获取密钥数据的唯一可能解决方案是将其写入密钥链并获取引用。从引用中我们可以得到基64编码的字符串,然后可以将其读取到EVP_PKEY结构中。现在,我们可以创建keystore并将其保存到一个文件中。要通过iOS函数访问密钥库中的数据,我们必须通过let data = FileManager.default.contents(atPath: path)! as NSData读取文件

完整的解决方案如下:

代码语言:javascript
复制
func createP12(secCertificate: SecCertificate, secPrivateKey: SecKey) {
    // Read certificate
    // Convert sec certificate to DER certificate
    let derCertificate = SecCertificateCopyData(secCertificate)
    // Create strange pointer to read DER certificate with OpenSSL
    // data must be a two-dimensional array containing the pointer to the DER certificate as single element at position [0][0]
    let certificatePointer = CFDataGetBytePtr(derCertificate)
    let certificateLength = CFDataGetLength(derCertificate)
    let certificateData = UnsafeMutablePointer<UnsafePointer<UInt8>?>.allocate(capacity: 1)
    certificateData.pointee = certificatePointer
    // Read DER certificate
    let certificate = d2i_X509(nil, certificateData, certificateLength)
    // Print certificate
    X509_print_fp(stdout, certificate)
    // Read private key
    // Convert sec key to PEM key
    let tempTag = "bundle.temp"
    let tempAttributes = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: tempTag,
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecValueRef: secPrivateKey,
        kSecReturnData: kCFBooleanTrue
        ] as NSDictionary
    var privateKeyRef: AnyObject?
    // Store private key in keychain
    SecItemDelete(tempAttributes)
    guard SecItemAdd(tempAttributes, &privateKeyRef) == noErr else {
        NSLog("Cannot store private key")
        return
    }
    // Get private key data
    guard let privateKeyData = privateKeyRef as? Data else {
        NSLog("Cannot get private key data")
        return
    }
    let pemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n\(privateKeyData.base64EncodedString())\n-----END RSA PRIVATE KEY-----\n"
    // Delete private key in keychain
    SecItemDelete(tempAttributes)
    let privateKeyBuffer = BIO_new(BIO_s_mem())
    pemPrivateKey.data(using: .utf8)!.withUnsafeBytes({ (bytes: UnsafePointer<Int8>) -> Void in
        BIO_puts(privateKeyBuffer, bytes)
    })
    let privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, nil, nil, nil)
    // !!! Remove in production: Print private key
    PEM_write_PrivateKey(stdout, privateKey, nil, nil, 0, nil, nil)
    // Check if private key matches certificate
    guard X509_check_private_key(certificate, privateKey) == 1 else {
        NSLog("Private key does not match certificate")
        return
    }
    // Set OpenSSL parameters
    OPENSSL_add_all_algorithms_noconf()
    ERR_load_crypto_strings()
    // Create P12 keystore
    let passPhrase = UnsafeMutablePointer(mutating: ("" as NSString).utf8String)
    let name = UnsafeMutablePointer(mutating: ("SSL Certificate" as NSString).utf8String)
    guard let p12 = PKCS12_create(passPhrase, name, privateKey, certificate, nil, 0, 0, 0, 0, 0) else {
        NSLog("Cannot create P12 keystore:")
        ERR_print_errors_fp(stderr)
        return
    }
    // Save P12 keystore
    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 {
        NSLog("Cannot open file handle: \(path)")
        return
    }
    let p12File = fdopen(fileHandle.fileDescriptor, "w")
    i2d_PKCS12_fp(p12File, p12)
    fclose(p12File)
    fileHandle.closeFile()
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38317727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档