S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

调用OPENSSL读取PEM文件的灵异问题

Posted on 2010-01-11 18:30 S.l.e!ep.¢% 阅读(6145) 评论(0)  编辑 收藏 引用 所属分类: OpenSSL

openssl genrsa -out private.key 1024
openssl rsa -in private.key -pubout -out public.key

        BIO  * key  =  NULL; 
        RSA 
* =  NULL; 
        key 
=  BIO_new(BIO_s_file()); 
        BIO_read_filename(key, 
" c:\\private.key " ); 
        r 
=  PEM_read_bio_RSAPrivateKey(key, NULL, NULL, NULL); 
        BIO_free_all(key);

读取 private key 读取正常,r 并不返回空

使用同样方法读取 public key

        BIO *key = NULL; 
        RSA 
*= NULL; 
        key 
= BIO_new(BIO_s_file()); 
        BIO_read_filename(key, 
"c:\\public.key"); 
        r 
= PEM_read_bio_RSAPublicKey(key, NULL, NULL, NULL); 
        BIO_free_all(key);

不正常, r 总是返回 NULL,很不爽,将函数改一下 PEM_read_bio_RSA_PUBKEY

  BIO *key1=NULL;
  RSA *r1=NULL;
  key1=BIO_new(BIO_s_file());
  if(BIO_read_filename(key1,"c:\\public.key") <= 0 )
  {
   printf("error\n");
  }
  
  r1 = PEM_read_bio_RSA_PUBKEY(key1, NULL,NULL,NULL);
  BIO_free_all(key1);
  openssl_to_keys(r, 1024, priv, pub);

r1 读取成功

 具体原因未知

作者: playmud  时间: 2009-08-24 11:53:00
让我们先来看一下pem.h头文件中的定义:
 
#define PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
        (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u)
#define PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
        (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u)
        
#define PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
        (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u)
#define PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
        (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u) 
 

 

对应的很工整是不是,你生成一个私钥,然后用它生成一个公钥。

openssl genrsa -out private.pem 1024 
openssl rsa -in priv.pem -pubout -out public.pem 

用任何一种方法打开私钥,读取私钥信息,得到RSA,查看RSA,ok,没有问题,一切都还看起来比较正常。

然后用任何一种方法打开公钥,读取公钥信息,问题出现了:RSA对象为空,你失败了。

 

通过openssl的手册和帮助,你会发现两个函数:

PEM_read_bio_RSA_PUBKEY()
PEM_read_RSA_PUBKEY()

他们才是你要找的对应的,而上面两个函数是从任何.h里面找不到的,但是他们的确是真实存在的符号连接,在对应的.o文件中用objdump可以查看到他们的符号,很诡异!

现象描述完了,还未探其究竟。

附加读取 PEM file 的code
        BIO *key = NULL; 
        RSA *r = NULL; 
        key = BIO_new(BIO_s_file()); 
        BIO_read_filename(key, "c:\\private.key"); 
        r = PEM_read_bio_RSAPrivateKey(key, NULL, NULL, NULL); 
        BIO_free_all(key);
        
        R_RSA_PRIVATE_KEY priv;
        R_RSA_PUBLIC_KEY  pub;
        openssl_to_keys(r, 1024, priv, pub);

        BIO *key1=NULL; 
        RSA *r1=NULL; 
        key1=BIO_new(BIO_s_file()); 
        if(BIO_read_filename(key1,"c:\\public.key") 
<= 0 )
        {
            printf("error\n");
        } 
        
        r1 
= PEM_read_bio_RSA_PUBKEY(key1, NULL,NULL,NULL); 
        BIO_free_all(key1);
        openssl_to_keys(r, 1024, priv, pub);


static void bn_to_bin(BIGNUM* bn, unsigned char* bin, int n) {
    memset(bin, 
0, n);
    
int m = BN_num_bytes(bn);
    BN_bn2bin(bn, bin
+n-m);
}

void openssl_to_keys(
                     RSA
* rp, int nbits, R_RSA_PRIVATE_KEY& priv, R_RSA_PUBLIC_KEY& pub
                     ) {
    pub.bits 
= nbits;
    bn_to_bin(rp
->n, pub.modulus, sizeof(pub.modulus));
    bn_to_bin(rp
->e, pub.exponent, sizeof(pub.exponent));
    
    memset(
&priv, 0sizeof(priv));
    priv.bits 
= nbits;
    bn_to_bin(rp
->n, priv.modulus, sizeof(priv.modulus));
    bn_to_bin(rp
->e, priv.publicExponent, sizeof(priv.publicExponent));
    bn_to_bin(rp
->d, priv.exponent, sizeof(priv.exponent));
    bn_to_bin(rp
->p, priv.prime[0], sizeof(priv.prime[0]));
    bn_to_bin(rp
->q, priv.prime[1], sizeof(priv.prime[1]));
    bn_to_bin(rp
->dmp1, priv.primeExponent[0], sizeof(priv.primeExponent[0]));
    bn_to_bin(rp
->dmq1, priv.primeExponent[1], sizeof(priv.primeExponent[1]));
    bn_to_bin(rp
->iqmp, priv.coefficient, sizeof(priv.coefficient));
}

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理