学习使用JavaScript的RSA加密算法库

RSA算法加密早已接触过很次,但一直没有真正使用过,而且大多加密操作都在服务端执行,很少有较复杂的加密操作在客户端执行。最近处理了一个需要在前端页面进行RSA加密操作的问题,做一个小记录。

问题要求是使用RSA加密数据,格式需要用PKCS#1 v1.5padding

首先PKCS 是 “Public Key Cryptography Standards”,其中PKCS#1 主要用作对数据进行RSA加解密,其他标准可以参考Wiki

v1.5 padding代表使用第1.5版本填充模式,对加密数据进行一定的填充,是加密可选择的方法之一,也是最常用的方法。
在OPENSSL中,PKCS#1 v1.5padding是默认的加解密方式

PKCS #1 RSA Encryption Version 1.5

在进行RSA运算时需要将源数据D转化为Encryption block(EB)。其中pkcs1padding V1.5的填充模式安装以下方式进行

(1) EB = 00+ BT+PS +00 + D

说明

EB:为转化后Hex进制表示的数据块,长度为128个字节(密钥1024位的情况下)

00:开头为00。个人认为应该是一个保留位。因为目前BT的类型至于三种(00,01,02)一个字节就可以表示。

BT:用一个字节表示,在目前的版本上,有三个值00 01 02,如果使用公钥操作,BT永远为02,如果用私钥操作则可能为00或01。

PS:为填充位PS由k-3-D这么多个字节构成,k表示密钥的字节长度,如果我们用1024bit的RSA密钥,这个长度就是1024/8=128 ,D表示明文数据D的字节长度

对于BT为00的,则这些字节全部为00,对于BT为01的这些值全部为FF,对于BT为02的,这些字节的值随机产生但不能是0字节(就是00)。

00:在源数据D前一个字节用00表示

D:实际源数据

公式(1)整个EB的长度就是密钥字节的长度。

对于BT为00的,数据D中的数据就不能以00字节开头,要不然会有歧义,因为这时候你PS填充的也是00,就分不清哪些是填充数据哪些是明文数据了 但如果你的明文数据就是以00字节开头怎么办呢?对于私钥操作,你可以把BT的值设为01,这时PS填充的FF,那么用00字节就可以区分填充数据和明文数据对于公钥操作,填充的都是非00字节,也能够用00字节区分开。如果你使用私钥加密,建议你BT使用01,保证了安全性。

对于BT为02和01的,PS至少要有8个字节长,BT为02肯定是公钥加密,01肯定是私钥加密,要保证PS有八个字节长 因为EB= 00+BT+PS+00+D=k

所以D<=k-11,所以当我们使用128字节密钥对数据进行加密时,明文数据的长度不能超过过128-11=117字节

当RSA要加密数据大于 k-11字节时怎么办呢?把明文数据按照D的最大长度分块然后逐块加密,最后把密文拼起来就行。

其次,在使用RSA加密的过程中,我们需要公钥(顺便一提,在公钥和私钥搭配词语中,钥读作yue)。 而公钥可以由OPENSSL生成的密钥对中获取,通常OPENSSL生成的密钥对是pem格式的私钥。
openssl genrsa -out rsa_1024_priv.pem 1024 其中1024代表的是密钥长度 openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem从私钥中可以提取出公钥

在提供公钥的前提下,我们可以从中提取出系数(modulus)和模数(exponent)供其他使用。

那么如何使用呢?经过几天的搜寻,找到并且确认了一个使用上述方法的JS加密算法库,从中可以找到我们需要的代码
该算法库包含了RSA加解密的全部内容,并且提供密钥的生成和拆解,同时它的加密后明文是经过base64编码的,很符合在项目中的实际需求。

详情可见GitHub


JSRSA

1431 Words

2017-08-22 08:00 +0800