2012-03-26 6 views
6

Estoy intentando construir un servidor HTTPS en una aplicación iOS, para actuar como un proxy entre mi aplicación web y mi servidor externo.Certificado de identidad SSL para ejecutar un servidor HTTPS en iOS

He logrado hacer un servidor HTTP escuchando un socket, ya sea gracias a CFSocketRef o usando la biblioteca GCDAsyncSocket. tengo también tener éxito al hacer una aplicación de Mac que ejecuta un servidor HTTPS, usando la biblioteca GCDAsyncSocket y gracias a mi método "SecureSocket:" por debajo del cual asegura la conexión:

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 
{ 
    // (...) 
    // secure the connection 
    [self secureSocket:newSocket]; 
    // (...) 
} 

- (void)secureSocket:(GCDAsyncSocket *)sock 
{ 
    // The root self-signed certificate I have created 
    NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
    NSData *certData = [[NSData alloc] initWithContentsOfFile:certificatePath]; 
    CFDataRef certDataRef = (CFDataRef)certData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 
    [certData release]; 

    // the "identity" certificate 
    SecIdentityRef identityRef; 
    SecIdentityCreateWithCertificate(NULL, cert, &identityRef); 

    // the certificates array, containing the identity then the root certificate 
    NSArray *certs = [[NSArray alloc] initWithObjects:(id)identityRef, (id)cert, nil]; 

    // the SSL configuration 
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 
    [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 
    [settings setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 
    [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel]; 
    [settings setObject:certs forKey:(NSString *)kCFStreamSSLCertificates]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLIsServer]; 

    [sock startTLS:settings]; 
    [certs release]; 
} 

El certificado que estoy usando es un auto -certificado SSL del servidor firmado que he creado con Keychain Access. Entiendo que tengo que darle al sistema un conjunto de configuración con una matriz que contiene una identidad y un certificado. Y funciona bien en mi aplicación Mac.

El problema es habilitar SSL en el servidor HTTP de mi aplicación iOS. El método "SecIdentityCreateWithCertificate()" que crea la identidad no existe en iOS y no sé cómo crear una identidad de otra manera.

Cómo crear un SecIdentityRef en iOS (para habilitar el lado del servidor SSL)? ¿Perdí algo me gusta almacenar la clave pública/privada en mi aplicación, o alguna otra cosa? Muchas gracias.

+0

Se ha cambiado en CocoaAsyncSocket v7.4, algunas teclas de opción antiguas ahora no están disponibles y arrojarán una excepción. Use GCDAsyncSocketManuallyEvaluateTrust y evalúe en -socket: didReceiveTrust: delegate en su lugar. Ver mi ejemplo en https://gist.github.com/hlung/6432966 – Hlung

Respuesta

4

Voy a publicar una respuesta por separado, ya que los comentarios no son adecuados para compartir códigos.
Esto es lo que yo uso para importar mi PKCS12:

CFArrayRef keyref = NULL; 
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)p12Data, 
             (__bridge CFDictionaryRef)[NSDictionary 
                    dictionaryWithObject:password 
                    forKey:(__bridge id)kSecImportExportPassphrase], 
             &keyref); 

if (sanityChesk != noErr) { 
    NSLog(@"Error while importing pkcs12 [%d]", sanityChesk); 
    return nil; 
} 

NSArray *keystore = (__bridge_transfer NSArray *)keyref; 

El contenido completo p12 estará en el almacén de claves matriz.

+0

mi código aquí utiliza el ARC, de ahí la necesidad de las palabras clave __bridge crípticas;) – pmilosev

+0

que estaba haciendo lo mismo.Obtengo el mismo resultado con su código: _keystore_ array está vacío. Si tiene un mejor resultado con el mismo código, supongo que significa que no genero ni almaceno mis certificados, ¿verdad? Lo que hice fue crear un certificado raíz autofirmado desde Keychain Access, luego almacené los archivos .cer y .p12 en mi paquete de proyecto e intento usarlos sin éxito como puede ver. Gracias por su tiempo, agradezco su ayuda. – Laurent

+0

solo para que funcione ... ¿por qué no intenta exportar algunos de los pares clave/certificado de trabajo (por ejemplo, certificados de desarrollo firmados por Apple)? – pmilosev

0
+0

Ya lo he intentado en realidad, pero no puedo hacerlo funcionar; podría ser la pregunta correcta aquí. He importado mi clave privada (archivo p12) y utilicé la función extractIdentityAndTrust() tal como lo muestra Apple en su enlace, pero siempre obtengo una matriz vacía _items_ que hace que esta función se cuelgue al intentar acceder al primer elemento de la matriz. Alguna idea sobre eso? – Laurent

+0

Si ha utilizado el método 'SecPKCS12Import' devolverá un NSArray que contiene NSDictionaries. La identidad en el diccionario se almacena bajo la clave 'kSecImportItemIdentity', mientras que la cadena de certificados (NSArray nuevamente) se encuentra debajo de la clave 'kSecImportItemCertChain'. Mientras tanto, también estoy buscando una manera de crear la identidad en tiempo de ejecución, ya que no estoy tratando con certificados pre-cargados. Publicaré el resultado aquí si encuentro algo;) – pmilosev

+0

Gracias @pmilosev. Mi problema es que utilizo la función _extractIdentityAndTrust_ como lo muestra Apple en el enlace de arriba, pero la matriz _items_ que obtengo siempre está vacía: 'NSDictionary * optionsDictionary = [NSDictionary dictionaryWithObject: @" myPrivateKeyPassword "forKey: (id) kSecImportExportPassphrase]; Elementos CFArrayRef = CFArrayCreate (NULL, 0, 0, NULL); securityError = SecPKCS12Import (inPKCS12Data, optionsDictionary, y material); ' – Laurent

Cuestiones relacionadas