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?
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.