С помощью. сертификат хранилища ключей bks в приложении для iPhone
Я создаю приложение для iPhone, которому требуются хранилища ключей.bks для аутентификации. Я не нашел ничего об этой информации для приложений iOS.
Я хотел бы знать, разрешает ли Apple использовать хранилища ключей в своих приложениях и как начать работу на iOS. Сертификаты создаются с использованием BouncyCastle. Я нашел информацию об этом для Android, но для iOS мне не повезло. Любая помощь будет оценена.
1 ответ
Вы можете экспортировать нужные вам сертификаты из хранилища ключей, как это
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. Мне не повезло с этим, и мне все равно понадобился сертификат в цепочке для ключей, но здесь кое-что об этом.
Обновить:
Как указано в комментариях 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);
}
И последнее, но не менее важное: ссылки на эту тему:
- https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/Reference/reference.html
- https://developer.apple.com/library/ios/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html
- https://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html
- https://github.com/kuapay/iOS-Certificate--Key--and-Trust-Sample-Project
- http://blog.wingsofhermes.org/?p=75