2010-11-18 5 views
11

Ho un server socket TCP e voglio fare quanto segue w/o utilizzando SSL:inviare la chiave pubblica RSA per iphone e utilizzarla per cifrare

  1. Nel server, fanno coppia di chiavi RSA (So come per fare ciò utilizzando la libreria crittografica di openssl)
  2. Sul server, inviare la chiave pubblica a iphone e mantenere la chiave privata.
  3. Su client (iphone), si desidera crittografare un messaggio utilizzando la chiave pubblica, utilizzando SecKeyEncrypt.
  4. Sul server, decrittografare il messaggio.

Il messaggio è abbastanza breve in modo che il risultato di riempimento PKCS1 si adatti a 128 byte.

Non so come fare 2 ~ 4. Qualcuno lo sa?

+0

Non una domanda, per quanto posso vedere. –

+0

Mi dispiace Greg. Ho appena aggiunto una domanda. –

+0

Questo non sarà sicuro senza SSL; sarà soggetto a un attacco [man in the middle] (http://en.wikipedia.org/wiki/Man_in_the_middle_attack). – cobbal

risposta

18

Questo dovrebbe fare ciò che stai chiedendo: crittografa i dati con la chiave pubblica del server. Non è soggetto agli attacchi MITM, a meno che l'attaccante non abbia una copia della chiave privata e la sua password (comunicare via non SSL, tuttavia, lo è ancora, ma i dati che crittografate con la chiave pubblica legittima del server saranno quasi impossibili da decifrare) .

L'ho lazzato insieme dai documenti di Apple, questo sito, i forum degli sviluppatori Apple e probabilmente altrove. Quindi grazie a tutti ho aggiunto il codice! Questo codice presuppone diverse cose:

  1. Hai già generato le vostre coppie di chiavi RSA (sto usando una chiave a 4096 bit e sembra abbastanza veloce) e, utilizzando la chiave privata, ha creato una codifica DER certificato chiamato "cert.cer" che hai inserito nel pacchetto di risorse della tua app (ovviamente, puoi anche scaricare il certificato dal tuo server, ma poi sarai nuovamente aperto agli attacchi MITM). Per impostazione predefinita, OpenSSL genera un certificato codificato PEM, quindi è necessario convertirlo con "openssl x509 -in cert.pem -inform PEM -out cert.cer -outform DER". iOS barf su PEM. Il motivo per cui utilizzo un certificato è in realtà più semplice da utilizzare e supportato in iOS. Usare solo la chiave pubblica non è (anche se può essere fatto).

  2. Hai aggiunto Security.framework al progetto e si #import <Sicurezza/Security.h>.

/* Restituisce un NSData del testo cifrato, o nullo se la crittografia non ha avuto successo.
è del certificato X.509 come NSData (da dataWithContentsOfFile :, ad esempio) */

+(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 per "Liberare il quinto piano di sicurezza!" – rob5408

+0

ciao scaba, ho un file public.key dal server JAVA, ora ho bisogno di criptare la mia password usando quella chiave in ios sdk ... non riesco a leggere il file di estensione .key in ios. – Apple

+0

Tapan: è necessario utilizzare una chiave codificata DER. Verifica che il tuo public.key sia codificato DER, altrimenti dovrai convertirlo per usarlo. Vedi il mio numero 1 qui sopra. – scaba

1

Beh, suppongo che avresti bisogno di pubblicare la tua chiave pubblica nel mondo esterno (l'iPhone nel tuo caso). Per fare il miglior modo è di pubblicare un certificato contenente la tua chiave pubblica, e l'app per iPhone può scaricarlo. Quindi l'applicazione iPhone può utilizzare il principio di PGP per crittografare i dati con un algoritmo simmetrico (come AES) e crittografare il simmetrico con la chiave pubblica. L'applicazione nel server riceve il messaggio, decrittografa la chiave simmetrica con la sua chiave privata e quindi decrittografa i dati crittografati con la chiave simmetrica così ottenuta.

Ma, come ha detto cobbal, chiunque può intercettare il messaggio tra il server e l'iPhone e può cambiare, e il server non saprebbe se è 'in realtà' ricevuto i dati da iPhone, a meno che non si firma utilizzando un certificato SSL (cioè crittografare l'hash del metodo con la chiave privata dell'iPhone).

Il mio suggerimento è, utilizzare l'applicazione di terze parti availale piuttosto che farlo da soli, in quanto potrebbero essere un po 'falso nell'implementazione. PGP è una libreria pubblica disponibile, puoi usarla.