manbetx官方网站

jsencrypt代码分析——openssl的rsa加密解密在js的落实。17.openssl编程——RSA介绍。

十月 26th, 2018  |  manbet体育登录

当js上开rsa,感觉jsencrypt这个是包裹的可比好之,但因故起或撞了数坑,所以踩上代码里填充填坑~

17.1  RSA介绍

类型以此地 https://github.com/travist/jsencrypt

RSA算法是一个泛运用的公钥算法。器密钥包括公钥和私钥。他能够用于数字签名、身份证明和密钥交换。RSA密钥信息根本概括:

【rsa算法】

* n:模数

首先科普一下rsa:公钥私钥成对,用中一个加密只能用其他一个解密,常用公钥加密私钥解密。

* e:公钥指数

同样开始看斯坦佛那个库,原始之算法实现:

* d:私钥指数

长度,建议至少1024。模数n(常取默认65537)两度都要用。

* p:最初的大素数

指数e,和n一起就是是公钥。指数d,和n一起就是自私钥。质数p和q用于生成密钥对,然后就扔弃不明白。

* q:最初的大素数

实际算法网上一样不行把,就无多说了。

* dmp1:e * dmp1 = 1 (mod(p-1))

【ssl/ssh密钥对】

* dmp1:e * dmp1 = 1 (mod(q -1))

从而服务器上之家伙转的密钥对,格式一般是之类,有开始执行了行,内容用base64转码。这里涉及一些万国编码规范,代码分析时于挨家挨户分解。

* iqmp:q * iqmp = 1 (mod p)

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIA4OVgB4FRq4l5zjEmd4r/jswRcHlZQ
kg10p9rzG3VyXCPpa/ZkwOYy+kGq7a7BjAKTpic2cUNRim4m8HKTdc8CAwEAAQ==
-----END PUBLIC KEY-----

内部,公钥为n和e;私钥为n和d。在事实上利用被,公钥加密一般用来商量密钥;私钥加密一般用来签名。

【代码分析】

 

加载公钥:setPublicKey->setKey->JSEncryptRSAKey->parseKey

17.2
openssl的RSA实现

RSAKey.prototype.parseKey = function (pem) {…}

openssl的兑现RSA实现源码在crypto/rsa目录下。它实现了RSA
PKCS1正经。主要源码如下:

注写得不行好!

a.rsa.h

/**
...省略...
 *This method accepts public key
 * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
 * The format is defined as:
 * PublicKeyInfo ::= SEQUENCE {
 *   algorithm       AlgorithmIdentifier,
 *   PublicKey       BIT STRING
 * }
 * Where AlgorithmIdentifier is:
 * AlgorithmIdentifier ::= SEQUENCE {
 *   algorithm       OBJECT IDENTIFIER,     the OID of the enc algorithm
 *   parameters      ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
 * }
 * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
 * RSAPublicKey ::= SEQUENCE {
 *   modulus           INTEGER,  -- n
 *   publicExponent    INTEGER   -- e
 * }
 */

成效:定义RSA数据结构以及RSA_METHOD,定义了RSA的各种函数

代码如下:

b.rsa_asn1.c

 1 RSAKey.prototype.parseKey = function (pem) {
 2   try {
 3 ...
 4     var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
 5     var asn1 = ASN1.decode(der);
 6 ...
 7     if (asn1.sub.length === 9) {
 8       // Parse the private key.
 9     }
10     else if (asn1.sub.length === 2) {
11       // Parse the public key.
12       var bit_string = asn1.sub[1];
13       var sequence = bit_string.sub[0];
14       modulus = sequence.sub[0].getHexStringValue();
15       this.n = parseBigInt(modulus, 16);
16       public_exponent = sequence.sub[1].getHexStringValue();
17       this.e = parseInt(public_exponent, 16);
18     }
19     else {
20       return false;
21     }
22     return true;
23   }
24   catch (ex) {
25     return false;
26   }
27 };

功用:实现了RSA密钥的DER编码和解码,包括公钥和私钥

此地用了解一下各种编码格式。hex和base64就未解释了。

c.rsa_chk.c

ASN.1抽象语法标记,我之知情就是是对准数码进行结构化解析的正儿八经:一个正经的ASN.1编码对象来四独地段:对象标识域、数据长度域、数据域以及罢标志(可选,在长度不可知情况下需要,openssl中没拖欠标志)。

功能:RSA密钥检查

DER则是现实的编码实现。 http://baike.baidu.com/view/100318.htm#4

d.rsa_eay.c

PKCS#1虽然是RSA中不过基础的算法定义和密钥规定,讲人语句就是概念了:公钥是元组(n,e),算法是n=q*p等一多元公式。https://en.wikipedia.org/wiki/PKCS1

