2012-06-23 6 views
14

Estoy trabajando en una aplicación iOS5 que facilitará los pagos móviles entre dos usuarios. Como parte del proceso de pago, el remitente y el destinatario deben comunicarse con un servidor. El servidor requiere que ambas partes presenten sus identidades cuando se inicia una prueba de autenticación al conectarse.¿Cómo puedo importar un certificado por programación en el llavero de mi aplicación iOS y pasar la identidad a un servidor cuando sea necesario?

Actualmente, he no modificable el proceso de certificado mediante la utilización de los dos métodos siguientes en mi código:

NSURLConnection Delegado didReceiveAuthenticationChallenge

(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge 
{ 
NSLog(@"Authentication challenge"); 

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

SecIdentityRef myIdentity; 
SecTrustRef myTrust; 
extractIdentityAndTrust(inP12data, &myIdentity, &myTrust); 

SecCertificateRef myCertificate; 
SecIdentityCopyCertificate(myIdentity, &myCertificate); 
const void *certs[] = { myCertificate }; 
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL); 

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent]; 

[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
} 

C Método extractIdentityAndTrust

OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust) 
{ 
OSStatus securityError = errSecSuccess; 

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); 
securityError = SecPKCS12Import(inP12data, options, &items); 

if (securityError == 0) { 
    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); 
} 

return securityError; 
} 

He probado este código varias veces y he tenido éxito. Ahora estoy tratando de seguir adelante y permitir que la identidad adecuada se almacene y luego se recupere del llavero de la aplicación. Mi objetivo es permitir a los usuarios importar sus archivos P12 a través de iTunes File Sharing o Dropbox y guardarlos en el llavero.

He consultado la documentación de Apple para Getting and Using Persistent Keychain References y no he podido averiguar cómo importar la identidad. Su código es un poco confuso para mí ya que usan variables/referencias no declaradas (específicamente la

&persistent_ref 

variable). Si alguien pudiera ayudar a descifrarlo, sería muy apreciado.

TL; DR: ¿Cómo puedo guardar el contenido de un archivo P12 en mi llavero de IOS5 aplicación y recuperarlo más adelante a mano fuera de un método NSURLConnection didReceiveAuthenticationChallenge?

+0

estoy teniendo el mismo problema con mi código de conexión SSL has encontrado una solución a ella? – Radu

+0

hey, ¿pueden ayudarme? Tengo el error EXC_BAD en este punto. ¿Pueden orientar m? SecurityError = SecPKCS12Import (inP12data, options & items); –

+0

@BhavikKama tal vez su referencia al archivo .p12 es incorrecta o utiliza un archivo de certificado no válido. –

Respuesta

6

El siguiente código debe hacer el truco:

NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init]; 
[secIdentityParams setObject:(id)myIdentity forKey:(id)kSecValueRef]; 
OSStatus status = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL); 

interactuar con el llavero pasando en un diccionario de pares de valores clave que desea encontrar o crear. Cada tecla representa una opción de búsqueda o un atributo del elemento en el llavero. Las claves son constantes predefinidas que debe usar según el tipo de datos que se almacenarán. Esas claves se pueden encontrar en el documento de desarrollador de Apple.

Creo que el código fuente de Apple no incluye la asignación de persistentRef. Deberían haber agregado dicha declaración al comienzo del método:

NSData *persistentRef = nil; 

Tenga en cuenta que el uso de la referencia persistente no es obligatorio. El código anterior debería funcionar bien.A medida que Apple lo explica bien:

Puesto que una referencia persistente permanece válida entre invocaciones de su programa y se puede almacenar en el disco, puede utilizar uno para que sea más fácil encontrar un elemento llavero que se necesita en repetidas ocasiones

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

Cuestiones relacionadas