openssl中aes、rsa算法的使用

来源:互联网 发布:sql 执行存储过程 编辑:程序博客网 时间:2024/05/18 00:30

一、RSA

1.  算法原理


RSA算法是一个广泛使用的公钥算法。其密钥包括公钥和私钥。它能用于数字签名、身份认证以及密钥交换。RSA密钥长度一般使用1024位或者更高。RSA密钥信息主要包括[1]:

Ø         n:模数

Ø         e:公钥指数

Ø         d:私钥指数

Ø         p:最初的大素数

Ø         q:最初的大素数

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

Ø         dmq1:e*dmq1 = 1 (mod (q-1))

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

其中,公钥为n和e;私钥为n和d。在实际应用中,公钥加密一般用来协商密钥;私钥加密一般用来签名。

RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密,最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用RSA对刚才的加密密钥进行加密。


使用RSA算法需要注意两个问题:

1. 加密位数。这个是在生成key时需要指定的,在调用加解密函数时会用到。

2. 填充模式。有三种

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 

3) RSA_NO_PADDING  不填充
RSA_size(rsa)

2.  使用方法

(1) 公钥和私钥保存到文件中

第一步 生成公钥、私钥文件



   生成KEY时,需要提供key的位数以及e变量因子。   

通过PEM_write_RSAPublicKey,PEM_write_RSAPrivateKey这两个方法,把公钥和私钥以PEM格式写入文件。

这里有个问题,那就是内存释放问题。RSA_new与RSA_free,BN_new与BN_free配对,但即使这样还是会产生内存泄露,需要在整个程序结束的时候调用CRYPTO_cleanup_all_ex_data(); 

需要注意的是,CRYPTO_cleanup_all_ex_data()不能在potential race-conditions条件在调用(我理解的意思是当函数外部存在RSA结构体的时候,在函数内部执行CRYPTO_cleanup_all_ex_data()将导致函数外的RSA结构体也被清理掉),因此最好在程序结束的时候才调用。

第二步 执行加解密操作


公钥加密,首先调用PEM_read_RSAPublicKey方法,从PEM文件中把key读取到RSA的结构中,然后调用RSA_public_encrypt对数据分块加密,需要指定填充模式。

RSA_public_encrypt每次最多加密RSA_size(rsa)长度的数据,所以需要重复执行。

私钥解密,一样的道理,只不过调用的方法换成PEM_read_RSAPrivateKey和RSA_private_decrypt。

(2) 公钥和私钥保存到内存中


第一步 加密key

已经格式化的key,直接读取;如果没格式化,则需要做一些处理。

    

(1)公钥字符串开头要加上“-----BEGIN PUBLIC KEY-----\n”,结尾加上“\n-----END PUBLIC KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no start line

(2)公钥字符串每隔64个字符要加一个换行,否则会报秘钥格式错误。

c++代码实现举例:

int nPublicKeyLen = strPublicKey.size();      //strPublicKey为base64编码的公钥字符串
for(int i = 64; i < nPublicKeyLen; i+=64)
{
if(strPublicKey[i] != '\n')
{
strPublicKey.insert(i, "\n");
}
i++;
}
strPublicKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");
strPublicKey.append("\n-----END PUBLIC KEY-----\n");

openssl提供了bio接口以支持各种形式的秘钥读取

第二步 执行加解密操作

公钥加密




调用PEM_read_bio_RSA_PUBKEY从内存中读取公钥到RSA中,私钥则调用PEM_read_bio_RSAPrivateKey方法。


二、AES

1.  算法原理

AES加密数据块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。AES加密有很多轮的重复和变换。大致步骤如下:

1、密钥扩展(KeyExpansion)

2、初始轮(Initial Round)

3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey

4、最终轮(Final Round),最终轮没有MixColumns。


AES中有几个参数需要注意:

1. 分块长度,固定128比特。编码时填写这个参数即可

2. 密钥长度,用户自己选择,一般使用128比特

3.  ECB、CBC、CFB、OFB)

2.  使用方法

常用的模式是ECB和CBC

(1) ECB(Electronic Codebook,电码本)模式是分组密码的一种最基本的工作模式。在该模式下,待处理信息被分为大小合适的分组,然后分别对每一分组独立进行加密或解密处理

(a)for循环使用:


(b)下面我们看下openssl中的源码实现:


(2) CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。

openssl中提供的加密接口,是对整个输入数据加密,然后返回整个的加密结果,不需要for循环去分块加密,因为他们的前后块有关联。

(a)使用:


(b)源码:





//从上面的源码可以看出,cbc本质上和ecb差别不大,唯一区别是将前一次加密结果,与要加密的内容异或。因此,cbc的并行性较差,因为每次都要等待前一次的结果,而ecb则不用,速度较快。


0 0
原创粉丝点击