PYTHON RSA 使用私钥加密公钥解密独家解决方案_typeerror: this is not a private key-程序员宅基地

技术标签: rsa  加密解密  python  PYTHON  

由于自身与客户经常对接业务接口,对RSA加密的方式有一些了解。通常我们客户用的是PHP或JAVA较多,像PYTHON这样的客户很少,近期就碰到一个客户用的就是这个语言,但研究了很久发现PYTHON语言中一些已知库中里面RSA加密没有提供[私钥加密公钥解密的方法]。接下来说正题!

灵感来源于C#中的Org.BouncyCastle.Crypto.Engines一段代码

public BigInteger ProcessBlock( BigInteger input)
        {
            if (key is RsaPrivateCrtKeyParameters)  //这里判断了KEY是否为私钥,如果不是私钥看返回的代码
            {
                //
                // we have the extra factors, use the Chinese Remainder Theorem - the author
                // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
                // advice regarding the expression of this.
                //
                RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters)key;

                BigInteger p = crtKey.P;;
                BigInteger q = crtKey.Q;
                BigInteger dP = crtKey.DP;
                BigInteger dQ = crtKey.DQ;
                BigInteger qInv = crtKey.QInv;

                BigInteger mP, mQ, h, m;

                // mP = ((input Mod p) ^ dP)) Mod p
                mP = (input.Remainder(p)).ModPow(dP, p);

                // mQ = ((input Mod q) ^ dQ)) Mod q
                mQ = (input.Remainder(q)).ModPow(dQ, q);

                // h = qInv * (mP - mQ) Mod p
                h = mP.Subtract(mQ);
                h = h.Multiply(qInv);
                h = h.Mod(p);               // Mod (in Java) returns the positive residual

                // m = h * q + mQ
                m = h.Multiply(q);
                m = m.Add(mQ);

                return m;
            }

            return input.ModPow(key.Exponent, key.Modulus);//这个代码给了我启发
        }

经过以上的案例,于是我在PYTHON中Crypto库中找到加密的代码

文件名:RSA.PY  路径:Crypto\PublicKey\RSA.py

下载下载RSA.PY(将此文件替换CRYPTO库中的Crypto\PublicKey\RSA.py替换,使用以下方法)

为了保证源方法不变的情况做了以下修改

修改内容:增加方法:has_public(判断是否为公钥),修改_decrypt,_encrypt (修改加解密方法使其支持私钥加密公钥解密)代码如下:

    def has_public(self):
        """Whether this is an RSA public key"""
        return hasattr(self,"_e") and not self.has_private()


    def _encrypt(self, plaintext):
        if not 0 <= plaintext < self._n:
            raise ValueError("Plaintext too large")
        if self.has_public():
            return int(pow(Integer(plaintext), self._e, self._n))
        elif self.has_private():
            return int(pow(Integer(plaintext), self._d, self._n))
        else:
            raise TypeError("This is not a key")


    def _decrypt(self, ciphertext):
        if not 0 <= ciphertext < self._n:
            raise ValueError("Ciphertext too large")
        if self.has_private():
            # raise TypeError("This is not a private key")

            # Blinded RSA decryption (to prevent timing attacks):
            # Step 1: Generate random secret blinding factor r,
            # such that 0 < r < n-1
            r = Integer.random_range(min_inclusive=1, max_exclusive=self._n)
            # Step 2: Compute c' = c * r**e mod n
            cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n
            # Step 3: Compute m' = c'**d mod n       (normal RSA decryption)
            m1 = pow(cp, self._dp, self._p)
            m2 = pow(cp, self._dq, self._q)
            h = ((m2 - m1) * self._u) % self._q
            mp = h * self._p + m1
            # Step 4: Compute m = m**(r-1) mod n
            result = (r.inverse(self._n) * mp) % self._n
            # Verify no faults occurred
            if ciphertext != pow(result, self._e, self._n):
                raise ValueError("Fault detected in RSA decryption")
            return result
        elif self.has_public():
            return pow(Integer(ciphertext), self._e, self._n)
        else:
            raise TypeError("This is not a key")

