将PEM编码的X.509证书导入iOS KeyChain [英] Import PEM encoded X.509 certificate into iOS KeyChain

查看:730
本文介绍了将PEM编码的X.509证书导入iOS KeyChain的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从某处收到一个包含PEM编码的X.509证书的字符串。我想将此证书导入iOS的KeyChain。



我打算执行以下操作:


  1. 将NSString转换为openssl X509

  2. 创建PKCS12

  3. 将PKCS12转换为NSData

  4. 使用SecPKCS12Import导入NSData

到目前为止,我想出了以下代码:

  const char * cert_chars = [certStr cStringUsingEncoding:NSUTF8StringEncoding]; 

BIO * buffer = BIO_new(BIO_s_mem());
BIO_puts(buffer,cert_chars);

X509 * cert;
cert = PEM_read_bio_X509(buffer,NULL,0,NULL);
if(cert == NULL){
NSLog(@error);
}
X509_print_fp(stdout,cert);


EVP_PKEY * privateKey;
const unsigned char * privateBits =(unsigned char *)[privateKeyData bytes];
int privateLength = [privateKeyData length];

privateKey = d2i_AutoPrivateKey(NULL,& privateBits,privateLength);

if(!X509_check_private_key(cert,privateKey)){
NSLog(@PK error);
}

PKCS12 * p12 = PKCS12_create(test,David's Cert,privateKey,cert,NULL,0,0,0,0,0);不幸的是,即使X509_check_private_key成功并且X509_print_fp(stdout,cert)打印了有效的证书,p12也是nil


  1. 是我的方法正确

  2. PKCS12_create似乎失败?

更新



调用PKCS12_create似乎在以下方法失败:

  int EVP_PBE_CipherInit(ASN1_OBJECT * pbe_obj,const char * pass,int passlen,
ASN1_TYPE * param,EVP_CIPHER_CTX * ctx,int en_de)
{
const EVP_CIPHER * cipher;
const EVP_MD * md;
int cipher_nid,md_nid;
EVP_PBE_KEYGEN * keygen;

if(!EVP_PBE_find(EVP_PBE_TYPE_OUTER,OBJ_obj2nid(pbe_obj),
& cipher_nid,& md_nid,& keygen))
{
char obj_tmp [80 ];
EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_PBE_ALGORITHM);
if(!pbe_obj)BUF_strlcpy(obj_tmp,NULL,sizeof obj_tmp);
else i2t_ASN1_OBJECT(obj_tmp,sizeof obj_tmp,pbe_obj);
ERR_add_error_data(2,TYPE =,obj_tmp);
return 0;
}

if(!pass)
passlen = 0;
else if(passlen == -1)
passlen = strlen(pass);

if(cipher_nid == -1)
cipher = NULL;
else
{
cipher = EVP_get_cipherbynid(cipher_nid);
if(!cipher)
{
EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_CIPHER);
return 0;
}
}

if(md_nid == -1)
md = NULL;
else
{
md = EVP_get_digestbynid(md_nid);
if(!md)
{
EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_DIGEST);
return 0;
}
}

if(!keygen(ctx,pass,passlen,param,cipher,md,en_de))
{
EVP_F_EVP_PBE_CIPHERINIT ,EVP_R_KEYGEN_FAILURE);
return 0;
}
return 1;
}

检索密码

  cipher = EVP_get_cipherbynid(cipher_nid); 

以某种方式对RC2-40-CBC返回nil。


<在创建PKCS12之前,缺少以下调用:

  OpenSSL_add_all_algorithms(); 
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();

这些解决了缺少密码的问题以及随后的缺少摘要的问题。


I'm receiving a String containing a PEM encoded X.509 certificate from somewhere. I'd like to import this certificate into the KeyChain of iOS.

I'm planning to do the following:

  1. convert NSString to openssl X509
  2. create PKCS12
  3. convert PKCS12 to NSData
  4. import NSData with SecPKCS12Import

So far I came up with the following code:

const char *cert_chars = [certStr cStringUsingEncoding:NSUTF8StringEncoding];

BIO *buffer = BIO_new(BIO_s_mem());
BIO_puts(buffer, cert_chars);

X509 *cert;
cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
if (cert == NULL) {
    NSLog(@"error");
}
X509_print_fp(stdout, cert);


EVP_PKEY *privateKey;
const unsigned char *privateBits = (unsigned char *) [privateKeyData bytes];
int privateLength = [privateKeyData length];

privateKey = d2i_AutoPrivateKey(NULL, &privateBits, privateLength);

if (!X509_check_private_key(cert, privateKey)) {
    NSLog(@"PK error");
}

PKCS12 *p12 = PKCS12_create("test", "David's Cert", privateKey, cert, NULL, 0, 0, 0, 0, 0);

Unfortunately, p12 is nil even though X509_check_private_key was successful and X509_print_fp(stdout, cert) prints a valid certificate.

  1. is my approach correct
  2. how come PKCS12_create seems to fail?

Update:

The call PKCS12_create seems to fail in the following method:

int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
           ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
{
const EVP_CIPHER *cipher;
const EVP_MD *md;
int cipher_nid, md_nid;
EVP_PBE_KEYGEN *keygen;

if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
                &cipher_nid, &md_nid, &keygen))
    {
    char obj_tmp[80];
    EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_PBE_ALGORITHM);
    if (!pbe_obj) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp);
    else i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj);
    ERR_add_error_data(2, "TYPE=", obj_tmp);
    return 0;
    }

if(!pass)
    passlen = 0;
else if (passlen == -1)
    passlen = strlen(pass);

if (cipher_nid == -1)
    cipher = NULL;
else
    {
    cipher = EVP_get_cipherbynid(cipher_nid);
    if (!cipher)
        {
        EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_CIPHER);
        return 0;
        }
    }

if (md_nid == -1)
    md = NULL;
else
    {
    md = EVP_get_digestbynid(md_nid);
    if (!md)
        {
        EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_DIGEST);
        return 0;
        }
    }

if (!keygen(ctx, pass, passlen, param, cipher, md, en_de))
    {
    EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_KEYGEN_FAILURE);
    return 0;
    }
return 1;   
}

Retrieving the cipher

cipher = EVP_get_cipherbynid(cipher_nid);

somehow returns nil for "RC2-40-CBC".

解决方案

The following calls were missing before creating the PKCS12:

OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();

These solved the problems with the missing cipher and also a subsequent problem of a missing digest.

这篇关于将PEM编码的X.509证书导入iOS KeyChain的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