RSA算法padding方式

在开发过程中,发现iOS端经过RSA加密的密文传到服务端之后, 服务端无法解析,本来想通过比较同一段明文的加密结果,来判断服务端和iOS端加密方式的区别,结果发现加密结果一直不一样。然后服务端尝试多次加密同一段明文,得到的结果也不一样。 


然后就很震惊。学过密码学的我也知道RSA的原理, 类似:
  1)、密文 = 明文^e mod n
  2)、明文 = 密文^d mod n
  3)、那么 publickKey = (e,n),privateKey = (d,n)


经过研究,发现目前的RSA算法其实都会在加密的过程中加入一个随机值,所以每次加密的结果都会不一样。那么既然每次加密的结果都不一样, 那怎么解密呢, 具体方案如下:
 1)、 密文 =( random+明文) ^e mod n  //publicKey  加密
 2)、(random+明文) = 密文^d mod n   // 服务器端利用privateKey 解密
 3)、 明文 = (random+明文) - random //服务器端解码出random


 解决了这个疑问之后,有回到第一个问题,iOS加密的结果为何会解不出来呢。 答案是RSA算法添加随机数的方式也有很多种,因为iOS设定的padding方式和服务端的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. RSA_NO_PADDING  不填充
输入:可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充

输出:和modulus一样长


用python实现RSA_PKCS1_PADDING填充的RSA代码如下:


import cgi, base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA
from Crypto import Random

# 私钥文件
priKey = '''-----BEGIN RSA PRIVATE KEY-----
xxxx
-----END RSA PRIVATE KEY-----'''

# 公钥文件
pubKey = '''-----BEGIN PUBLIC KEY-----
xxxx
-----END PUBLIC KEY-----'''

# 伪随机数生成器
random_generator = Random.new().read


'''*RSA加密
* data待加密数据
* 最后的加密结果,需要用base64编码
* return 加密结果
'''


def rsa_encrypt(data):
    key = RSA.importKey(pubKey)
    cipher = PKCS1_v1_5.new(key)
    cipher_text = base64.b64encode(cipher.encrypt(data))
    return cipher_text


'''*RSA解密
* encrypt_text待解密数据
* 解密用私钥
* return 解密的结果
'''


def rsa_decode(encrypt_text):
    key = RSA.importKey(priKey)
    cipher = PKCS1_v1_5.new(key)
    text = cipher.decrypt(base64.b64decode(encrypt_text), random_generator)
    return text

猜你喜欢

转载自blog.csdn.net/harleylau/article/details/80135128
今日推荐