2012-06-13 3 views
7

Что я пытаюсь сделать, это повторить следующую команду запустить через терминал на Mac, но на iPhone/в какао:REPLICATE OpenSSL SMIME команда на iPhone/Cocoa

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

где "зашифрованы" это зашифрованный файл, который является результатом команды.

Хотя в нем указаны 2 отдельных ключа (открытый и закрытый ключ), их можно использовать как один файл .p12.

После того, как this фрагмент какао для шифрования файла с использованием сертификата .p12, я не уверен, что это правильный путь.

Каков наилучший способ для тиражирования команды smime на iPhone (в соответствии с приведенной выше командой терминала), или это вообще невозможно вообще с помощью доступных методов Security.framework/CommonCrypto?

+0

Не знаю ответа, но удачи в приложении PassKit! –

ответ

3

Насколько я знаю - вы немного за рулем - с веслом, запертым в магазине приложений.

  • IOS не хватает CMSEncoderAddSigners, CMSEncoderUpdateContent, CMSEncoderCopyEncodedContent, которые вам нужно для этого.
  • Использование openssl или Chilkat также не является идеальным: поскольку API-интерфейс keychain iOS не дает вам доступа (private) к закрытому ключу после импорта.

Я решил это в прошлом как с opensl, так и с Chilkat.

В каждом случае, однако, я «кеширую» копию закрытого ключа - как только он попадает в цепочку ключей - все, что я могу вернуть, - это SecKeyRef (вам нужно ввести дополнительное соглашение/разрешение с яблоком способный вернуть его обратно и все еще находиться в Appstore. Обращайтесь к любому из приложений VPN (например, можжевельника), чтобы увидеть, как методы/рамки будут связаны).

Для openssl - просто возьмите код smime.c в приложениях openssl и измените. Для Чилкэт вещи намного проще:

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]; 

и где поле идентичности имеет «держать свой собственный кэш» чита:

-(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; 
} 

Предупреждение: в выше я уже раздели большинство MNGT управления/ошибки и/или заменил его утверждениями, поскольку в противном случае он получил слишком много урона.

С благодарностью,

Dw.

Смежные вопросы