侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签

Python  /  管理员 发布于 7年前   250

Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签,具体代码如下所示:

#!/usr/bin/env python# -*- coding: utf8 -*-import osimport rsaimport jsonimport hashlibimport base64from Crypto.Cipher import AESfrom ..settings_manager import settingsclass 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 resclass 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 ciphertextdef 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 unhexlifyfrom Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5import base64from Crypto.Hash import SHA1from Crypto.Signature import pkcs1_15def 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 signaturedef 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加密解密、加签验签,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!


  • 上一条:
    python3实现绘制二维点图
    下一条:
    Python3.7基于hashlib和Crypto实现加签验签功能(实例代码)
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客