Python 利用PYQT5设计基于RSA算法盲签名的匿名化电子支付系统设计与实现

基于RSA算法的盲签名算法

        David Chaum 于1982年提出盲签名的概念,并利用RSA算法设计了第一个盲签名方案. 该方案的安全性基于大整数分解问题

盲签名的步骤

1.密钥生成

签名者执行以下步骤生成密钥对:

①签名者选择两个大素数p,q, 计算n=pq, φ(n)=(p-1)(q-1);

②签名者选择两个大整数e,d, 满足ed =1 mod φ(n), gcd(e, φ(n))= 1;

③签名者保存私钥(d,n), 并公开公钥(e, n)和安全哈希函数H:{0,1}*→Zn*.

2.盲化

①用户选择随机数r∈R Zn*, 计算m' = re H(m) mod n,其中m是待签名的消息;

②用户将盲化的消息m'发送给签名者.

 3.签名

签名者计算σ' ≡ m' d  mod n ,并将 σ' 发送给用户。

4.去盲化

用户计算σ ≡ σ' r-1  mod n

r-1是盲化因子的逆元

 5.签名正确性验证

用户通过验证σe ≡ H(m) mod n

详细设计

我们为这个基于盲签名的匿名化电子支付系统设计了服务端(交易方)和用户端(被交易方)。和一个管理系统

1.密钥生成

        使用RSA模块的generate生成密钥对

# 生成 RSA 密钥对
def generate_rsa_key_pair():private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)public_key = private_key.public_key()return private_key, public_key

2.生成盲化因子

        使用secrets.randbits(1024)生成一个1024位的随机数,再用Miller-Rabin算法检查n是否是素数当n为素数的时候输出为盲化因子

def generate_blinding_factor():# 生成盲化因子(一个1024位的随机素数)while True:prime_candidate = secrets.randbits(1024)if is_prime(prime_candidate):return prime_candidatedef is_prime(n, k=5):# 用Miller-Rabin算法检查n是否是素数if n < 2: return Falsefor p in [2,3,5,7,11,13,17,19,23,29]:if n % p == 0: return n == ps, d = 0, n - 1while d % 2 == 0:s, d = s + 1, d // 2for i in range(k):x = pow(secrets.randbelow(n-3) + 2, d, n)if x == 1 or x == n - 1: continuefor r in range(s - 1):x = pow(x, 2, n)if x == n - 1: breakelse:return Falsereturn True

3.消息盲化

        发送者使用盲化因子 k 对原始消息 m 进行盲化操作,生成盲化后的消息 m'。公钥 e 和 n 是接收者的公钥,在进行盲化和解盲化操作时需要使用。m‘=mk^emod(n)

def blind_hide_msg(msg, factor, e, n):hide_msg = (msg * pow(factor, e, n)) % nreturn hide_msg

4.接收方签名

接收方计算s’=(m’)^d(mod n)并把计算后的签名值s’发送给发送方

def blind_signature(blind_msg, d, n):blind_sig = pow(blind_msg, d, n)return blind_sig

5.解盲

        签名者将签名值 s' 发送回给发送者。发送者使用盲化因子的逆元素和签名值 s1 结合起来计算原始消息 m 的数字签名 s。

def blind_retrieve_sig(blind_sig, factor, n):inverse = pow(factor, -1, n)signature = (blind_sig * inverse) % nreturn signature

6.验证盲签名 

         发送方计算接收方发送的s‘,并计算出原始的消息m的数字签名 s=s’k^−1(mod n) 与接收方计算的数字签名进行一个比较,如果相同接收方验证盲签名成功! 用户通过验证s‘e ≡ H(m) mod n来验证盲签名

verification_result = pow(unblinded_signature2,e1,n1)

算法运行截图

