使用Keychain存储密钥在iOS中生成OpenSSL证书签名请求

ana*_*oma 12 openssl keychain csr ios

我正在尝试在iOS中生成CSR.由于iOS的Apple安全框架显然不包括CSR生成方法,因此我必须为我的项目编译OpenSSL源代码.

现在我想知道如何将这些方法与我之前在Keychain中生成的密钥一起使用.也就是说,我需要将SecKeyRef类型转换为OpenSSL类型,如EVP_PKEY.这将允许我调用OpenSSL方法X509_REQ_set_pubkey.

有谁知道实现这一目标的方法?

ana*_*oma 16

自己找到了解决方案.

首先,您需要从Keychain中提取密钥作为NSData.

- (NSData *) getKeyDataWithIdentifier:(NSString *) identifier
{
    NSData * keyBits = nil;
    NSMutableDictionary * keyQuery = [[NSMutableDictionary alloc] init];
    NSData * encodedId = [identifier dataUsingEncoding:NSUTF8StringEncoding];
    [keyQuery setObject:encodedId forKey:kSecAttrApplicationTag];
    [keyQuery setObject:kSecClassKey forKey:kSecClass];
    [keyQuery setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnData];
    [keyQuery setObject:kSecAttrKeyTypeRSA forKey:kSecAttrKeyType];

    OSStatus sanityCheck = SecItemCopyMatching((CFDictionaryRef)keyQuery, (CFTypeRef *)&keyBits);

    if (sanityCheck != noErr) {
        NSLog(@"Error: %ld", sanityCheck);
    }

    return keyBits;
}
Run Code Online (Sandbox Code Playgroud)

现在我们需要将此数据转换为unsigned char并将其提供给方法d2i_RSAPublicKey

- (void) generateCSR:(NSData *) keyData
{
    X509_REQ *req = NULL;
    X509_NAME *name= NULL;
    EVP_PKEY *key;
    const unsigned char * bits = (unsigned char *) [keyData bytes];
    int length = [keyData length];

    if ((req=X509_REQ_new()) == NULL) {
        NSLog(@"big error");
        return;
    }

    RSA * rsa = NULL;
    key=EVP_PKEY_new();
    d2i_RSAPublicKey(&rsa, &bits, length);
    EVP_PKEY_assign_RSA(key,rsa);
    name = X509_REQ_get_subject_name(req);
    X509_REQ_set_pubkey(req, key);

    /* This function creates and adds the entry, working out the
     * correct string type and performing checks on its length.
     * Normally we'd check the return value for errors...
             */
    X509_NAME_add_entry_by_txt(name,"CN",
                               MBSTRING_ASC, "My certificate request", -1, -1, 0);
    X509_REQ_print_fp(stdout, req);
}
Run Code Online (Sandbox Code Playgroud)

这会在OpenSSL(未签名)中生成一个简单的CSR,其中包含公钥和通用名称,并将其打印到标准输出.