5

我正在构建一个需要 .bks 密钥库进行身份验证的 iPhone 应用程序。我没有找到任何关于 iOS 应用程序的信息。

我想知道苹果是否允许在他们的应用程序中使用密钥库以及如何开始使用 iOS。证书是使用 BouncyCastle 创建的。我确实为 android 找到了有关它的信息,但对于 iOS,我没有运气。任何帮助将不胜感激。

4

1 回答 1

2

您可以像这样从密钥库中导出所需的证书

keytool -exportcert -keystore <keystore> -file some.cer

您可能需要告诉 keytool 有关商店类型和商店提供者的信息,请看这里

您可以使用以下代码将该 .cer 文件读入 iOS 钥匙串:

- (void) importCertToKeyChain: (NSData *) data
{
    // Delete the old certificate, otherwise SecItemAdd complains.
    OSStatus oss = SecItemDelete((__bridge CFDictionaryRef)([self clientCertificateQuery]));

    // Import the certificate
    SecCertificateRef certRef = NULL;
    certRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(data));

    NSDictionary *att = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)(kSecClassCertificate), kSecClass, (__bridge id) certRef, kSecValueRef, nil];

    oss = SecItemAdd((__bridge CFDictionaryRef)(att), NULL);
}

当您需要证书时,您可以像这样从钥匙串中获取:

- (SecCertificateRef) getCertFromKeyChain
{
    CFTypeRef ref = NULL;
    SecItemCopyMatching((__bridge CFDictionaryRef)([self clientCertificateQuery]), &ref);

    return (SecCertificateRef) ref;
}

clientCertificateQuery 看起来像这样。

static NSString *clientCertSubject = @"TestSubjectClient";

-(NSMutableDictionary *) clientCertificateQuery
{
    NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
    [query setObject:(__bridge id) kSecClassCertificate forKey:(__bridge id)kSecClass];
    [query setObject:clientCertSubject forKey:(__bridge id<NSCopying>)(kSecMatchSubjectContains)];
    [query setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
 id)kSecAttrKeyType];
    return query;
}

还有一个读取 PCKS12 存储的功能(您仍然需要将 BKS 存储转换为该格式)。它被调用SecPKCS12Import,您无需将证书导入您的 iOS 钥匙串。我没有运气,无论如何都需要钥匙串中的证书,但这里有一些关于 this的内容。

更新:

正如 camdaochemgio 在评论中指出的那样,在应用程序中包含包含秘密信息(如私钥)的证书时,不建议使用上述方法。因为 .cer 文件不受保护,可以轻松地从 .ipa 中提取。

PKCS#P12 支持密码保护,所以最好使用它。

您可以像这样将您的密钥库转换为 PKCS#P12(取自此处):

 keytool -importkeystore -srckeystore KEYSTORE.jks -destkeystore KEYSTORE.p12 -srcstoretype BKS -deststoretype PKCS12 -srcstorepass mysecret -deststorepass mysecret -srcalias myalias -destalias myalias -srckeypass mykeypass -destkeypass mykeypass -noprompt

然后你可以像这样加载 .p12 文件(学分在这里

// Load Certificate
NSString *path = [[NSBundle mainBundle] pathForResource:@"cert" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;

// Only password based PKCS#12 blobs are supported
CFStringRef password = CFSTR("Password");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

// The import
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import(inP12data, options, &items);

if (securityError == 0)
{
    // Exploring the content
    CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
    const void *tempIdentity = NULL;
    tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
    *identity = (SecIdentityRef)tempIdentity;
    const void *tempTrust = NULL;
    tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
    *trust = (SecTrustRef)tempTrust;
}

if (options) {
    CFRelease(options);
}

最后但并非最不重要的一些关于这个主题的链接:

于 2013-09-17T20:17:02.290 回答