在钥匙串中存储.p12证书以供以后使用 [英] Storing a .p12 certificate in keychain to use later

查看:282
本文介绍了在钥匙串中存储.p12证书以供以后使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试按照Apple文档在此处处理客户端p12证书:

I am trying to follow the apple docs for dealing with client p12 certificates here:

https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW13

我已经从文件系统成功加载了.p12证书:

I have successfully loaded a .p12 cert from the file system:

- (SecIdentityRef)getClientCertificate:(NSString *) certificatePath {
    SecIdentityRef identity = nil;
    NSData *PKCS12Data = [NSData dataWithContentsOfFile:certificatePath];

    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    CFStringRef password = CFSTR("password");
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
    CFRelease(options);
    CFRelease(password);
    if (securityError == errSecSuccess) {
        NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        identity = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
    } else {
        NSLog(@"Error opening Certificate.");
    }

    return identity;
}

然后我获得该身份的证书:

I then get the certificate for that identity:

- (CFArrayRef)getCertificate:(SecIdentityRef) identity {
    SecCertificateRef certificate = nil;

    SecIdentityCopyCertificate(identity, &certificate);
    SecCertificateRef certs[1] = { certificate };



    CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL);

    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;

    OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &myTrust);
    if (status == noErr) {
        NSLog(@"No Err creating certificate");
    } else {
        NSLog(@"Possible Err Creating certificate");
    }
    return array;
}

但是我真正想做的是将证书(或身份)存储在我的应用程序钥匙串中,这样我就不会从文件系统中读取它了.

But what I really want to do is store the certificate (or the identity) in my apps keychain so I am not reading it from the file system.

几个问题:

  1. 我应该存储哪个?证书还是身份?
  2. 如何存储和检索它?

上面的链接讨论了获取和使用持久性钥匙串引用",这使我感到非常困惑.

The link above talks about 'Getting and Using Persistent Keychain References' which is very confusing to me.

它还讨论了在钥匙串中查找证书",但它提到使用证书的名称来查找它.我不确定'名字'的来源.

It also talks about 'Finding a Certificate In the Keychain', but it mentions using the name of the certificate to find it. I am not sure where the 'name' comes from.

推荐答案

  1. 我应该存储哪个?证书还是身份?

这取决于您正在执行的操作,以及您是否需要设备上的私钥进行身份验证. SecIdentityRef包含证书和私钥.如果您使用.p12文件进行身份验证,则可能要存储和使用完整身份.如果您只需要证书,那么我不会首先将完整的.p12加载到驱动器上,因为它包含私钥.

It depends on what you are doing, and whether you need the private key on your device for authentication. A SecIdentityRef contains the certificate and private key. If you are using the .p12 file for authentication, then you likely want to store and use the full identity. If you only need the certificate, then I wouldn't be loading the full .p12 onto the drive in the first place, as it contains the private key.

  1. 如何存储和检索它?

我建议将您的身份(或证书)存储在钥匙串中,并使用kSecAttrLabel作为查询的唯一参考.

I would recommend storing your identity (or certificate) in the keychain, and using kSecAttrLabel as a unique reference for querying.

您需要查看的文档是存储身份钥匙串中,它会将您定向到存储一个钥匙串中的证书,并概述了存储身份和证书之间所需的一些细微差别.

The documentation you need to look at is Storing an Identity in the Keychain, which directs you to Storing a Certificate in the Keychain and outlines some minor differences required between storing an identity and certificate.

操作如下(根据上面的链接改编):

This is done as follows (adapted from the links above):

保存到钥匙串

// Create a query (with unique label for reference later)
NSDictionary* addquery = @{ (id)kSecValueRef:   (__bridge id)identity,
                            (id)kSecClass:      (id)kSecClassIdentity,
                            (id)kSecAttrLabel:  @"My Identity",
                           };

// Add the identity to the keychain
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addquery, NULL);
if (status != errSecSuccess) {
    // Handle the error
}

从钥匙串加载

// Query the keychain for your identity
NSDictionary *getquery = @{ (id)kSecClass:     (id)kSecClassIdentity,
                            (id)kSecAttrLabel: @"My Identity",
                            (id)kSecReturnRef: @YES,
                            };

// Retrieve the identity from the keychain
SecIdentityRef identity = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)getquery,
                                      (CFTypeRef *)&identity);
if (status != errSecSuccess) { <# Handle error #> }
else                         { <# Use identity #> }

if (identity) { CFRelease(identity); } // After you are done with it

正如RyanR所提到的,您还可以在保存钥匙串项目后为其创建持久引用,然后将其保存到文件中.我建议将[kSecReturnPersistentRef][3]添加到您的addquery中以实现此目的.

As RyanR mentioned, you can also create a persistent reference to the keychain item once it has been saved, and then save that to file. I would recommend adding [kSecReturnPersistentRef][3] to your addquery to achieve this.

这篇关于在钥匙串中存储.p12证书以供以后使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