将PEM编码的X.509证书导入iOS KeyChain [英] Import PEM encoded X.509 certificate into iOS KeyChain
问题描述
我从某处收到一个包含PEM编码的X.509证书的字符串。我想将此证书导入iOS的KeyChain。
我打算执行以下操作:
- 将NSString转换为openssl X509
- 创建PKCS12
- 将PKCS12转换为NSData
- 使用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
- 是我的方法正确
- 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:
- convert NSString to openssl X509
- create PKCS12
- convert PKCS12 to NSData
- 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.
- is my approach correct
- 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屋!