Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get SecKeyRef from base64 coded string

Tags:

security

ios

rsa

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?

like image 360
Frank Avatar asked Sep 07 '12 14:09

Frank


1 Answers

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.

like image 119
quellish Avatar answered Oct 29 '22 20:10

quellish