get SecKeyRef from base64 coded string

2020-02-09 04:04发布

问题:

I'm working on an iOS app and I get a base64 coded public key such as:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3gn+tJ1+PbP0GHa6hmM35WsVyibpypWAwRuBYY4MGfh3VWoXgiyiLo5HJTW1eR9BUFq3z+yOG1rwzSabZ8I4zneWm0kH7xErSjNrMbmjirbL7e6TQNa1ujP/x4x9XVbqf3vIsNVs19kn/qSX/HGzd5Ct3TGAo0AT0T4JwkCfciwIDAQAB

I'd like to encode some text with this public key, but I cannot find a way to convert this string to a useful public key.

What do I need to do?

回答1:

First, you must base64 decode your NSString to NSData: See this answer for solutions. If you are developing for iOS 7, you can use initWithBase64EncodedString::options.

Once you have the string decoded as NSData, you can attempt to create a certificate from it. The format of the certificate you received matters - you can use DER (which is common) or PKCS12. You're likely to be getting it as DER, so that's what I'll assume you need guidance on.

Create a certificate and policy:

SecCertificateRef   cert    = NULL;
SecPolicyRef        policy  = NULL;

cert = SecCertificateCreateWithData(kCFAllocatorDefault, data);
policy = SecPolicyCreateBasicX509();

If the cerificate data was in an incorrect format when passed to SecCertificateCreateWithData you will get a NULL result.

At this point you have the certificate, but not the public key. To obtain the public key you must create a trust reference and evaluate the trust of the certificate.

OSStatus        status      = noErr;
SecKeyRef       *publicKey  = NULL;
SecTrustRef     trust       = NULL;
SecTrustResultType  trustType   = kSecTrustResultInvalid;

if (cert != NULL){
    SecCertificateRef   certArray[1] = {cert};
    certs = CFArrayCreate(kCFAllocatorDefault, (void *)certArray, 1, NULL);
    status = SecTrustCreateWithCertificates(certs, policy, &trust);

    if (status == errSecSuccess){
        status = SecTrustEvaluate(trust, &trustType);

        // Evaulate the trust.
        switch (trustType) {
            case kSecTrustResultInvalid:
            case kSecTrustResultConfirm:
            case kSecTrustResultDeny:
            case kSecTrustResultUnspecified:
            case kSecTrustResultFatalTrustFailure:
            case kSecTrustResultOtherError:
                break;
            case kSecTrustResultRecoverableTrustFailure:
                *publicKey = SecTrustCopyPublicKey(trust);
                break;
            case kSecTrustResultProceed:
                *publicKey = SecTrustCopyPublicKey(trust);
                break;
        }

    }
}

If everything went well, you should now have a populated SecKeyRef with the public key. If it didn't go well, you will have a NULL SecKeyRef and an OSStatus indicating what went wrong. SecBase.h in the Security framework gives more detailed information on those error codes.

Now that you have a SecKeyRef with a public key, using it to encrypt data with a corresponding private key is covered well by the programming guide.

Note that you will have to release the things you allocated above (policy, certs) using ARC or CFRelease.



标签: ios security rsa