注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

勇敢的劳尤条

 
 
 

日志

 
 

openssl命令行——RSA加解密(深入分析)  

2014-01-04 11:00:42|  分类: 软件安全以及传输 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
下面继续前一篇,使用带密码的RSA私钥。
首先是生成私钥和公钥。这里需要输入私钥的保护密码。

openssl genrsa -des3 -out test_en.key 1024
openssl rsa -in test_en.key -pubout -out test_pub_en.key

截图如下,至此生成了test_en.key和test_pub_en.key。
openssl命令行——RSA加解密 - yuanshuilee - 勇敢的劳尤条

紧接着,与上面同样的操作,进行加密和解密。

openssl rsautl -in hello.in -out fuck.out -encrypt -pubin -inkey test_pub_en.key
openssl rsautl -in fuck.out -decrypt -inkey test_en.key

截图如下,可见加密解密都完成了,但是每次使用私钥都需要密码。
openssl命令行——RSA加解密 - yuanshuilee - 勇敢的劳尤条


至此,基本的加密解密已经完成了,但是我仍有疑问。首先是私钥可以加密,这个容易理解。但是为什么rsa命令也有-des这些选项呢?官网做如下解释,不太理解。
后来,继续查看rsa官网的详细说明,才慢慢理解。首先,rsa这个工具可以从私钥文件中导出私钥,也可以导出公钥。所以,所谓的加密方式,是专门为导出私钥而准备的,公钥既然是公开的,就没必要加密。

-pubin

by default a private key is read from the input file: with this option a public key is read instead.

-pubout

by default a private key is output: with this option a public key will be output instead. This option is automatically set if the input is a public key.

-des|-des3|-idea

These options encrypt the private key with the DES, triple DES, or the IDEA ciphers respectively before outputting it. A pass phrase is prompted for. If none of these options is specified the key is written in plain text. This means that using the rsa utility to read in an encrypted key with no encryption option can be used to remove the pass phrase from a key, or by setting the encryption options it can be use to add or change the pass phrase. These options can only be used with PEM format output files.

但是,在生成加密私钥对应的公钥时,可以指定-des加密选项,但是好像没什么区别,因为加密解密过程还是一样。经过理解,-des并没有作用,但是生成的两个公钥文件仍然不同。
openssl命令行——RSA加解密 - yuanshuilee - 勇敢的劳尤条

打开私钥文件,可以看到,没有加密和经过加密的私钥文件是不一样的,至少开头不一样。经过加密的私钥,开头有加密的部分信息。

-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDCteioi0oxi5+4ITHMOBKmMA7c5jxW23g4uuLOfaKslSwgQB4J
c+SG2M1zs/kg46c5PPdh6OkISCTHzrAN3eZyKdxjkSpXWvwnRvIZvg1qrhBcuIab
acV0mojedX4akTGTaVRJi8xbSBJA6/7LCAHBKAbTko2UIYWEdb52lW/y/QIDAQAB
AoGAOPXGTigRWFUkMFVln/x3WC6O6ohf9njVvqLNXuLaB+rLsdOP9ev1Wo1p7QMl
Sj3O2avAIuBj64xPVjRcxHG5zAFYBQW8BIYsR7fFDuJE4zS1uWXeCERhBCkj2NlK
mssnJQLqd5+PzrVGJcE/RBmNGyx1hxYaNyDMFKZrzm/j7QECQQDiAxvdgvgFVHq/
TsBbfH1mILDmbER6/WL8hpftUKDzqcGJWhyHVA83kPE+54qqlTqd+mXYd67MZjID
suujyd5NAkEA3IuWrG3s2Fdsz0CObm0s0avdO0b2fkfEkccRvxd376awdyNSbn+w
4/LgYA7muuChwhFLjHR4fl3LOnAayM+fcQJAXgexFi2hBoapMuKOwQFAIrdDIfq1
Wv4Eqs9Mch1zeSyNKpnk+KCOXC3fUK6AUIwZgRRmPvM8NCnocQWFZ/VamQJAE+ly
cBz4nku+YjPk6ClpO4D1120/wgT+xV6gxoz64iM9mXQR9DIJKXt7MJEH2eWAFUJ0
fLjjTB1xxNPsRycfsQJAMZA9ChLw1cOvETI8TVecEhHOqLw54h8qLvI0LlEnZJIt
QcMJH2+igFDoHMRd48YZBaV4/s66mbVskDQKsRwBlw==
-----END RSA PRIVATE KEY-----

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,9F37DC73A5DBCA69