完整算法代码

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import binascii
import secrets
import gmpy2
import hashlib
import random
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Cryptodome.Util.number import inversedef blind_hide_msg(msg, factor, e, n):hide_msg = (msg * pow(factor, e, n)) % nreturn hide_msgdef blind_signature(blind_msg, d, n):blind_sig = pow(blind_msg, d, n)return blind_sig# 判断是否为素数
def is_prime(num):if num <= 1:return Falsefor i in range(2, int(num**0.5) + 1):if num % i == 0:return Falsereturn Truedef generate_blinding_factor():# 生成盲化因子(一个1024位的随机素数)while True:prime_candidate = secrets.randbits(1024)if is_prime(prime_candidate):return prime_candidatedef is_prime(n, k=5):# 用Miller-Rabin算法检查n是否是素数if n < 2: return Falsefor p in [2,3,5,7,11,13,17,19,23,29]:if n % p == 0: return n == ps, d = 0, n - 1while d % 2 == 0:s, d = s + 1, d // 2for i in range(k):x = pow(secrets.randbelow(n-3) + 2, d, n)if x == 1 or x == n - 1: continuefor r in range(s - 1):x = pow(x, 2, n)if x == n - 1: breakelse:return Falsereturn True# 生成 RSA 密钥对
def generate_rsa_key_pair():private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)public_key = private_key.public_key()return private_key, public_key# 保存密钥到文件
def save_key_to_file(key, filename):pem = key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())with open(filename, 'wb') as f:f.write(pem)# 从文件中加载密钥
def load_key_from_file(filename):with open(filename, 'rb') as f:pem = f.read()key = serialization.load_pem_private_key(pem, password=None)return keydef blind_retrieve_sig(blind_sig, factor, n):inverse = pow(factor, -1, n)signature = (blind_sig * inverse) % nreturn signature#--------------`--------------------------------------------------------------------------------
# 生成 RSA 密钥对
private_key, public_key = generate_rsa_key_pair()
bank_private_key, bank_public_key = generate_rsa_key_pair()# 保存私钥到文件
private_key_file = "private_key.pem"
private_key_file2 = "bank_private_key.pem"
save_key_to_file(private_key, private_key_file)
save_key_to_file(bank_private_key,private_key_file2)
# 保存公钥到文件
public_key_file = "public_key.pem"
public_key_file2 = "bank_public_key.pem"
with open(public_key_file, 'wb') as f:f.write(public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo))
with open(public_key_file2, 'wb') as f:f.write(public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo))# 从文件中加载密钥
loaded_private_key = load_key_from_file(private_key_file)
loaded_bank_private_key = load_key_from_file(private_key_file2)
loaded_public_key = serialization.load_pem_public_key(open(public_key_file, 'rb').read())
loaded_bank_public_key = serialization.load_pem_public_key(open(public_key_file2, 'rb').read())# 从加载的密钥中提取模数 n、私钥指数 d 和公钥指数 e
n = loaded_private_key.private_numbers().public_numbers.n
d = loaded_private_key.private_numbers().d
e = loaded_public_key.public_numbers().e# 从加载的密钥中提取模数 n、私钥指数 d 和公钥指数 e
n1 = loaded_bank_private_key.private_numbers().public_numbers.n
d1 = loaded_bank_private_key.private_numbers().d
e1 = loaded_bank_public_key.public_numbers().e# 清除返回值对象,防止泄露信息
loaded_private_key = None
loaded_public_key = Noneprint("n:", n)
print("d:", d)
print("e:", e)
print("n1:", n1)
print("d1:", d1)
print("e1:", e1)m =1234
# 生成盲化因子Alice选择一个随机数  k 作为盲化因子
k = generate_blinding_factor()
print("blinding factor",k)#generate_blinding_factor()函数使用secrets.randbits(1024)生成一个随机的1024位素数作为盲化因子。
#is_prime()函数使用Miller-Rabin算法检查整数是否是素数。然后,blind_message()函数将盲化因子应用于消息,以生成盲化的消息和盲化因子的值。
#1.发送者使用盲化因子 k 对原始消息 m 进行盲化操作,生成盲化后的消息 m'。公钥 e 和 n 是接收者的公钥,在进行盲化和解盲化操作时需要使用。
m1 = blind_hide_msg(m,k, e1, n1)#盲化
print("盲化后的消息 m':",m1)
#发送者将盲化后的消息 m1 发送给签名者。#2.签名者使用私钥对盲化后的消息 m1 进行解密操作,生成签名值 s1。 d1和n1是签名者银行的私钥
s1 = blind_signature(m1, d1, n1)
print("签名值 s'", s1)
real_sig = pow(m, d1, n1)
print("原签名 =", real_sig)#3.签名者将签名值 s' 发送回给发送者。发送者使用盲化因子的逆元素和签名值 s1 结合起来计算原始消息 m 的数字签名 s。
unblinded_signature2=blind_retrieve_sig(s1,k, n1)
print("解盲后", unblinded_signature2)if unblinded_signature2==real_sig:print("验证成功!!!!")
else:print("验证失败")hash_value = hashlib.sha256(str(m).encode()).digest()
# 4验证数字签名
verification_result = pow(unblinded_signature2,e1,n1)
# 计算验证结果的哈希值
verification_bytes = verification_result.to_bytes((verification_result.bit_length() + 7) // 8, byteorder="big")
verification_hash = hashlib.sha256(verification_bytes).digest()
print("verification_hash",verification_hash)
print("unblinded_signature2",unblinded_signature2)
# 将哈希值转换为整数类型
hash_int = int.from_bytes(hash_value, byteorder="big")# 检查验证结果是否与哈希值一致
if verification_result == m:print("数字签名验证通过")
else:print("数字签名验证失败")

系统测试

系统执行流程图

        本系统的执行过程如图所示。首先客户端用户查询要发送的对象,然后用户输入要盲化的金额、输入发送对象名、输入备注,然后使用密钥对金额进行盲化,并将这些信息作为盲化请求发送给服务端,服务端用户首先可以查看到用户发送过来的盲化请求,然后输入序号可以下载密钥,然后解密,再用密钥生成自己的签名值,发送给客户端用户,客户端用户接收到该签名值之后用密钥解盲。

用户查询发送对象

客户端用户先点击按钮按钮查询可发送的对象。

用户发送信息

        用户输入要交易(盲化)的金额,输入要发送的对象名,输入备注,点击发送按钮将这些值以及盲化金额发送给交易方。

服务端(交易方)可以查询被交易方发过来的盲化请求。

下载用户公钥,交易方下载密钥。

 签名者验证发送方身份

服务端生成签名值

然后点击按钮将该值发送给客户端用户。

发送方接收到服务端返回的签名进行解盲

发送方解盲后发送给第三方,第三方验证签名

第三方验证签名

数据库设计 

数据表建立语句

验证签名表
CREATE TABLE `verify_sign` (`id` int NOT NULL AUTO_INCREMENT,`userfrom` varchar(255) DEFAULT NULL,`d` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci用户信息表
CREATE TABLE `user_info` (`id` int NOT NULL AUTO_INCREMENT,`userfrom` varchar(255) DEFAULT NULL,`m` text,`k` text,`n` text,`e` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
服务端盲签名回应表
CREATE TABLE `blind_response2` (`id` int NOT NULL AUTO_INCREMENT,`userfrom` varchar(255) DEFAULT NULL,`userto` varchar(255) DEFAULT NULL,`sign_sig` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
客户端用户请求发送表
CREATE TABLE `blind_payrequest2` (`id` int NOT NULL AUTO_INCREMENT,`userfrom` varchar(255) DEFAULT NULL,`userto` varchar(255) DEFAULT NULL,`payment_description` varchar(255) DEFAULT NULL,`payment_time` datetime DEFAULT NULL,`payment_amount` text,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
用户密钥表
CREATE TABLE `user_keys` (`id` int NOT NULL AUTO_INCREMENT,`user` varchar(255) DEFAULT NULL,`public_key` TEXT,`private_key` TEXT,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/605327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OpenVINO 】在 MacOS 上编译 OpenVINO C++ 项目

前言 英特尔公司发行的模型部署工具OpenVINO™模型部署套件&#xff0c;可以实现在不同系统环境下运行&#xff0c;且发布的OpenVINO™ 2023最新版目前已经支持MacOS系统并同时支持在苹果M系列芯片上部署模型。在该项目中&#xff0c;我们将向大家展示如何在MacOS系统、M2芯片的…

编写一个简单的服务和客户端(C++)

背景 当节点使用服务进行通信时&#xff0c;发送数据请求的节点称为客户端节点&#xff0c;响应请求的节点称为服务节点。请求和响应的结构由.srv文件确定。 这里使用的例子是一个简单的整数加法系统&#xff1b;一个节点请求两个整数之和&#xff0c;另一个节点响应结果。 …

基于云平台技术的车辆远程诊断浅谈

基于云平台技术的车辆远程诊断浅谈 一、引言 随着汽车工业的不断发展&#xff0c;车辆故障诊断技术的需求日益增长。传统的车辆故障诊断方式已经无法满足现代汽车对高效、智能的追求。基于云平台技术的车辆远程诊断创新&#xff0c;为汽车故障诊断带来了新的解决方案。 二、…

【linux】docker基本概念和基础指令操作(镜像、容器)

docker docker镜像 images xxxx(名称):xxxx(版本号) 每一个image可以生成若干个容器&#xff08;container&#xff09;&#xff0c;所有用相同镜像生成的容器环境完全一样 每一个容器都是一个完全独立的云端服务器 镜像指令 docker pull ubuntu:20.04 #拉取一个镜像 doc…

鸿鹄电子招投标系统源码实现与立项流程:基于Spring Boot、Mybatis、Redis和Layui的企业电子招采平台

随着企业的快速发展&#xff0c;招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求&#xff0c;建立一个公平、公开、公正的采购环境至关重要。在这个背景下&#xff0c;我们开发了一款电子招标采购软件&#xff0c;以最大限度地控制采购成本&#…

HarmonyOS应用开发者基础(初级)认证题库

开发者能力认证 一、判断 首选项preferences是以Key-Value形式存储数据&#xff0c;其中Key是可以重复。&#xff08;错&#xff09;使用http模块发起网络请求时&#xff0c;必须要使用on(‘headersReceive’&#xff09;订阅请求头&#xff0c;请求才会成功。&#xff08;错…

15.脚本备份、恢复达梦DM数据库

1.备份脚本 #!/bin/bash # 通过docker命令查询达梦数据库容器id CONTAINER_IDdocker ps -a | grep "dm8_single" | awk {print $1} | head -n 1#备份目录 DUMP_DIR"/data/dm8/data/backup"DATE_FORMATdate %Y%m%d echo "备份my_db1数据库开始&#…

从零开始构建一个属于您的 Web3 项目(Web3项目三实战之一)

午后,沏上一壶茶,走到那冬日暖阳照耀到的阳台,落座于桌旁,很是舒心地敲打键盘上的每个按键,这样的午后,或许才是我们所向往的吧! 它舍弃了城市中的喧嚣;也没有大都市的那种快节奏;更加没有了“尔虞我诈、精于算计”的职场“战火硝烟”。 它有的只是寂静、随心所欲、闲…

NFS 共享存储实验

一、服务器部署 第一步、安装nfs和rpcbind包 [rootserver ~]# yum install -y nfs-utils rpcbind截图&#xff1a; 第二步、这里选择一个 lvm 挂载点做 NFS 共享目录 [rootserver ~]# df -HT截图&#xff1a; 第三步、修改配置文件 [rootserver ~]# vi /etc/exports /home …

SpringBoot 接口:响应时间优化9个技巧!

今天聊聊 SpringBoot接口&#xff1a;响应时间优化的9个技巧。在实际开发中&#xff0c;提升接口响应速度是一件挺重要的事&#xff0c;特别是在面临大量用户请求的时候。好了&#xff0c;咱们直接切入正题。 本文&#xff0c;已收录于&#xff0c;我的技术网站 ddkk.com&…

神经网络的核心:简单易懂理解 PyTorch 非线性激活函数

目录 torch.nn子函数非线性激活详解 nn.Softmin Softmin 函数简介 函数工作原理 参数详解 使用技巧与注意事项 示例代码 nn.Softmax Softmax 函数简介 函数工作原理 参数详解 使用技巧与注意事项 示例代码 nn.Softmax2d Softmax2d 函数简介 函数工作原理 输入…

2024最新前端源码分享(附效果图及在线演示)

分享10款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 粒子文字动画特效 基于canvas实现的粒子文字动画特效 会来回切换设定的文字特效 图…

字典类型存为csv

在Python中把Dict转换为CSV salary [{‘Name’:‘Alice’, ‘Job’:‘Data Scientist’, ‘Salary’:122000}, {‘Name’:‘Bob’, ‘Job’:‘Engineer’, ‘Salary’:77000}, {‘Name’:‘Carl’, ‘Job’:‘Manager’, ‘Salary’:119000}] Method 1 import pandas as pd …

本地jar安装到仓库

安装 jar mvn install:install-file -DgroupId坐标(相对于maven的路径) -DartifactId工程名称 -Dversion版本号 -Dpackagingjar -Dfilejar安装 source mvn install:install-file -DgroupId坐标(相对于maven的路径) -DartifactId工程名称 -Dversion版本号 -Dpackagingjar -Dfi…

在版权付费方面,OpenAI 比人想象中的还要「小气」

随着新闻出版商与AI公司达成“使用新闻训练AI模型”的协议&#xff0c;像 OpenAI 等科技企业愿意为受版权保护的信息支付的价格逐渐浮出水面。 据 The Information 报道&#xff0c;OpenAI 每年愿意向出版商提供 100万到500万美元来支付受版权保护的新闻文章训练其AI模型。 但…

LLM、AGI、多模态AI 篇五:基于LoRA微调ChatGLM3

文章目录 系列LLaMA-Factory简介推荐硬件要求环境搭建数据准备指令微调数据集偏好数据集自定义数据集指令监督微调合并 LoRA 权重并导出模型其他(训练全流程)预训练奖励模型训练PPO 强化学习训练DPO 强化学习训练通过一站式网页界面快速上手

createTempFile方法详解

createTempFile方法详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;我们将深入探讨一个在Java中常用的文件处理工具——createTempFile方法&am…

【leetcode】力扣热门之合并两个有序列表【简单难度】

题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 用例 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[] 输入&#xff1a;l1 []…

数据库连接使用问题 - 1

原理 open-in-view 是 Spring Boot ⾃动加载 Spring Data JPA 提供的⼀个配置&#xff0c;全称为 spring.jpa.open-in-viewtrue&#xff0c;它只有 true 和 false 两个值&#xff0c;默认是 true。 这个配置为true时&#xff0c;会导致Web MVC请求处理的一开始&…

王中阳Go赠书活动第一期:《TVM编译器原理与实践》

文章目录 前言TVM编译器的实现过程关于《TVM编译器原理与实践》编辑推荐内容简介作者简介图书目录书中前言/序言《TVM编译器原理与实践》全书速览入手《TVM编译器原理与实践》传送门&#xff1a;结束语参加抽奖 前言 随着人工智能的发展&#xff0c;计算机视觉、自然语言处理和…