您所在的位置:首页 / 知识分享

关于RSA加密总结

2020.08.18

323

首先抛开语言层面来说,RRSA私钥和公钥文件格式通常有pkcs#1, pkcs#8,pkcs#7, pkcs#12, pem。

RSA加密算法是一种非对称加密算法,其玩法打破了以往所有加密算法的规则.在RSA出现之前,所有的加密方法都是同一种模式:加密解密的规则使用同一种方式.

RSA加密/解密
使用公钥加密的数据,利用私钥进行解密
使用私钥加密的数据,利用公钥进行解密

没错,RSA加密使用了"一对"密钥.分别是公钥和私钥,这个公钥和私钥其实就是一组数字!其二进制位长度可以是1024位或者2048位.长度越长其加密强度越大。


一般来说,抛开语言层面来说,RRSA私钥和公钥文件格式通常有pkcs#1, pkcs#8,pkcs#7, pkcs#12, pem。


PKCS#1格式如下
-----BEGIN RSA PRIVATE KEY-----
.....
-----END RSA PRIVATE KEY-----

PCKS#8格式如下
-----BEGIN PRIVATE KEY-----
.....
-----END PRIVATE KEY-----

pkcs#7除需要PCKS#1 KEY外,还需要x509 格式证书。

通常PHP中有openssl_sign、openssl_pkcs7_sign 签名,openssl_sign使用的是PKCS#1,openssl_pkcs7_sign时使用的是PEM格式的证书文件。另外,openssl_public_encrypt等加密使用的key也是PCKS#1格式。

在使用PCKS#1进行加密运算时,对加密的数据有长度限制,需要将源数据D转化为Encryption block(EB)。在BouncyCastle实现RSA的PKCS1V1.5模式中,如果是公钥加密信息(forEncryption=true),密钥长度为1024位,那么输出的密文块长度为128个字节,输入的明文块长度为127-10,即输入的明文块最大是117位,如果输入的明文块小于117位,比如输入的明文块长度为64位,那么会对这个明文块进行补位,在明文块前添加一位的0x02字节(代表公钥加密)然后后面的52位为随机的字节,在补位的最后一位,{即52(117-64-1),从零开始的},添加一位的字节0x00,在补位的后面添加实际的明文块。

对应PHP中openssl_public_encrypt(或者openssl_private_encrypt)  函数默认都是OPENSSL_PKCS1_PADDING  填充也就是PKCS1Padding填充方式。因此,基于PKCS1Padding的,会经常的看到如下代码..
$crypto = '';
foreach (str_split($data, 117) as $chunk) {
openssl_public_encrypt($chunk, $encryptData, $public_key);

$crypto .= $encryptData;
}
将加密的字符串按117分块加密,但在使用openssl_public_decrypt(或者openssl_private_decrypt)解密时,需要按128位分块解密,如下:
$plainData = str_split($data, 128);
foreach ($plainData as $chunk) {
$str = '';
$decryptionOk = openssl_private_decrypt($chunk, $str, $pi_key);//私钥解密
if ($decryptionOk === false) {
return false;
}
$decrypted .= $str;
}

另对于OPENSSL_NO_PADDING模式,PHP与JAVA有差别,在java(Android)中rsa加密选择无填充模式如果不足128字节的话,
调用方法会自动帮你填充至128字节再进行加密。但PHP没有,需要手动处理。
$data = str_pad($data, 128);

另外,在使用openssl_sign、openssl_pkcs7_sign 签名, 有不同算法(PHP中如: OPENSSL_ALGO_SHA1)。
**原来OpenSSL 1.0.2版本默认签名算法为sha256**
**OpenSSL 1.0.1版本默认签名算法为sha1**


特别说明:

x509,公钥证书,只有公钥。
p7,签名或加密。可以往里面塞x509,同时没有签名或加密内容。
p12,含有私钥,同时可以有公钥,有口令保护。
p7的作用就是电子信封。
X509是基本规范
P7和P12是两个实现规范,P7是数字信封,P12是带有私钥的证书规范。
x509是数字证书的规范,P7和P12是两种封装形式。比如说同样的电影,有的是avi格式,有的是mpg,大概就这个意思。

P7一般是把证书分成两个文件,一个公钥一个私钥,有PEM和DER两种编码方式。
PEM比较多见,就是纯文本的,P7一般是分发公钥用,看到的就是一串可见字符串,
扩展名经常是.crt,.cer,.key等。DER是二进制编码。
P12是把证书压成一个文件,.pfx 。主要是考虑分发证书,私钥是要绝对保密的,
不能随便以文本方式散播。所以P7格式不适合分发。.pfx中可以加密码保护,所以相对安全些。
在实践中要中,用户证书都是放在USB Key中分发,服务器证书经常还是以文件方式分发。
服务器证书和用户证书,都是X509证书,就是里面的属性有区别。


X509 是证书规范
PKCS#7 是消息语法 (常用于数字签名与加密)
PKCS#12 个人消息交换与打包语法 (如.PFX .P12)打包成带公钥与私钥