Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
作者:mrr 发布时间:2022-12-10 13:55:18
标签:python,pycryptodome,加密,解密
Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签,具体代码如下所示:
#!/usr/bin/env python
# -*- coding: utf8 -*-
import os
import rsa
import json
import hashlib
import base64
from Crypto.Cipher import AES
from ..settings_manager import settings
class RSAEncrypter(object):
"""RSA加密解密
参考 https://stuvel.eu/python-rsa-doc/index.html
对应JavaScript版本参考 https://github.com/travist/jsencrypt
[description]
"""
@classmethod
def encrypt(cls, plaintext, keydata):
#明文编码格式
content = plaintext.encode('utf8')
if os.path.isfile(keydata):
with open(keydata) as publicfile:
keydata = publicfile.read()
pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(keydata)
#公钥加密
crypto = rsa.encrypt(content, pubkey)
return base64.b64encode(crypto).decode('utf8')
@classmethod
def decrypt(cls, ciphertext, keydata):
if os.path.isfile(keydata):
with open(keydata) as privatefile:
keydata = privatefile.read()
try:
ciphertext = base64.b64decode(ciphertext)
privkey = rsa.PrivateKey.load_pkcs1(keydata, format='PEM')
con = rsa.decrypt(ciphertext, privkey)
return con.decode('utf8')
except Exception as e:
pass
return False
@classmethod
def signing(cls, message, privkey):
""" 签名
https://legrandin.github.io/pycryptodome/Doc/3.2/Crypto.Signature.pkcs1_15-module.html
"""
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
if os.path.isfile(privkey):
with open(privkey) as privatefile:
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')
return sign
except Exception as e:
raise e
@classmethod
def verify(cls, message, sign, pubkey):
""" 验证签名
https://legrandin.github.io/pycryptodome/Doc/3.2/Crypto.Signature.pkcs1_15-module.html
"""
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
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) as e:
raise e
pass
except Exception as e:
raise e
pass
return res
class AESEncrypter(object):
def __init__(self, key, iv=None):
self.key = key.encode('utf8')
self.iv = iv if iv else bytes(key[0:16], 'utf8')
def _pad(self, text):
text_length = len(text)
padding_len = AES.block_size - int(text_length % AES.block_size)
if padding_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
return t3
def _unpad(self, text):
pad = ord(text[-1])
return text[:-pad]
def encrypt(self, raw):
raw = raw.encode('utf8')
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
encrypted = cipher.encrypt(raw)
return base64.b64encode(encrypted).decode('utf8')
def decrypt(self, enc):
enc = enc.encode('utf8')
enc = base64.b64decode(enc)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
decrypted = cipher.decrypt(enc)
return self._unpad(decrypted.decode('utf8'))
class AESSkyPay:
"""
Tested under Python 3.7 and pycryptodome
"""
BLOCK_SIZE = 16
def __init__(self, key):
#菲律宾支付通道 SkyPay Payment Specification.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
def pkcs5_pad(self,s):
"""
padding to blocksize according to PKCS #5
calculates the number of missing chars to BLOCK_SIZE and pads with
ord(number of missing chars)
@see: http://www.di-mgt.com.au/cryptopad.html
@param s: string to pad
@type s: string
@rtype: string
"""
BS = self.BLOCK_SIZE
return s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode('utf8')
def pkcs5_unpad(self,s):
"""
unpadding according to PKCS #5
@param s: string to unpad
@type s: string
@rtype: string
"""
return s[:-ord(s[len(s) - 1:])]
# 加密函数,如果text不足16位就用空格补足为16位,
# 如果大于16当时不是16的倍数,那就补足为16的倍数。
# 补足方法:PKCS5
def encrypt(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编码
return base64.b64encode(ciphertext).decode()
def decrypt(self, text):
cryptor = AES.new(self.key, self.mode)
plain_text = cryptor.decrypt(base64.b64decode(text))
return bytes.decode(self.pkcs5_unpad(plain_text))
def aes_decrypt(ciphertext, secret=None, prefix='aes:::'):
secret = secret if secret else settings.default_aes_secret
cipher = AESEncrypter(secret)
prefix_len = len(prefix)
if ciphertext[0:prefix_len]==prefix:
return cipher.decrypt(ciphertext[prefix_len:])
else:
return ciphertext
def aes_encrypt(plaintext, secret=None, prefix='aes:::'):
secret = secret if secret else settings.default_aes_secret
cipher = AESEncrypter(secret)
encrypted = cipher.encrypt(plaintext)
return '%s%s' % (prefix, encrypted)
if __name__ == "__main__":
try:
# for RSA test
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)
# for AES test
key = 'abc20304050607081q2w3e4r*1K|j!ta'
cipher = AESEncrypter(key)
plaintext = '542#1504'
encrypted = cipher.encrypt(plaintext)
print('Encrypted: %s' % encrypted)
ciphertext = 'EPLtushldq9E1U8vG/sL3g=='
assert encrypted == ciphertext
plaintext = '542#1504你好'
encrypted = '+YGDvnakKi77SBD6GXmThw=='
decrypted = cipher.decrypt(encrypted)
print('Decrypted: %s' % decrypted)
assert decrypted == plaintext
except KeyboardInterrupt:
sys.exit(0)
ps:Python3 RSA加密解密加签验签示例代码
本代码引入Pycryptodome基于Python3.50版本编译库
#!/usr/bin/env python3
# coding=utf-8
# Author: Luosu201803
"""
create_rsa_key() - 创建RSA密钥
my_encrypt_and_decrypt() - 测试加密解密功能
rsa_sign() & rsa_signverify() - 测试签名与验签功能
"""
from binascii import unhexlify
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5
import base64
from Crypto.Hash import SHA1
from Crypto.Signature import pkcs1_15
def create_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)
with open("my_private_rsa_key.pem", "wb") as f:
f.write(encrypted_key)
with open("my_rsa_public.pem", "wb") as f:
f.write(key.publickey().exportKey())
def encrypt_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)
def rsa_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()) #check wheather object of pkcs1_15 can be signed
#base64编码打印可视化
signature = base64.b64encode(pkcs1_15.new(private_key).sign(hash_obj))
return signature
def rsa_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('The signature is valid.')
return True
except (ValueError,TypeError):
print('The signature is invalid.')
if __name__ == '__main__':
# create_rsa_key()
encrypt_and_decrypt_test()
# message = b'Luosu is a Middle-aged uncle.'
# signature = rsa_sign(message)
# print('signature:',signature)
# print(rsa_signverify(message,signature))
总结
以上所述是小编给大家介绍的Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://gitee.com/leeyi/codes/iy39w07x6hc5b8uqm2oat31
0
投稿
猜你喜欢
- 异常的参数一个异常可以带上参数,可作为输出的异常信息参数。你可以通过except语句来捕获异常的参数,如下所示:变量接收的异常值通常包含在异
- select user_name,count(*) as count from user_table group by user_name
- zip即将多个可迭代对象组合为一个可迭代的对象,每次组合时都取出对应顺序的对象元素组合为元组,直到最少的对象中元素全部被组合,剩余的其他对象
- 由于工作关系,只能暂时放弃对mongodb的研究了 .开始研究PHPcms .目前为止我已经基本完成了模块的开发.趁着周末来这里做个总结.我
- 目前很多网站都使用ajax技术动态加载数据,和常规的网站不一样,数据时动态加载的,如果我们使用常规的方法爬取网页,得到的只是一堆html代码
- 1、搭载QT环境按win+R输入 pip install pyqt5 下载QT5 当然也可以去Qt的官网的下载 ,使用命令行更快捷方便 所以
- 如下所示:import cv2 # [1]导入OpenCv开源库import numpy as npimage_path = "F
- js的成员和方法好象没有private和public之分,列一下public的成员和方法成员:name 控件的名字,既这个控件的变量名(必选
- #/bin/sh #检测mysql server是否正常提供服务 mysqladmin -u sky -ppwd -h localhost
- 1.理论只要两个表的公共字段有匹配值,就将这两个表中的记录组合起来。个人理解:以一个共同的字段求两个表中符合要求的交集,并将每个表符合要求的
- 1 安装pyqt51.1 安装pyqt5pip install PyQt51.2 安装pyqt5常用工具包pip install PyQt5
- 在网上有很多文章介绍数据库优化知识,但是大部份文章只是对某个一个方面进行说明,而对于我们程序员来说这种介绍并不能很好的掌握优化知识,因为很多
- 前言本文中所有的代码使用 JavaScript 编写,但你也可以用其他兼容 JSR 223 的脚本语言。这些例子可作为脚本文件也可以在交互式
- cgo 使得在 Golang 中可以使用 C 代码。Hello World为了有一个较为直观的了解,我们来看一个简单的例子,创建文件 mai
- Delphi连接MySQL真麻烦,研究了一天,从网上找了无数文章,下载了无数插件都没解决。最后返璞归真,老老实实用ADO来连接,发现也不是很
- 今天学到Python 有一个名为 random 的内置模块,可用于生成随机数,这个好玩~可以用来做为上课随机点名的程序了哈哈。。def ma
- 一、文本文件文本文件,主要包括csv和txt两种等,相应接口为read_csv()和to_csv(),分别用于读写数据1. read_csv
- arange()类似于内置函数range(),通过指定开始值、终值和步长创建表示等差数列的一维数组,注意得到的结果数组不包含终值。linsp
- 目录问题描述解决方案问题分析问题描述在 MySQL 中使用 delete 语句删除数据之后,监控视图中可用的磁盘空间没有增加,磁盘使用率没有
- 关于Pillow与PILPIL(Python Imaging Library)是Python一个强大方便的图像处理库,名气也比较大。不过只支