为什么80%的码农都做不了架构师?>>>
rsa加密--选择padding模式需要注意的问题。。。
RSA加密常用的填充方式有下面3种:
1.RSA_PKCS1_PADDING 填充模式,最常用的模式
要求:
输入:必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11
如果输入的明文过长,必须切割, 然后填充
输出:和modulus一样长
根据这个要求,对于512bit的密钥, block length = 512/8 – 11 = 53 字节
2.RSA_PKCS1_OAEP_PADDING
输入:RSA_size(rsa) – 41
输出:和modulus一样长
3.for RSA_NO_PADDING 不填充
输入:可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充
输出:和modulus一样长
跟DES,AES一样,RSA也是一个块加密算法( block cipher algorithm),总是在一个固定长度的块上进行操作。但跟AES等不同的是, block length是跟key length有关的。每次RSA加密的明文的长度是受RSA填充模式限制的,但是RSA每次加密的块长度就是key length。
需要注意:
在BouncyCastle实现RSA的PKCS1V1.5模式中,如果是公钥加密信息(forEncryption=true),密钥长度为1024位,那么输出的密文块长度为128个字节,输入的明文块长度为127-10,即输入的明文块最大是117位,如果输入的明文块小于117位,比如输入的明文块长度为64位,那么会对这个明文块进行补位,在明文块前添加一位的0x02字节(代表公钥加密)然后后面的52位为随机的字节,在补位的最后一位,{即52(117-64-1),从零开始的},添加一位的字节0x00,在补位的后面添加实际的明文块。
这样做的目的就是使得明文块转化成与module差不多的大整数。
如果是私钥加密(forPrivateKey=true),密钥长度为1024位,那么输出 的密文块长度也是128字节,输入的明文块的长度为127-10,即输入的明文块最大是117位,如果输入的明文块小于117位,比如输入的明文块长度为64位,那么对这个明文块进行补位,在明文块千添加一位的0x01字节(代表私钥加密),然后在后面的52位为字节0xff,在最后一位{即52(117-64-1),从零开始),添加一位的字节0x00,在补位的后面添加时间的明文块。
RSA算法在运算时需要将数据填充至分组长度(与RSA密钥模长相等)。
PAD方式分下面两种:
EM = 0x00 || 0x01 || PS || 0x00 || T
PS : pad with 0xFF, length : Len(EM) - 3 - Len(T)
EM = 0x00 || 0x02 || PS || 0x00 || M
PS : pad with random data, length : Len(EM) - 3 - Len(M)
填充串PS的长度最少为8个字节,这是RSA操作的一种安全措施。
所以RSA签名的数据长度不能超过分组长度-11字节。
这个在http://tools.ietf.org/html/rfc2313中的“8.1 Encryption-block formatting”3可以找到。
3.RSA_PKCS1_OAEP_PADDING填充模式没有使用过, 他是PKCS#1推出的新的填充方式,安全性是最高的,和前面RSA_PKCS1_PADDING的区别就是加密前的编码方式不一样。
http://tools.ietf.org/html/rfc2313 这里面有一些关于RSA加密PKCS#1标准的有关介绍,感兴趣的同学
可以去看一下。。。
int RSA_sign(int type, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa);
会根据type是SHA1还是MD5,给m加header,sha1 header = 15 bytes, md5 head = 18 bytes
我们把RSA_sign签名后的数据进行解密,用int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);函数,发现解密后的数据为:
$ ./a.exe (我写的一个验证程序 rsa-sysssl.c)
sha1 header: (15 bytes) 3021300906052b0e03021a05000414
sha1 data: 395e4981d467d1bd120dfb708ed4e3869c34bc04
input string = aaabbbccc
sha1 header: (15 bytes) 3021300906052b0e03021a05000414
sha1 data: 299fbb21cb784c917664fe027deb52d1ee8b24ea
input string = asdfajkhsdf
这就证实了我们上面RSA_sign会给数据加header的做法,其实header的含义是这样:
/*
* See:
* http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
*/
/*
* id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
* oiw(14) secsig(3) algorithms(2) 26 }
*/
static const u_char id_sha1[] = {
0x30, 0x21, /* type Sequence, length 0x21 (33) */
0x30, 0x09, /* type Sequence, length 0x09 */
0x06, 0x05, /* type OID, length 0x05 */
0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
0x05, 0x00, /* NULL */
0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
};
/*
* id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
* rsadsi(113549) digestAlgorithm(2) 5 }
*/
static const u_char id_md5[] = {
0x30, 0x20, /* type Sequence, length 0x20 (32) */
0x30, 0x0c, /* type Sequence, length 0x09 */
0x06, 0x08, /* type OID, length 0x05 */
0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */
0x05, 0x00, /* NULL */
0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */
};