功用:openssl实现的平等栽RSA_METHOD,作为默认的平种植RSA计算实现方式。此文件贯彻rsa_sign\rsa_verify和rsa_keygen回调函数。

即时段代码两处于亮点,一个是else if (asn1.sub.length === 2)判断公钥(没追究,反正靠子节点数判断);
点滴一个凡var bit_string = asn1.sub[1];即前有一段asn1.sub[0]凡算法标识。

e.rsa_gen.c

此处我并未坑,但是别公钥时假如命令不对应是会见踩坑的(有同等种命令是浮动无算法标记的公钥)~~~

力量:RSA密钥生成,如果RSA_METHOD中的rsa_ekygen回调函数不也空,则调用它,否则调用器内部贯彻。

 

f.rsa_lib.c

加密:encrypt->RSAEncrypt->pkcs1pad2 | doPublic->RSADoPublic

意义:主要实现了RSA运算的季只函数(公钥私钥,加密解密),他们还调用了RSA_METHOD中相应回调函数。

pkcs1pad2是举行补位处理:

g.rsa_none.c

适合参 var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
是(模位数+7)/8得到模的字节长度?

成效:实现了一致栽填充和去填。

接下来是均等文山会海的动操作,此处的意图是填入随机位使得每次加密的密文都无平等。http://blog.chinaunix.net/uid-21880738-id-1813144.html

h.rsa_null.c

RSADoPublic最终实施加密算法x^e (mod n)

功效:实现同种空的RSA_METHOD.

 

i.rsa_oaep.c

从那之后,主要的算法、规范以及坑基本上覆盖了,私钥和解密坑比较少,就非多说了。

功用:实现了oaep填充与失填

末尾,附送一个本年好坑,跨语言跨类库的下不小心可能会见赶上的
http://blog.chinaunix.net/uid-23069658-id-4282969.html

j.rsa_pk1.

给这js类库而言,-pubout出来的是可用的,而-RSAPublicKey_out出来的是休可用之。

意义:实现了pkcs1填写充与夺填

同这相应,服务器openssl的类库中PEM_read_RSA_PUBKEY()读入是呼应的,而PEM_read_RSAPublicKEY()读入是勿对应的。
 

k.rsa_sign.c

 

功效:实现了RSA的签约以及验签

l.rsa_ssl.c

功能:实现了ssl填充

m.rsa_x931.c

效果:实现了相同种植填充和去填

 

17.3
RSA签名以及说明过程

RSA签名过程如下:

a.对用户数量进行摘要

b.构造X509_SIG结构并DER编码,其中包括了摘要算法和摘要结果

c.对a的结果开展填充,填满RSA密钥长度字节数。比如1024号RSA密钥必要填写满128字节。具体的填方式发生用户指定。

d.对b的结果用RSA私钥加密。

RSA_eay_private_encrypt函数实现了c和d过程

 

RSA验签过程是伤处过程的逆过程,如下:

a.对数码用RSA公钥解密,得到签名过程中b过程

b.去除a结果的填充

c.从b的结果中道非道算法,以及摘要结果

d.将本数因c中获摘要算法进行摘要计算

e.比较d与签名过程中a的结果。

RAS_eay_public_decrypt实现了a和b过程。

 

17.4 数据结构

RSA主要数据结构定义在crypto/rsa/rsa.h

 

struct rsa_meth_st {

char *name;

int (*rsa_pub_enc) (int flen, const unsigned char *from,

unsigned char *to, RSA *rsa, int padding);

int (*rsa_pub_dec) (int flen, const unsigned char *from,

unsigned char *to, RSA *rsa, int padding);

int (*rsa_priv_enc) (int flen, const unsigned char *from,

unsigned char *to, RSA *rsa, int padding);

int (*rsa_priv_dec) (int flen, const unsigned char *from,

unsigned char *to, RSA *rsa, int padding);

int (*rsa_mod_exp) (BIGNUM *r0, BIGNUM *a, const BIGNUM *p,

const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);

int (*init) (RSA *rsa);

int (*finish) (RSA *rsa);

int flags;

char *app_data;

int (*rsa_sign) (int type,

const unsigned char *m, unsigned int m_length,

unsigned char *sigret, unsigned int *siglen,

const RSA *rsa);

int (*rsa_verify) (int dytpe, const unsigned char *m,

unsigned int m_length, const unsigned char *sigbuf,

unsigned int siglen, const RSA *rsa);

int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);

int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,

BIGNUM *e, BN_GENCB *cb);

}

 

