RSA 是一种非对称加密算法,可以对交互的数据进行加密和加签。
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。
公开密钥与私有密钥是一对,如果用私有密钥对数据进行加签,只有用对应的公开密钥才能验签;如果用公开密钥对数据进行加密,那么只有用对应的私有密钥才能解密。
如何生成公私钥?
通过openssl工具生成RSA的公钥和私钥(opnssl工具可在互联网中下载到)
下载:
1. 通过官网途径下载
2. 从github上克隆源码
linux 下安装方式(已处在该目录下):
1. sudo ./config
2. sudo make
3 sudo make test
4. sudo make install
*我在编译的过程中出现了一个错误给忽略了导致安装完成后无法正常使用报错:(openssl: error while loading shared libraries:libssl.so.1.1: cannot open shared object file: No such file or directory)这是由于安装库的位置不正确导致的,
解决方法是建立一个软链接:
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1
ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1*
生成私钥:
genrsa -out key.pem 1024
,并回车
此时,我们可以在bin文件夹中看到一个文件名为key.pem的文件,打开它,
可以看到—–BEGIN RSA PRIVATE KEY—–开头,—–END RSA PRIVATE KEY—–结尾的
没有换行的字符串,这个就是原始的私钥。
生成公钥:
输入命令rsa -in key.pem -pubout -out pubkey.pem,并回车
此时,我们可以在bin文件夹中看到一个文件名为pubkey.pem的文件,打开它,
可以看到—–BEGIN PUBLIC KEY—–开头, —–END PUBLIC KEY—–结尾的没有换行的
字符串,这个就是公钥。
ACTION 如果因为openssl太大不想下载的话
我们也可以使用python自带的模块来生成公私钥,不只是因为功能强大。项目中使用的一般都是openssl生成的,这是独立于某一语言之外的
使用python中的crypto来生成公私钥:
In [1]: from Crypto import Random
In [2]: from Crypto.PublicKey import RSA
#伪随机数
In [3]: random_generator = Random.new().read
In [4]: rsa = RSA.generate(1024,random_generator)
In [5]: myprivate = rsa.exportKey()
In [6]: myprivate
Out[6]: '-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCUzbANLEEENoLBzZjXIFkWj41OL73o7GLEVlsgsALKEyJDQ1iz\n+nrzrojQ/4B3tBwi5AJBVf+rd/CUHMDtq16OV6QiDPHB49b2w2Zn8O6+dkok6IvE\nKfHhBv8Es2ZRvtWeaMW98M8cO13WegzWoeA12CJlvGK6bW5zk4U5WRX+GwIDAQAB\nAoGASXZ+uxIlCxJqXYnGMjbrJKM8bORPCsZhQHMtzCZ5ShBGMxT1nu1DdDivnRb2\n8qH93g/ZOS5e6eVt5YGIkg2vwS+wtx0SlLQg7IRgFfk3uimeNPcLxUP2bjWmcxwX\nrcPdDCPjetx0GDd/vvKUozmzREAON0EhB0PvViM6BdsVHpkCQQDAS37X17hiVuhU\nliii13ZDMM/BQMCKZyk1cSPjow90Cptmmqy8HGWs6+5mV7jgBf558oZATIfxSNEf\nBTuLWKjnAkEAxhmwfmUiQfG77gN12XmctRP6tvspWc5Rl41pyqcyBztlnngkZL3R\nCrbx8OGTmWa2yq8DFkUdEyOdzFkeNhgWrQJBAJPvAIwopu7wkRfR1T1BqPeT66Bu\nojFXn7o/ai7L2S2ao2bSA6VL62SWtPcC8XVW5ykFzQZWWhbjwA2vRtmywW0CQAHN\nMgG0Qb9/x0m+1k+H/5jV+a24UwPyEGPkcVXad2YBcEckqJAR+dizGTgrlQAMIxVs\nygZl0oHeDQ1SsiejyHECQATZLWxB5E1rumQHUKqFftDNwFHVGTLB9+r6V6IgimFq\nO83UgcpSIfiaFN/DR7gTi+R8iUTa7SCTUZ3mUlNMeC0=\n-----END RSA PRIVATE KEY-----'
In [7]: mypublic = rsa.publickey()
# 生成公钥
In [8]: mypublic = mypublic.exportKey()
In [9]: mypublic
Out[14]: '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUzbANLEEENoLBzZjXIFkWj41O\nL73o7GLEVlsgsALKEyJDQ1iz+nrzrojQ/4B3tBwi5AJBVf+rd/CUHMDtq16OV6Qi\nDPHB49b2w2Zn8O6+dkok6IvEKfHhBv8Es2ZRvtWeaMW98M8cO13WegzWoeA12CJl\nvGK6bW5zk4U5WRX+GwIDAQAB\n-----END PUBLIC KEY-----'
需要保存的话可以用python的文件操作:
with open ('/home/private.pem',wb) as f:
f.write(myprivate)
开始数据的加密与签名等操作
在开始操作前再回顾一下必要的常识:
通常在项目中是双向验证双向加密的,也就是说可能会有两对公私钥
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
# 加密函数
def encrypt(message, public_key):
"""
功能:对参数使用公钥进行加密
参数:
message:待加密数据
public_key: str, 公钥字符串
返回值:
str,加密后的字符串
"""
message_length = len(message)
block_size = message_length / 117
if message_length % 117 != 0:
block_size += 1
cipher = get_cipher(public_key)
encrypted_message = []
for i in range(0, block_size):
if message_length > i * 117:
part_message = message[(i * 117):((i + 1) * 117)]
else:
part_message = message[i * 117:]
# 以上部分是为了处理加密数据太长进行的分段操作
part_encrypted_message = cipher.encrypt(part_message)
encrypted_message.append(part_encrypted_message)
ret = base64.b64encode(''.join(encrypted_message))
return ret
# 解密函数
def decrypt(encrypted_data, private_key):
"""
功能:使用私钥对参数进行解密,RSA ECB PKCS1Padding 解密。
1024密钥,对应最大的加密块大小117,最大密码块大小为128
参数:
encrypted_data: 加密后的参数
private_key: 自己的私钥
返回值:
str,解密后的字符串
"""
raw_data = base64.b64decode(encrypted_data)
assert len(raw_data) % 128 == 0, u'加密字符串长度不正确'
block_size = len(raw_data) / 128
cipher = get_cipher(private_key)
dsize = SHA.digest_size
sentinel = Random.new().read(15+dsize)
decrypted_messages = []
for i in range(0, block_size):
if len(raw_data) > i * 128:
part = raw_data[i * 128: (i + 1) * 128]
else:
part = raw_data[i * 128:]
part_decrypt_message = cipher.decrypt(part, sentinel)
decrypted_messages.append(part_decrypt_message)
return ''.join(decrypted_messages)
# 签名函数
def sign(data, key):
h = SHA.new(data)
# 首先生成RSA实例
rsa_private = RSA.importKey(key)
from Crypto.Signature import PKCS1_v1_5 as PKCS1V15
signer = PKCS1V15.new(rsa_private)
signature = signer.sign(h)
signature = base64.b64encode(signature)
return signature
# 验签函数
def check_sign(params, sign, public_key):
"""
功能:使用公钥验证签名内容
参数:
params dict, 待验证参数
sign str, 签名
public_key str, 公钥字符串
返回值:
true/false true表示验证通过;false表示验证失败;
"""
from Crypto.Signature import PKCS1_v1_5 as PKCS1V15
rsa_public = RSA.importKey(public_key)
verifier = PKCS1V15.new(rsa_public)
h = SHA.new(params)
return verifier.verify(h, base64.b64decode(sign))