PYTHON加解密方法:

1、读取证书CER/PFX扩展名文件  文件:RsaReadUtil.py

from OpenSSL import crypto

class RsaReadUtil:

    @staticmethod
    def get_private_key(pfx_file_path,password):
        pfx = crypto.load_pkcs12(open(pfx_file_path,'rb').read(),password)
        res = crypto.dump_privatekey(crypto.FILETYPE_PEM,pfx.get_privatekey())
        return res.strip()

    @staticmethod
    def get_public_key(cer_file_path):
        cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cer_file_path, "rb").read())
        res = crypto.dump_publickey(crypto.FILETYPE_PEM, cert.get_pubkey()).decode("utf-8")
        return res.strip()

2、核心加解密方法,支持公钥加密私钥解密,私钥加密公钥解密

from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_cipper
from Crypto.PublicKey import RSA


import binascii
import base64
import  RsaReadUtil

class RsaUtil:
    @staticmethod
    def En_Core(srcdata,publick_keys):
        rsakey = RSA.importKey(publick_keys)
        cipher = PKCS1_v1_5_cipper.new(rsakey)
        block_size = int(rsakey.n.bit_length() / 8 - 11)
        en_code_data = base64.b64encode(str(srcdata).encode("utf-8"))
        print(en_code_data)
        en_data = bytes()
        while en_code_data:
            input_data = en_code_data[:block_size]
            en_code_data = en_code_data[block_size:]
            en_data += cipher.encrypt(input_data)
        return en_data.hex()

    @staticmethod
    def En_Public(src_data,cer_key_path):
        # ---公钥加密---#
        return RsaUtil.En_Core(src_data, RsaReadUtil.RsaReadUtil.get_public_key(cer_key_path))

    @staticmethod
    def En_Private(src_data,pfx_key_path,pfx_pwd):
        # ---私钥加密---#
        return RsaUtil.En_Core(src_data,RsaReadUtil.RsaReadUtil.get_private_key(pfx_key_path,pfx_pwd))

    @staticmethod
    def De_Core(srcdata,private_kes):
        rsakey = RSA.importKey(private_kes)
        cipher = PKCS1_v1_5_cipper.new(rsakey)
        block_size = int(rsakey.n.bit_length() / 8)

        de_code_data = binascii.unhexlify(srcdata)
        out_data = bytes()
        while de_code_data:
            input_data = de_code_data[:block_size]
            de_code_data = de_code_data[block_size:]
            out_data += cipher.decrypt(input_data,'')
        return str(base64.b64decode(out_data),encoding="utf-8")

    @staticmethod
    def De_Private(src_data,pfx_key_path,pfx_pwd):
        # ---私钥解密---#
        return RsaUtil.De_Core(src_data,RsaReadUtil.RsaReadUtil.get_private_key(pfx_key_path,pfx_pwd))

    @staticmethod
    def De_Public(src_data,cer_key_path):
        # ---公钥解密---#
        return RsaUtil.De_Core(src_data,RsaReadUtil.RsaReadUtil.get_public_key(cer_key_path))

3、测试代码:

import RsaUtil
from SignatureUtil import Signature

cer_path = "D:\\********.cer"
pfx_path = "D:\\*******.pfx"
pfx_pwd = "*****"

desc = "把导出私钥及设置的密码和下载的配到生产环境"
print(desc)
print("私钥加密>>>")
pub_en_str = RsaUtil.RsaUtil.En_Private(desc,pfx_path,pfx_pwd)
print(pub_en_str)
print("公钥解密>>>")
pri_de_str = RsaUtil.RsaUtil.De_Public(pub_en_str,cer_path)
print(pri_de_str)

print("公钥加密>>>")
pub_en_str = RsaUtil.RsaUtil.En_Public(desc,cer_path)
print(pub_en_str)

print("私钥解密>>>")
pri_de_str = RsaUtil.RsaUtil.De_Private(pub_en_str,pfx_path,pfx_pwd)
print(pri_de_str)

以上代码测试OK

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yjjihmtd/article/details/121651841

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签