Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
Python3.7基于pycryptodome的AES加密解密、RSA加密解密、加签验签,具体代码如下所示:
#!/usr/bin/envpython
#-*-coding:utf8-*-
importos
importrsa
importjson
importhashlib
importbase64
fromCrypto.CipherimportAES
from..settings_managerimportsettings
classRSAEncrypter(object):
"""RSA加密解密
参考https://stuvel.eu/python-rsa-doc/index.html
对应JavaScript版本参考https://github.com/travist/jsencrypt
[description]
"""
@classmethod
defencrypt(cls,plaintext,keydata):
#明文编码格式
content=plaintext.encode('utf8')
ifos.path.isfile(keydata):
withopen(keydata)aspublicfile:
keydata=publicfile.read()
pubkey=rsa.PublicKey.load_pkcs1_openssl_pem(keydata)
#公钥加密
crypto=rsa.encrypt(content,pubkey)
returnbase64.b64encode(crypto).decode('utf8')
@classmethod
defdecrypt(cls,ciphertext,keydata):
ifos.path.isfile(keydata):
withopen(keydata)asprivatefile:
keydata=privatefile.read()
try:
ciphertext=base64.b64decode(ciphertext)
privkey=rsa.PrivateKey.load_pkcs1(keydata,format='PEM')
con=rsa.decrypt(ciphertext,privkey)
returncon.decode('utf8')
exceptExceptionase:
pass
returnFalse
@classmethod
defsigning(cls,message,privkey):
"""签名
https://legrandin.github.io/pycryptodome/Doc/3.2/Crypto.Signature.pkcs1_15-module.html
"""
fromCrypto.Signatureimportpkcs1_15
fromCrypto.HashimportSHA256
fromCrypto.PublicKeyimportRSA
ifos.path.isfile(privkey):
withopen(privkey)asprivatefile:
privkey=privatefile.read()
try:
key=RSA.import_key(privkey)
h=SHA256.new(message.encode('utf8'))
sign=pkcs1_15.new(key).sign(h)
sign=base64.b64encode(sign).decode('utf8')
returnsign
exceptExceptionase:
raisee
@classmethod
defverify(cls,message,sign,pubkey):
"""验证签名
https://legrandin.github.io/pycryptodome/Doc/3.2/Crypto.Signature.pkcs1_15-module.html
"""
fromCrypto.Signatureimportpkcs1_15
fromCrypto.HashimportSHA256
fromCrypto.PublicKeyimportRSA
res=False
sign=base64.b64decode(sign)
#print('sign',type(sign),sign)
try:
key=RSA.importKey(pubkey)
h=SHA256.new(message.encode('utf8'))
pkcs1_15.new(key).verify(h,sign)
res=True
except(ValueError,TypeError)ase:
raisee
pass
exceptExceptionase:
raisee
pass
returnres
classAESEncrypter(object):
def__init__(self,key,iv=None):
self.key=key.encode('utf8')
self.iv=ivifivelsebytes(key[0:16],'utf8')
def_pad(self,text):
text_length=len(text)
padding_len=AES.block_size-int(text_length%AES.block_size)
ifpadding_len==0:
padding_len=AES.block_size
t2=chr(padding_len)*padding_len
t2=t2.encode('utf8')
#print('text',type(text),text)
#print('t2',type(t2),t2)
t3=text+t2
returnt3
def_unpad(self,text):
pad=ord(text[-1])
returntext[:-pad]
defencrypt(self,raw):
raw=raw.encode('utf8')
raw=self._pad(raw)
cipher=AES.new(self.key,AES.MODE_CBC,self.iv)
encrypted=cipher.encrypt(raw)
returnbase64.b64encode(encrypted).decode('utf8')
defdecrypt(self,enc):
enc=enc.encode('utf8')
enc=base64.b64decode(enc)
cipher=AES.new(self.key,AES.MODE_CBC,self.iv)
decrypted=cipher.decrypt(enc)
returnself._unpad(decrypted.decode('utf8'))
classAESSkyPay:
"""
TestedunderPython3.7andpycryptodome
"""
BLOCK_SIZE=16
def__init__(self,key):
#菲律宾支付通道SkyPayPaymentSpecification.lending.v1.16.pdf
#SkyPay对密码做了如下处理
s1=hashlib.sha1(bytes(key,encoding='utf-8')).digest()
s2=hashlib.sha1(s1).digest()
self.key=s2[0:16]
self.mode=AES.MODE_ECB
defpkcs5_pad(self,s):
"""
paddingtoblocksizeaccordingtoPKCS#5
calculatesthenumberofmissingcharstoBLOCK_SIZEandpadswith
ord(numberofmissingchars)
@see:http://www.di-mgt.com.au/cryptopad.html
@params:stringtopad
@types:string
@rtype:string
"""
BS=self.BLOCK_SIZE
returns+((BS-len(s)%BS)*chr(BS-len(s)%BS)).encode('utf8')
defpkcs5_unpad(self,s):
"""
unpaddingaccordingtoPKCS#5
@params:stringtounpad
@types:string
@rtype:string
"""
returns[:-ord(s[len(s)-1:])]
#加密函数,如果text不足16位就用空格补足为16位,
#如果大于16当时不是16的倍数,那就补足为16的倍数。
#补足方法:PKCS5
defencrypt(self,text):
cryptor=AES.new(self.key,self.mode)
#这里密钥key长度必须为16(AES-128),
#24(AES-192),或者32(AES-256)Bytes长度
#目前AES-128足够目前使用
ciphertext=cryptor.encrypt(self.pkcs5_pad(text.encode('utf8')))
#因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
#所以这里将加密的字符串进行base64编码
returnbase64.b64encode(ciphertext).decode()
defdecrypt(self,text):
cryptor=AES.new(self.key,self.mode)
plain_text=cryptor.decrypt(base64.b64decode(text))
returnbytes.decode(self.pkcs5_unpad(plain_text))
defaes_decrypt(ciphertext,secret=None,prefix='aes:::'):
secret=secretifsecretelsesettings.default_aes_secret
cipher=AESEncrypter(secret)
prefix_len=len(prefix)
ifciphertext[0:prefix_len]==prefix:
returncipher.decrypt(ciphertext[prefix_len:])
else:
returnciphertext
defaes_encrypt(plaintext,secret=None,prefix='aes:::'):
secret=secretifsecretelsesettings.default_aes_secret
cipher=AESEncrypter(secret)
encrypted=cipher.encrypt(plaintext)
return'%s%s'%(prefix,encrypted)
if__name__=="__main__":
try:
#forRSAtest
ciphertext='Qa2EU2EF4Eq4w75TnA1IUw+ir9l/nSdW3pMV+a6FkzV9bld259DxM1M4RxYkpPaVXhQFol04yFjuxzkRg12e76i6pkDM1itQSOy5hwmrud5PQvfnBf7OmHpOpS6oh6OQo72CA0LEzas+OANmRXKfn5CMN14GsmfWAn/F6j4Azhs='
public_key='/Users/leeyi/workspace/joywin_staff/joywin_staff_api/datas/public.pem'
private_key='/Users/leeyi/workspace/joywin_staff/joywin_staff_api/datas/private.pem'
ciphertext=RSAEncrypter.encrypt('admin888中国',public_key)
print("ciphertext:",ciphertext)
plaintext=RSAEncrypter.decrypt(ciphertext,private_key)
print("plaintext:",type(plaintext))
print("plaintext:",plaintext)
#forAEStest
key='abc20304050607081q2w3e4r*1K|j!ta'
cipher=AESEncrypter(key)
plaintext='542#1504'
encrypted=cipher.encrypt(plaintext)
print('Encrypted:%s'%encrypted)
ciphertext='EPLtushldq9E1U8vG/sL3g=='
assertencrypted==ciphertext
plaintext='542#1504你好'
encrypted='+YGDvnakKi77SBD6GXmThw=='
decrypted=cipher.decrypt(encrypted)
print('Decrypted:%s'%decrypted)
assertdecrypted==plaintext
exceptKeyboardInterrupt:
sys.exit(0)
ps:Python3RSA加密解密加签验签示例代码
本代码引入Pycryptodome基于Python3.50版本编译库
#!/usr/bin/envpython3
#coding=utf-8
#Author:Luosu201803
"""
create_rsa_key()-创建RSA密钥
my_encrypt_and_decrypt()-测试加密解密功能
rsa_sign()&rsa_signverify()-测试签名与验签功能
"""
frombinasciiimportunhexlify
fromCrypto.PublicKeyimportRSA
fromCrypto.CipherimportPKCS1_OAEP,PKCS1_v1_5
importbase64
fromCrypto.HashimportSHA1
fromCrypto.Signatureimportpkcs1_15
defcreate_rsa_key(password="123456"):
"""
创建RSA密钥,步骤说明:
1、从Crypto.PublicKey包中导入RSA,创建一个密码(此密码不是RSA秘钥对)
2、生成1024/2048位的RSA密钥对(存储在私钥文件和公钥文件)
3、调用RSA密钥实例的exportKey方法(传入"密码"、"使用的PKCS标准"、"加密方案"这三个参数)得到私钥。
4、将私钥写入磁盘的文件。
5、使用方法链调用publickey和exportKey方法生成公钥,写入磁盘上的文件。
"""
key=RSA.generate(1024)
encrypted_key=key.exportKey(passphrase=password,pkcs=8,protection="scryptAndAES128-CBC")
#encrypted_key=key.exportKey(pkcs=1)
print('encrypted_key:',encrypted_key)
withopen("my_private_rsa_key.pem","wb")asf:
f.write(encrypted_key)
withopen("my_rsa_public.pem","wb")asf:
f.write(key.publickey().exportKey())
defencrypt_and_decrypt_test(password="123456"):
#加载私钥用于加密
recipient_key=RSA.import_key(
open("my_rsa_public.pem").read()
)
cipher_rsa=PKCS1_v1_5.new(recipient_key)
#使用base64编码保存数据方便查看,同样解密需要base64解码
en_data=base64.b64encode(cipher_rsa.encrypt(b"123456,abcdesd"))
print("加密数据信息:",type(en_data),'\n',len(en_data),'\n',en_data)
#加载公钥用于解密
encoded_key=open("my_private_rsa_key.pem").read()
private_key=RSA.import_key(encoded_key,passphrase=password)
cipher_rsa=PKCS1_v1_5.new(private_key)
data=cipher_rsa.decrypt(base64.b64decode(en_data),None)
print(data)
defrsa_sign(message,password="123456"):
#读取私钥信息用于加签
private_key=RSA.importKey(open("my_private_rsa_key.pem").read(),passphrase=password)
hash_obj=SHA1.new(message)
#print(pkcs1_15.new(private_key).can_sign())#checkwheatherobjectofpkcs1_15canbesigned
#base64编码打印可视化
signature=base64.b64encode(pkcs1_15.new(private_key).sign(hash_obj))
returnsignature
defrsa_signverify(message,signature):
#读取公钥信息用于验签
public_key=RSA.importKey(open("my_rsa_public.pem").read())
#message做“哈希”处理,RSA签名这么要求的
hash_obj=SHA1.new(message)
try:
#因为签名被base64编码,所以这里先解码,再验签
pkcs1_15.new(public_key).verify(hash_obj,base64.b64decode(signature))
print('Thesignatureisvalid.')
returnTrue
except(ValueError,TypeError):
print('Thesignatureisinvalid.')
if__name__=='__main__':
#create_rsa_key()
encrypt_and_decrypt_test()
#message=b'LuosuisaMiddle-ageduncle.'
#signature=rsa_sign(message)
#print('signature:',signature)
#print(rsa_signverify(message,signature))
总结
以上所述是小编给大家介绍的Python3.7基于pycryptodome的AES加密解密、RSA加密解密、加签验签,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!