2010-11-18 10 views
11

Tengo un servidor de socket TCP y quiero hacer lo siguiente w/o el uso de SSL:enviar la clave pública RSA para iPhone y utilizarlo para cifrar

  1. En el servidor, haga RSA par de claves (sé cómo para hacer esto usando la biblioteca de cifrado de openssl)
  2. En el servidor, envíe la clave pública a iphone y conserve la clave privada.
  3. En el cliente (iphone), desea encriptar un mensaje usando la clave pública, utilizando SecKeyEncrypt.
  4. En el servidor, descifrar el mensaje.

El mensaje es lo suficientemente corto para que el resultado acolchado PKCS1 se ajuste a 128 bytes.

No sé cómo hacer 2 ~ 4. ¿Alguien sabe?

+0

No es una cuestión por lo que puedo ver. –

+0

Lo siento Greg. Acabo de agregar una pregunta. –

+0

Esto no será seguro sin SSL; estará sujeto a un [hombre en el ataque medio] (http://en.wikipedia.org/wiki/Man_in_the_middle_attack). – cobbal

Respuesta

18

Esto debería hacer lo que está pidiendo: encripta los datos con la clave pública del servidor. No está sujeto a ataques MITM, a menos que el atacante tenga una copia de su clave privada y su contraseña (comunicarse a través de un sistema no SSL, sin embargo, aún lo es, pero los datos que encripte con la clave pública legítima del servidor serán casi imposibles de descifrar) .

Construí esto en conjunto con los documentos de Apple, este sitio, los foros de desarrolladores de Apple y probablemente en otros lugares. ¡Así que gracias a todos los que he descifrado el código! Este código se supone varias cosas:

  1. Usted ya ha generado sus pares de claves RSA (estoy usando una clave de 4096 bits y parece lo suficientemente rápida) y, utilizando la clave privada, crea un DER codificada certificado llamado "cert.cer" que coloca en su paquete de recursos de su aplicación (obviamente, también puede descargar el certificado de su servidor, pero luego está abierto a ataques MITM de nuevo). De forma predeterminada, OpenSSL genera un certificado codificado PEM, por lo que debe convertirlo con "openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER". iOS se descartará en PEM. La razón por la que uso un certificado es que en realidad es más fácil trabajar con él y es compatible con iOS. Usar solo la clave pública no es (aunque se puede hacer).

  2. Ha agregado Security.framework a su proyecto y #import <Security/Security.h>.

/* Devuelve un NSData del texto cifrado, o nil si el cifrado no tuvo éxito.
Toma el certificado X.509 como NSData (de dataWithContentsOfFile :, por ejemplo) */

+(NSData *)encryptString:(NSString *)plainText withX509Certificate:(NSData *)certificate { 

    SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificate); 
    SecPolicyRef policy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    OSStatus status = SecTrustCreateWithCertificates(cert, policy, &trust); 

    SecTrustResultType trustResult; 
    if (status == noErr) { 
     status = SecTrustEvaluate(trust, &trustResult); 
    } 

    SecKeyRef publicKey = SecTrustCopyPublicKey(trust); 

    const char *plain_text = [plainText UTF8String]; 
    size_t blockSize = SecKeyGetBlockSize(publicKey); 
    NSMutableData *collectedCipherData = [NSMutableData data]; 

    BOOL success = YES; 
    size_t cipherBufferSize = blockSize; 
    uint8_t *cipherBuffer = malloc(blockSize); 

    int i; 
    for (i = 0; i < strlen(plain_text); i += blockSize-11) { 
     int j; 
     for (j = 0; j < blockSize-11 && plain_text[i+j] != '\0'; ++j) { 
      cipherBuffer[j] = plain_text[i+j]; 
     } 

     int result; 
     if ((result = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, cipherBuffer, j, cipherBuffer, &cipherBufferSize)) == errSecSuccess) { 
      [collectedCipherData appendBytes:cipherBuffer length:cipherBufferSize]; 
     } else { 
      success = NO; 
      break; 
     } 
    } 

    /* Free the Security Framework Five! */ 
    CFRelease(cert); 
    CFRelease(policy); 
    CFRelease(trust); 
    CFRelease(publicKey); 
    free(cipherBuffer); 

    if (!success) { 
     return nil; 
    } 

    return [NSData dataWithData:collectedCipherData]; 
} 
+3

+1 por "¡Libere el marco de seguridad de cinco!" – rob5408

+0

hello scaba, tengo el archivo public.key del servidor JAVA, ahora necesito encriptar mi contraseña usando esa clave en ios sdk ... no puedo leer el archivo de extensión .key en ios. – Apple

+0

Tapan: debe usar una clave codificada DER. Verifique que su clave public.key tenga codificación DER, de lo contrario, deberá convertirla para usarla. Ver mi # 1 arriba. – scaba

1

Bueno, supongo que tendrías que publicar tu clave pública en el mundo exterior (el iPhone en tu caso). Hacer la mejor manera es publicar un certificado que conatining su clave pública, y la aplicación de iPhone puede descargarlo. Entonces la aplicación de iPhone puede utilizar el principio de PGP para cifrar los datos con un algo simétrico (como AES) y encriptar el simétrico con la clave pública. La aplicación en el servidor recibiría el mensaje, descifraría la clave simétrica con su clave privada, y luego descifraría los datos cifrados con la clave simétrica así obtenida.

Pero como dijo cobbal, cualquiera puede interceptar el mensaje entre el servidor y el iPhone y puede cambiarlo, y el servidor no sabría si realmente ha recibido los datos del iPHone, a menos que lo firme usando un certificado SSL (es decir, cifra el hash del método con la clave privada del iPhone).

Mi sugerencia es utilizar una aplicación de terceros disponible en lugar de hacerlo usted mismo, ya que pueden existir algunos fallos en la implementación. PGP es una biblioteca pública disponible, puede usarla.

Cuestiones relacionadas