name:RSA_METHOD名称

rsa_pub_enc:公钥加密函数,padding为那填写方式,输入数据不能够太丰富,否则无法填充

rsa_pub_dec:公钥解密函数,padding为去填充的方法,输入数据长度为RSA密钥长度的字节数

rsa_priv_enc:私钥加密函数,padding为该填写方式,输入数据长度不克顶丰富,否则无法填充

rsa_priv_dec:私钥解密函数,padding为其除去填充的法,输入数据长度也RSA密钥长度的字节数。

rsa_sign:签名函数

rsa_verify:验签函数

rsa_keygen:RSA密钥对生成函数

 

 

b.RSA

RSA数据结构中隐含了公私钥信息(如果单纯来n和e,则表明公钥)

struct rsa_st {

int pad;

int32_t version;

const RSA_METHOD *meth;

ENGINE *engine;

BIGNUM *n;

BIGNUM *e;

BIGNUM *d

BIGNUM *p;

BIGNUM *q;

BIGNUM *dmp1;

BIGNUM *dmq1;

BIGNUM *iqmp;

STACK_OF(RSA_PRIME_INFO) *prime_infos;

RSA_PSS_PARAMS *pss;

CRYPTO_EX_DATA ex_data;

CRYPTO_REF_COUNT references;

int flags;

BN_MONT_CTX *_method_mod_n;

BN_MONT_CTX *_method_mod_p;

BN_MONT_CTX *_method_mod_q;

char *bignum_data;

BN_BLINDING *blinding;

BN_GLINDING *mt_blinding;

CRYPTO_RWLOCK *lock;

 

}

 

 

17.5 主要函数

a.RSA_check_key

功能:检查RSA密钥

b.RSA_new

作用:生成一个RSA密钥结构,并利用默认的rsa_pkcs1_eay_meth
RSA_METHOD方法

c.RSA_free

功能:释放RSA结构。

d.RSA *RSA_generate_key(int bits, unsigned long e_vlaue, void
(*callback)(int , int, void *), void *cb_arg)

职能:生成RSA密钥,bits是模数比特数,e_value是公钥指数e,callback回调函数由用户实现,用于干预密钥生成过程中之一部分运算,可谓空。

e.RSA_get_ex_data

成效:获取扩展数据

f.RSA_get_method

功能:获取RSA结构的RSA_METHOD.

g.RSA_padding_add_none

RSA_padding_add_PCKS1_OAEP

RSA_padding_add_PKCS1_type_1(私钥加密的填写)

RSA_padding_add_PKCS1_type_2(公钥加密的填充)

RSA_padding_add_SSLv23

h.RSA_padding_check_none

RSA_padding_check_PKCS1_OAEP

RSA_padding_check_PKCS1_type_1

RSA_padding_check_PKCS1_type_2

RSA_padding_check_SSLv23

RSA_PKCS1_SSLeay

i.int RSA_print(BIO *bp, const RSA *x, int off)

功能:将RSA信息输出到BIO中,off为出口信息以BIO中偏移量,比如是屏幕BIO,则表示打印信息的位置离左边屏幕边缘之偏离。

j.int DSA_print_fp(FILE *fp, const DSA *x, int off)

效果:将RSA信息输出到FILE中,off为出口偏移量。

k.RSA_public_decrypt

效益:公钥解密

l.RSA_public_encrypt

效益:公钥加密

m.RSA_set_default_method/RSA_set_method

意义:设置RSA结构中的method,当用户实现了一个RSA_METHOD时,调用此函数来设置,使RSA运算采用用户的措施。

n.RSA_set_ex_data

功效:设置扩大数据

o.RSA_sign

功能:RSA签名

p.RSA_sign_ASN1_OCTET_STRING

力量:另外一栽RSA签名,不关乎摘要算法,他以输入数据作为ASN1_OCTET_STRING进行DER编码,然后径直调用RSA_private_encrypt进行计算。

q.RSA_size

功用:获取RSA密钥长度字节数

r.RSA_up_ref

作用:给RSA密钥增加一个援

s.RSA_verify

功能:RSA验证

t.RSA_verify_ASN1_OCTET_STRING

职能:另一样种RSA验证,不关乎摘要算法,与RSA_sign_ASN1_OECTET_STRING对应。

u.RSAPKey_asn1_meth

功能:获取RSA私钥的ASN1_METHOD,包括i2d, d2i, new和free函数地址

v.RSAPrivateKey_dup

功能:复制RSA私钥

w.RSAPublicKey_dup

功能:复制RSA公钥

 

 

标签:, , , ,

Your Comments

近期评论

    功能


    网站地图xml地图