2017-01-19 163 views
2

我有一个p12文件,从中我将PrivateKey,PublicKey都提取为SecKeyRef,将证书提取为SecCertificateRef。将私钥(SecRefKey)转换为NSData或Base64

P12文件具有我需要用来签署数据(ECC)的ECDSA PrivateKey。

所以我使用了一个建议库:https://github.com/ricmoo/GMEllipticCurveCrypto

但我需要养活对Base64编码或NSData的密钥库,我不能养活SecKeyRef。我设法使用提供的here提供的方法提取公钥的NSData,它的工作原理。

但我找不到任何方式将指向私钥的SecRefKey转换为NSData。关于如何做到这一点的任何想法,或者使用ECC和SecKeyRefs在iOS中签署和验证数据。


以供参考,该方法可转换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

是的,我尝试,但后来它崩溃,可能是因为该方法只适用于对称密钥,我敢肯定,我产生了不对称的。 –