从证书中获取 public/private 密钥

Get public/private key from certificate

我尝试从设备上保存的证书中获取 public 或私钥。 我正在使用这种方法:

    - (SecKeyRef)publicKeyFromFile:(NSString *)path
{
    NSData * certificateData = [[NSData alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path]];

    if (certificateData != nil && certificateData.bytes != 0) {

        CFDataRef cfDataPath = CFDataCreate(NULL, [certificateData bytes], [certificateData length]);
        SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, cfDataPath);

        if (certificateFromFile) {
            SecPolicyRef secPolicy = SecPolicyCreateBasicX509();
            SecTrustRef trust;
            SecTrustCreateWithCertificates( certificateFromFile, secPolicy, &trust);
            SecTrustResultType resultType;
            SecTrustEvaluate(trust, &resultType);
            SecKeyRef publicKeyObj = SecTrustCopyPublicKey(trust);

            return publicKeyObj;
        }
    }

    return nil;
}

cfDataPath 中有数据,但 certificateFromFile 始终为 nil...

有谁知道问题出在哪里?

Apple 文档指的是:

Obtaining a SecKeyRef Object for Public Key Cryptography Extracting Keys from the Keychain If you are using existing public and private keys from your keychain, read Certificate, Key, and Trust Services Programming Guide to learn how to retrieve a SecKeychainItemRef object for that key. Once you have obtained a SecKeychainItemRef, you can cast it to a SecKeyRef for use with this API. Importing Existing Public and Private Keys Importing and exporting public and private key pairs is somewhat more complicated than generating new keys because of the number of different key formats in common use. This example describes how to import and export a key pair in PEM (Privacy Enhanced Mail) format.

阅读更多:https://developer.apple.com/library/mac/documentation/Security/Conceptual/SecTransformPG/SigningandVerifying/SigningandVerifying.html and https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/01introduction/introduction.html#//apple_ref/doc/uid/TP40001358

试试这个:

  -(BOOL)trustCertFromChallenge:(NSURLAuthenticationChallenge *)challenge
 {
SecTrustResultType trustResult;
SecTrustRef trust = challenge.protectionSpace.serverTrust;
OSStatus status = SecTrustEvaluate(trust, &trustResult);

//DLog(@"Failed: %@",error.localizedDescription);
//DLog(@"Status: %li | Trust: %@ - %li",(long)status,trust,(long)trustResult);

if (status == 0 && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) {

    SecKeyRef serverKey = SecTrustCopyPublicKey(trust);

    NSString *certPath = [[NSBundle mainBundle] pathForResource:@"MYCert" ofType:@"der"];
    NSData *certData = [NSData dataWithContentsOfFile:certPath];
    SecCertificateRef localCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);

    SecKeyRef localKey = NULL;
    SecTrustRef localTrust = NULL;
    SecCertificateRef certRefs[1] = {localCertificate};
    CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *)certRefs, 1, NULL);
    SecPolicyRef policy = SecPolicyCreateBasicX509();
    OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &localTrust);

    if (status == errSecSuccess)
        localKey = SecTrustCopyPublicKey(localTrust);

    CFRelease(localTrust);
    CFRelease(policy);
    CFRelease(certArray);

     if (serverKey != NULL && localKey != NULL && [(__bridge id)serverKey isEqual:(__bridge id)localKey])
        return YES;
    else
        return NO;
}

//DLog(@"Failed: %@",error.localizedDescription);

return NO;
  }

按照已接受的答案了解更多详情: