Marylia Gutierrez
Marylia Gutierrez

Reputation: 769

createKeychainValue from a NSString

I'm trying to add a certificate to the keychain. I saw several posts that make this from a file, but I want to create one from a NSString.

My NSString is on RSA - 64base and is like:

-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgIJAL8qgXMVVVhPMA0GCSqGSIb3DQEBBQUAMGwxCzAJBgNVBAYTAkJSMRIw
...
FT70at8bty9ocDaXuI3j6mfw2SI=
-----END CERTIFICATE-----

And I'm trying to do something like this:

+ (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];

    [searchDictionary setObject:(__bridge id)kSecClassCertificate forKey:(__bridge id)kSecClass];

    NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
    [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric];
    [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount];
    [searchDictionary setObject:SERVICE_NAME forKey:(__bridge id)kSecAttrService];
    return searchDictionary;
}


+ (BOOL)createKeychainValue:(NSString *)certificado forIdentifier:(NSString *)identifier {
    NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];

    NSData *certificadoData = [certificado dataUsingEncoding:NSUTF8StringEncoding];
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certificadoData);

    [dictionary setObject:(__bridge id)(cert) forKey:(__bridge id<NSCopying>)(kSecValueRef)];

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);

    CFRelease(cert);

    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}

But is getting back the cert as nil. Probably because my certificate is PEM and I need a DER. How can I convert? I'm using openssl on my project.

Upvotes: 4

Views: 987

Answers (2)

Marylia Gutierrez
Marylia Gutierrez

Reputation: 769

The function that works for me and created the SecCertificateRef was:

+ (NSData *)derFromPem:(NSString *)pem {

    BIO *certBio = BIO_new(BIO_s_mem());
    BIO_write(certBio, [pem UTF8String], strlen([pem UTF8String]));
    X509 *x = PEM_read_bio_X509(certBio,NULL,0,NULL);
    BIO *outBio = BIO_new(BIO_s_mem());
    i2d_X509_bio(outBio, x);

    int len = BIO_pending(outBio);
    char *out = calloc(len + 1, 1);
    int i = BIO_read(outBio, out, len);

    return [NSData dataWithBytes:out length:i];
}

Upvotes: 3

Elden
Elden

Reputation: 670

Convert RSA public key from PEM to DER:

UPDATE

- (NSData *)derFromPem:(NSString *)pem
{
    if (pem.length == 0) {
        return nil;
    }

    NSData *result = nil;
    const char *pem_str = [pem UTF8String];

    BIO *bio;
    RSA *rsa;
    // X509 *x509;

    bio = BIO_new_mem_buf(pem_str, strlen(pem_str));

    if (bio) {
        rsa = PEM_read_bio_RSAPublicKey(bio, &rsa, NULL, NULL);
        // x509 = PEM_read_bio_X509(bio, &x509, NULL/*password*/, NULL);

        if (rsa) { // or if (x509)
            uint8_t *buf, *bufp;
            int len = i2d_RSAPublicKey(rsa, NULL);
            // int len = i2d_X509(x509, NULL);

            if (len >= 0) {
                buf = bufp = malloc(len);
                i2d_RSAPublicKey(rsa, &bufp);
                // i2d_X509(x509, &bufp);
            }

            if (len >= 0) {
                result = [NSData dataWithBytes:buf length:len];
                free(buf);
            }

            RSA_free(rsa);
            // X509_free(x509);
        }

        BIO_free(bio);
    }

    return result;
}

Upvotes: 1

Related Questions