2017-01-19 32 views
2

У меня есть файл p12, из которого я извлекаю PrivateKey, PublicKey как SecKeyRef, так и сертификат как SecCertificateRef.Преобразование PrivateKey (SecRefKey) в NSData или Base64

В файле P12 есть ECDSA PrivateKey, который мне нужно использовать для подписи данных (ECC).

Поэтому я использую предложенную библиотеку: https://github.com/ricmoo/GMEllipticCurveCrypto

Но мне нужно кормить библиотеки с ключами на Base64 или NSData, я не могу кормить SecKeyRef. Мне удалось извлечь NSData для publicKey, используя предоставленные методы here, он работает.

Но я не могу найти способ конвертировать SecRefKey, который указывает на privateKey на NSData. Любые идеи о том, как это сделать, ИЛИ, подписывать и проверять данные в iOS, используя ECC с SecKeyRefs.


Для сравнения, этот метод преобразует P12 в IOS SecRefs:

- (BOOL)storeDetailsForP12CertificateData:(NSData *)certData password:(NSString*)pass identifier:(NSString*)identifier{  
    SecKeyRef publicKey, privateKey; 
    SecCertificateRef certRef; 

    //Extract keys and Certificate 
    NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; 
    [options setObject:pass forKey:(id)kSecImportExportPassphrase]; 

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 
    OSStatus securityError = SecPKCS12Import((CFDataRef) certData, 
              (CFDictionaryRef)options, &items); 

    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); 
    SecIdentityRef identityApp = 
    (SecIdentityRef)CFDictionaryGetValue(identityDict, 
             kSecImportItemIdentity); 

    assert(securityError == noErr); 

    //get private key 
    SecIdentityCopyPrivateKey(identityApp, &privateKey); 

    //get certificate 
    SecIdentityCopyCertificate(identityApp, &certRef); 

    //evaluate certificate. 
    CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &certRef, 1, NULL); 
    SecPolicyRef policy = SecPolicyCreateBasicX509(); 
    SecTrustRef trust; 
    SecTrustCreateWithCertificates(certs, policy, &trust); 
    (CFRelease(certs)); 
    SecTrustResultType trustResult; 
    SecTrustEvaluate(trust, &trustResult); 

    //get publickey 
    publicKey = SecTrustCopyPublicKey(trust); 

    //clean memory 
    (CFRelease(trust)); 
    (CFRelease(policy)); 

    if (!publicKey || !privateKey || !certRef) { 
     return NO; 
    } else { 
     KeyData *details = [[KeyData alloc] init]; 
     details.publicKey = publicKey; 
     details.privateKey = privateKey; 
     details.certificate = certRef; 
     details.fileData = certData; 

     return YES; 
    } 
} 

ответ

0

Похоже, вы просто должны использовать SecKeyCopyExternalRepresentation:

/*! 
    @function SecKeyCopyExternalRepresentation 
    @abstract Create an external representation for the given key suitable for the key's type. 
    @param key The key to be exported. 
    @param error On error, will be populated with an error object describing the failure. 
    See "Security Error Codes" (SecBase.h). 
    @result A CFData representing the key in a format suitable for that key type. 
    @discussion This function may fail if the key is not exportable (e.g., bound to a smart card or Secure Enclave). 
    The format in which the key will be exported depends on the type of key: 
    * kSecAttrKeyTypeRSA     PKCS#1 format 
    * kSecAttrKeyTypeECSECPrimeRandom SEC1 format (www.secg.org) 
*/ 
CFDataRef _Nullable SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) 

Обратите внимание, что CFDataRef является бесплатным мостовая до NSData, так что вы можете легко их конвертировать.

+0

Есть ли способ конвертировать данные обратно в SecKeyRef? –

+0

@SerenadeX, быстрый поиск дает мне 'SecKeyCreateWithData'. –

+0

Да, я пытаюсь это сделать, но потом он падает, вероятно, потому, что этот метод работает только с симметричными клавишами, и я уверен, что я генерирую асимметричные. –