rYJe+bVqCa2PPL+HtT1AZIh/PLlMz9iF8JsTXf/gs39Zd8c0YyoWOa83t9KN3+Vv
IHE15QXqdNWV9k3wpPf3RQ9/uuvSDWDsxdEupXUBpa6vjRIclbdA3MkkKsy2DYOZ
kYlyiGEFirQX7m36YhMPPdr03RzLkQ8M9q+Cb+pRPKTOdIH08w2AhKrgD7OWxMJR
cRIFlkSffchoogJahIJVqgLStbyMCfV62P6MIbp1Zv5uCZkcO7zBn+vcQISwK1dr
zs/8Wx7mUVDFv7Rim8CEdW4SUPtnBxK/sk6/iNeI7v9uJOk3RN/a+8hf4b95N+/g
MxhacyYe91cNQNkURriBHv1hspdKUSl2u+aV/RlAGpQOozwA8OSRNxu64tlSBBv+
Tul3wF1gXW6kXEy9jxVAnwFWSLdAoijYSIhL4J34ntB4Dn7vsx9uX8luR8IRkxx1
d9+6y9nYHdjwtAMhTJwvhLuLjIAjzFh3EDKiBMkH8dE92xk325LQCFNHKZhT1Y6x
C94iWBAXpmj+NCqNHls+fzy+aZqxsV/d6RHAPmPqW3KtSNiCFppSf+HwC5aZ68fk
z5xBDLWw5CAeOf5TVZk0iQEs5ERitZ2dqs/PG0RbRL9ZuEOCsEJnRBh2mPE9wL6G
C/JdTMcVDO3Z0Yk/uYEyGBpbdS+ahclLjVpgYj/t3NyX2zXVBhEF7Zov75mHByeX
X6NFLra7tdNsPpKrk0FO723qn+0EBUwIkMQ/ZTNv4LOYa2U/qWqGRUf2SeMcIcYC
dqnOYkzvM0nNZ5xM42fpggMRmatsw5D5cT92Sml7JG6ArFM0VhuYAg==
-----END RSA PRIVATE KEY-----

查看rsautl说明,发现它的加密用公钥,解密用私钥。但是事实上,经过我的测试有意外的发现。

-encrypt

encrypt the input data using an RSA public key.

-decrypt

decrypt the input data using an RSA private key.

openssl rsautl -in hello.in -out fuck.out -encrypt -inkey test.key
openssl rsautl -in fuck.out -decrypt -inkey test.key

openssl命令行——RSA加解密 - yuanshuilee - 勇敢的劳尤条

        事实证明,其实我是可以用私钥加密的,但是,我还是只能用私钥解密,用公钥却不行。这是为什么呢?分析rsautl源码,下面给出关键一段。

EVP_PKEY *pkey = NULL;
switch(key_type) {
case KEY_PRIVKEY:
pkey = load_key(bio_err, keyfile, keyform, 0,
passin, e, "Private Key");
break;

case KEY_PUBKEY:
pkey = load_pubkey(bio_err, keyfile, keyform, 0,
NULL, e, "Public Key");
break;

case KEY_CERT:
x = load_cert(bio_err, keyfile, keyform,
NULL, e, "Certificate");
if(x) {
pkey = X509_get_pubkey(x);
X509_free(x);
}
break;
}
rsa = EVP_PKEY_get1_RSA(pkey);

        我们看到rsautl用 EVP_PKEY 这个结构去读取keyfile,将读到的公钥私钥文件保存在EVP_PKEY里面。通过这个函数 EVP_PKEY_get1_RSA(pkey) 去获取真正的RSA结构体。而据我们前面的分析,私钥文件是可以产生公钥的,所以,所谓的私钥加密,其实只能用公钥解密,但是rsautl禁止掉了,它将这种方式提供成签名和认证,所以不允许直接的公钥解密。而由于私钥文件含有公钥和私钥的信息,所以就可以用私钥文件进行加密和解密了。下面再附上一段rsautl的源码,这里可以看出
签名=私钥加密
认证=公钥解密
加密=公钥加密
解密=私钥解密

switch(rsa_mode) {
case RSA_VERIFY:
rsa_outlen  = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_SIGN:
rsa_outlen  = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_ENCRYPT:
rsa_outlen  = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
case RSA_DECRYPT:
rsa_outlen  = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad);
break;
}

        经过一番理解,我认为,其实这里的所谓私钥文件,确实包含了私钥文件,但是同时他也包含了公钥,为什么呢?我们可以从私钥中推导得到公钥,这难道不奇怪吗?事实上,在Openssl中,RSA是内存结构。当我们生成一个RSA时,如果有rsa->n,rsa->e时,该RSA是公钥RSA。RSA的私钥只要有是rsa->n,rsa->d 就可以了。但是,往往在应用中,RSA的私钥是包括rsa->p,rsa->q,rsa->dmp1,rsa->dmq1,rsa->iqmp,试想想,d,n,p,q,p-1,q-1以及(p-1)*(q-1)都有了,推导出e太难吗?人们常说不能从私钥导出公钥,是指产生RSA后,抛弃掉p,q的情况的,没有p,q是无法从公钥中算出私钥的,也无法从私算出公钥的。这也就是从私钥推导出公钥的原理。下面给出RSA的结构体。可以看到,RSA结构其实包含了公钥和私钥生成的所有信息。

struct rsa_st
{
/* The first parameter is used to pickup errors where
* this is passed instead of aEVP_PKEY, it is set to 0 */
int pad;
long version;
const RSA_METHOD *meth;
/* functional reference if 'meth' is ENGINE-provided */
ENGINE *engine;
BIGNUM *n;
BIGNUM *e;
BIGNUM *d;
BIGNUM *p;
BIGNUM *q;
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
/* be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
int references;
int flags;

/* Used to cache montgomery values */
BN_MONT_CTX *_method_mod_n;
BN_MONT_CTX *_method_mod_p;
BN_MONT_CTX *_method_mod_q;

/* all BIGNUM values are actually in the following data, if it is not
* NULL */
char *bignum_data;
BN_BLINDING *blinding;
BN_BLINDING *mt_blinding;
};

       有了上面的分析,我们就能够理解为什么用私钥可以加密了。事实上,用私钥解密,它实际上是用私钥可以推导出的公钥进行加密,然后再用私钥解密,因为拥有私钥的人,必然是自己本人,自己本人加密的东西,自己能解密相信也是很顺利成章的


http://fossies.org/dox/openssl-1.0.1f/index.html (详细源码)
  评论这张
 
阅读(886)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017