2012-06-13 19 views
7

Quello che sto cercando di fare è replicare il seguente comando eseguito tramite Terminal su un Mac, ma sul iPhone/a Cocoa:Replicate OpenSSL smime su iPhone/cacao

openssl smime -binary -sign -signer cert.pem -inkey key.pem -in file.txt -out encrypted -outform DER 

dove "criptato" è il file crittografato che risulta dal comando.

Sebbene specifichi 2 chiavi separate (chiave pubblica e privata), è possibile avere questi come un singolo file .p12.

Dopo aver seguito lo snippet this per il cacao per la crittografia di un file utilizzando un certificato .p12, non sono sicuro se questa è la strada giusta da percorrere.

Qual è l'approccio migliore per la replica del comando smime su un iPhone (come da comando Terminale sopra), o non è nemmeno possibile attraverso i metodi disponibili Security.framework/CommonCrypto?

+0

Non so la risposta, ma buona fortuna con la tua applicazione PassKit! –

risposta

3

Per quanto ne so - sei un po 'su un torrente - con la pagaia chiusa nell'appstore.

  • iOS manca CMSEncoderAddSigners, CMSEncoderUpdateContent, CMSEncoderCopyEncodedContent che è necessario per questo.
  • L'uso di openssl o Chilkat non è l'ideale, poiché l'API keychain di iOS non consente più l'accesso alla chiave privata una volta importata.

Ho risolto questo problema in passato sia con openssl che con Chilkat.

In ogni caso tuttavia "memorizzo" una copia della chiave privata - come una volta che entra nel portachiavi - tutto ciò che posso ottenere è un SecKeyRef (è necessario stipulare un accordo/autorizzazione supplementare con apple per essere in grado di rimuoverlo ed essere ancora nell'appstore Reverse engineer di qualsiasi app VPN (ad esempio il ginepro) per vedere i metodi/framework da collegare).

Per openssl: è sufficiente prendere il codice smime.c nelle app di openssl e modificare. Per le cose Chilkat sono molto più semplice:

CkoCert * mine = [identity ckoCert]; 

    assert([mime AddEncryptCert: mine] == YES); 

    for(id cc in backupCerts) { 
     assert([mime AddEncryptCert:cc] == YES); 
    } 

    for(id key in [headers allKeys]) { 
     [mime SetHeaderField:[NSString stringWithFormat:@"%s%@", X_HDR_PREFIX, key] 
         value:[headers objectForKey:key] 
     ]; 
    }; 

    [mime SetBodyFromBinary:data];   
    assert([mime EncryptN] == YES); 

    return [mime GetMimeBytes]; 

e dove il campo di identità ha il 'mantenere la propria cache' imbrogliare:

-(id)initWithPKCS12:(NSData*)pkcs12der password:(NSString *)password { 
    if (password == nil) 
     password = [APPSETTINGS wellKnownPkcsPassword]; 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          password, kSecImportExportPassphrase, 
          nil]; 

    CFArrayRef items; 
    OSStatus status = SecPKCS12Import((__bridge CFDataRef)pkcs12der, 
     (__bridge CFDictionaryRef)options, &items); 

    if (status != noErr) { 
     NSLog(@"PKCS12 importAsDer failed: Error %ld",(long)status); 
     ... 
    } 

    if (!items || CFArrayGetCount(items) < 1) { 
     NSLog(@"PKCS12 importAsDer failed - nothing returned (%ld bytes DER)", 
       (long)[pkcs12der length]); 
     ... 
    } 

    CFDictionaryRef dict0 = (CFDictionaryRef) CFArrayGetValueAtIndex(items, 0); 
    if (!dict0) 
     return nil; 

    SecIdentityRef iRef = (SecIdentityRef) CFDictionaryGetValue(dict0, 
      kSecImportItemIdentity); 
    CFArrayRef cRef = (CFArrayRef) CFDictionaryGetValue(dict0, kSecImportItemCertChain); 

    self = [self initWithIdentityRef:iRef withChainArrayRef:cRef]; 
    CFRelease(items); 

#if TARGET_OS_IPHONE 
    // We lack SecPrivate* on iOS. So we cheat a bit - rather than 
    // use the keychain we limt ourselves to our own *.p12's and 
    // keep a copy of the private key in memory. 
    // 
# ifdef WITH_OPENSSL 

    const unsigned char * ptr = [pkcs12der bytes]; 
    PKCS12 * p12 = d2i_PKCS12(NULL, &ptr, len); 
    char buff[1024]; 

    if (!p12) { 
     NSLog(@"Could not decode PKCS#12: %s", ERR_error_string(ERR_get_error(), buff)); 
     ... 
    }; 

    const char * pass = [password cStringUsingEncoding:NSASCIIStringEncoding]; 

    if (PKCS12_parse(p12, pass, &pkey, &x509, NULL) != 1) { 
     NSLog(@"Could not parse PKCS#12: %s", ERR_error_string(ERR_get_error(), buff)); 
     ... 
    }; 
    .... 
# else 
    ckoCert = [[CkoCert alloc] init]; 

    if (!([ckoCert LoadPfxData:pkcs12der password:[APPSETTINGS wellKnownPkcsPassword]])) { 
     NSLog(@"PKCS12 loadPfxData failed: %@", [ckoCert LastErrorText]); 
     ... 
    } 

    ckoPrivateKey = [ckoCert ExportPrivateKey]; 
# endif // chilkat or openssl 
#endif // iOS 

    return self; 
} 

Attenzione: in precedenza ho spogliato più mngt gestione/errore e/o sostituito da asserisce come altrimenti è diventato un po 'troppo maneggevole.

Grazie,

Dw.