简体   繁体   中英

Converting a PrivateKey (SecRefKey) into NSData or Base64

I have a p12 file, from which I extract the PrivateKey, PublicKey both as SecKeyRef and the certificate as SecCertificateRef.

The P12 file have a ECDSA PrivateKey that I need to use to sign data (ECC).

So I'm using a suggested library: https://github.com/ricmoo/GMEllipticCurveCrypto

But I need to feed the library with the keys on Base64 or NSData, I can't feed SecKeyRef. I managed to extract the NSData for the publicKey using the methods provided here , it works.

But I can't find any way to convert a SecRefKey that points to a privateKey to NSData. Any ideas on how to do this, OR, sign and verify data in iOS using ECC with SecKeyRefs.


For reference, this method converts the P12 into 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;
    }
}

Looks like you simply need to use 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)

Note that CFDataRef is toll-free bridged to NSData , so you can easily convert them.

To export a private key for SEC, you need to retrieve SecKey and convert it to base64 (and format the result with 64 characters max per line. Here the Swift 5 code:

var keyResult: CFTypeRef?
var statusCode = SecItemCopyMatching(attributes as CFDictionary, &keyResult)
if statusCode == noErr && keyResult != nil {
       if let privateKey = SecKeyCopyExternalRepresentation(keyResult as! SecKey, nil) as Data? {
            print("Private Key: \((privateKey.base64EncodedString()))")
       }
       return (keyResult as! SecKey)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM