Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using . bks keystores certificate in iPhone app

I am building an iPhone app that needs .bks keystores to authenticate. I did not find anything about this information for iOS apps .

I would like to know if apple permits the use of keystores in their apps and how to get started on iOS. The certificates are created using BouncyCastle. I DID find information about it for android but for iOS i had no luck. Any help will be appreciated.

like image 556
Radu Avatar asked Nov 04 '22 16:11

Radu


1 Answers

You could export the certificate(s) you need from the keystore like this

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

You may need to tell keytool about the store type and store provider, look here.

You can read that .cer file into the iOS keychain with this code:

- (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);
}

When you need the certificate you can get from the keychain like this:

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

    return (SecCertificateRef) ref;
}

The clientCertificateQuery looks like this.

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;
}

There is also a function to read a PCKS12 store (you would still need to transform your BKS store into that format). It's called SecPKCS12Import and with it you won't need to import the cert into your iOS keychain. I had no luck with it and needed the cert in the keychain anyway, but here is something about this.

Update:

As camdaochemgio pointed out in the comments using above method is not recommend when including a certificate that contains secret information (like private keys) in an app. Because the .cer file is not protected and can easily be extracted from the .ipa.

PKCS#P12 supports password protection so it's better to use this.

You can covert your keystore to PKCS#P12 like this (taken from here):

 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

Then you can load the .p12 file like this (credits go here)

// 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);
}

Last but not least some links regarding this topic:

  • 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
like image 171
sofacoder Avatar answered Nov 15 '22 05:11

sofacoder