由于自身与客户经常对接业务接口,对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
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读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
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数