一、RSA_NO_PADDING模式,顾名思义,无填充;

测试运行时,也遇到几个问题,需要注意(以下举例均以模数1024bit,128字节):

1、加密数不能大于模数

否则,会报错:“data too large for modulus”,这个是正常的,否则大于模数解密时会出问题,因为加解密都是取模的。

因此,在读取文件加密时,每次读取128字节时,有可能大于模数,因此需要判断;大于模数时,读取127字节。

但问题也出来了:解密出来怎么判断第一个00是真实数据,还是需要去掉的呢?

PS:其他加密模式通过填充均避免了这种情况。

2、加密长度必须为keysize字节

   如果不等于,则报错:“data too large /too small for key size”,因为无填充,所以你的输入必须满(特别是最后一个数,不足时需要自己填充了)!

 

善用RSA报错处理:

char err[256];
        int ret = RSA_public_encrypt(keysize_y/8,buf,pEncode,rsaK,RSA_NO_PADDING);
        if(ret==-1)
        {
          //  ERR_load_RSA_strings();
            ERR_load_crypto_strings();
            ERR_error_string(ERR_get_error(), err);
            printf("%s\n",err);
            return;
        }

二、RSA_PKCS1_PADDING 模式

/*
   RFC 2313 - PKCS #1: RSA Encryption Version 1.5  
   EB = 00 || BT || PS || 00 || D
        EB - Encryption Block
        BT - Block Type                 :: 00 or 01 for private-key operation; 02 for public-key operation
        PS - Padding String             :: length = k-3-||D||
                                           BT 00: all 00
                                           BT 01: all FF
                                           BT 02: pseudorandomly generated and nonzero
         D - Data
         k - length of modulus in octets
*/

1、填充规则如上(其实看英文理解的更好,翻译的有词不达意的),

(1)EB为填充完毕后的加密块,EB = 00 || BT || PS || 00 || D

(2)BT块类型,00/01为私钥操作;02为公钥操作(即公钥加密时置02.......)

(3)PS为填充数组,长度=模长-3-输入明文长度,BT=00时:填充全00;BT=01时填充全FF;BT=02时填充非零随机数(实测:只要非零即可)

(4)D为要加密的明文数据

2、注意

填充PS,至少8字节,所以,输入明文最多(模长-11)字节;

只要按以上规则填充加密,你就可以与openSSL互相加解密。

(填充完毕后,其实就是按照无填充模式加密了)填充第一字节为00,保证了输入小于模数,肯定可以加密成功。

去填充也很简单,根据填充格式去掉即可,主要是00....00,后面的就是真实明文了。

三、RSA_PKCS1_OAEP_PADDING模式

据说是最安全的一种填充。

openssl 加密算法 openssl rsa加密_数组

参考:

与OpenSSL源码对照看,能看的更明白。

(1)其hash函数用的是sha1,输出是20字节;所以加密输入不能大于(模长-42)字节;42字节为2个20字节、2个1字节(00、01,PS可以没有);

(2)经测试,seed可以是任何数,全0、随机均可;

(3)利用源码和GMP库,自写加密,然后OpenSSL解密通过;需要注意的是:加密后的GMP大数在写入数组给OpenSSL解密时,要写入到模数大小的数组里,比如1024bit、256字节,要前面置0,而不是后面置0;即整个大数放到数组里应该就是原来的样子,如果只有255字节大小,应该第一个字节为0;而我在测试时直接从位置0开始写入的导入最后一个字节为0,是错误的。其他模式同理。

(4)利用源码和GMP库,自加密后,自解密时,先x^e mod n为pading后的数据EM(上图中的),此数据应该小于等于127字节(1024模数的话),因为EM第一字节为0(EM为大数时第一字节0实际不存在的),进行padding_check时,输入的数据就是这127字节的数据。(而不能是128字节带着第一字节0)