我在c#上和python上面各搭了一套RSA签名验签的系统,但是在c#上和python上的验签互相不能通过(c#签名python验签,python签名c#验签),只能在c#或者python自己的环境下,自己验签自己通过(就是c#签名 c#验签,python签名 python验签)。
请问为什么不能互通,帮忙看看问题在哪。
条件:c#签名helloworld python验签通过,PSS填充 SHA256 ,mgf=padding.MGF1(hashes.SHA256()), (盐度应该为32字节,但是c#里面没得选不知道为啥) 加密方法就是python里的配置。
最好还能和 https://try8.cn/tool/cipher/rsa 这个网站上的也互通,能弄好可以追加悬赏都可以。
以下是我的c#代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.IO;
static void Main(string[] args)
{
RSANissan RSAInstance = new RSANissan();
RSAInstance.PublicKey = "‘’‘’";
RSAInstance.PrivateKey = "‘’‘’";
if (true)
{
byte[] DataToSign = new byte[] { 1 };
byte[] SignData = RSAInstance.RSAHashSign(DataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
string[] hexStrings = SignData.Select(b => b.ToString("X2")).ToArray();
Console.WriteLine(string.Join(" ", hexStrings));
string VerifyResult = RSAInstance.RSAHashVerify(DataToSign, SignData, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
Console.WriteLine($"result = {VerifyResult}");
/*****************************************字符串签名*****************************************/
String DataToSignStr = "Hello World!";
SignData = RSAInstance.RSAHashSign(DataToSignStr, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
VerifyResult = RSAInstance.RSAHashVerify(DataToSignStr, SignData, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
Console.WriteLine($"result = {VerifyResult}");
Console.ReadKey();
}
}
public class RSANissan
{
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public byte[] RSAHashSign(string hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
{
RSACng rsa = new RSACng();
rsa.FromXmlString(PrivateKey);
byte[] Hash_byteArray = Encoding.UTF8.GetBytes(hash);
byte[] SignData = rsa.SignHash(Hash_byteArray, hashAlgorithm, padding);
return SignData;
}
public string RSAHashVerify(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
{
string result = "fail";
RSACng rsa = new RSACng();
rsa.FromXmlString(PrivateKey);
bool VerifyResult = rsa.VerifyHash(hash, signature, hashAlgorithm, padding);
if (VerifyResult)
{
result = "pass";
}
return result;
}
}
公私钥由于是自己使用的就不提供了,主要用的就是c#官方的rsa模块,用的rsacng类里的签名验签方法,方法网站如下。
https://learn.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.rsa.verifydata?view=net-7.0
以下是我的python代码
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import (
load_pem_private_key,
load_pem_public_key
)
import binascii
import base64
def verify_signature(public_key_path, signature, data):
with open(public_key_path, 'rb') as key_file:
public_key = load_pem_public_key(key_file.read())
try:
public_key.verify(
signature,
data.encode('utf-8'),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=32,
),
hashes.SHA256()
)
return True
except :
return False
# 输入参数
public_key_path = r'‘’‘'
data = 'helloworld'
print(type(data.encode('utf-8')))
print(data.encode('utf-8'))
signature = '6A4E0C09990735DC624F1F8362C750A1952401C603A7A6E1A42CFC25C8A222AF5CE224426CC973E56F7E435E6FD47BBE060A0D73E5643E138F73C47B9C530C27FE735A8C18F44DEDDF5DF14BA723333C73D83F44841C0E430E165D57A43FED7033F62733782ED74D568C599BFA28801B1784A570AF8C317C592A2F68DF97B80BA2F221FC673D11B96C1E637EDF356F6DCB39AA5F3BB60445A2C4319BCB2C76A4BA80BAEE1CDC4E3C07FF9DF0C269521C8BA6FA26503E98C0549B78E2A8471FB4367FBF52BF5E3EB2F1269BA656A38AE61517F54689F144BC6889FFB6EF182533E63642884F2DC28769C079259C39061DE01B7987535DAC7CD8D55A0959C8C7AB'
# 验证签名
is_valid = verify_signature(public_key_path, signature, data)
print("Signature verification result:", is_valid)
主要使用的是cryptography库,密钥也不提供了。
最简单的办法就是,你用相同的内容,在c#和python 中都加密,然后输出下结果是不是一样的,不是一样就说明其中有一个加密不对。
而且两边公钥或者私钥要一样
如果要和其它语言互通,需要协商好:待签名字符串转为byte数组的编码、签名值byte数组转字符串的编码、哈希算法(SHA1WithRSA 还是 SHA256WithRSA),都要保持一致,你c#和python明显不一致
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据您提供的C#和Python代码,以及问题描述,问题可能出在密钥的生成和使用上。
在C#代码中,您使用了RSACng类进行签名和验签操作。首先,请确保您的私钥和公钥是正确的,并且与对应的Python密钥匹配。验证密钥对是否匹配非常重要。
在Python代码中,您使用了cryptography库进行签名和验签操作。同样,请确保您的私钥和公钥是正确的,并且与对应的C#密钥匹配。
此外,确保在C#代码中使用的填充方式、哈希算法以及密钥长度等参数与Python代码中的配置相匹配。在C#代码中,您使用了RSASignaturePadding.Pss填充方式和HashAlgorithmName.SHA256哈希算法,确保在Python代码中使用相同的填充方式和哈希算法。
另外,您提到了网站https://try8.cn/tool/cipher/rsa。确保您在使用该网站进行测试时,使用的密钥格式和填充方式与您的代码一致。该网站可能使用不同的配置和默认值,因此与您的代码可能存在差异。
如果问题仍然存在,建议您逐步调试代码,输出中间结果,以便更好地定位问题所在。您可以检查密钥的正确性、填充方式和哈希算法的一致性,以及数据编码的一致性。
最后,如果问题仍然无法解决,可能需要进一步详细的代码和错误信息来进行排查。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
两个编码方式不同,寻找一种互通的编码方式来加密,比如UTf-8或者gbk
C# winform 配合python实现网络爬虫抓取网络签名实例
1 用py编写
__author__ = 'Administrator'
import requests as rq
import re
import sys
url="http://www.uustv.com/"
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
name=sys.argv[1]
fnts=sys.argv[2]
ziti={
'艺术':'1.ttf',
'连笔':'zql.ttf',
'商务':"8.ttf",
'楷书':'6.ttf',
'潇洒':'bzcs.ttf',
'草体':'lfc.ttf',
'行书':'2.ttf',
'个性':'3.ttf',
'可爱':'yqk.ttf'
}
fnts=ziti[fnts]
data={
'word': name,
'sizes': 60,
'fonts': fnts,
'fontcolor':'#FF0000'
}
'''<option value="1.ttf" >艺术签</option>
<option value="zql.ttf" selected="selected">连笔签</option>
<option value="8.ttf" >商务签</option>
<option value="6.ttf" >楷书签</option>
<option value="bzcs.ttf" >潇洒签</option>
<option value="lfc.ttf" >草体签</option>
<option value="2.ttf" >行书签</option>
<option value="3.ttf" >个性签</option>
<option value="yqk.ttf" >可爱签</option>
'''
resualt=rq.post(url=url,headers=headers,data=data)
resualt.encoding='utf-8'
a = re.findall('<img src="(.*?)"/>', resualt.text,re.S) #第二步,调用模块函数
print(url+a[0]) #以列表形式返回匹配到的字符串
getpic=rq.get(url+a[0])
#<div class="tu"><img src="tmp/159759548773182.gif"/></div>
with open("1.gif","wb") as file:
file.write(getpic.content)
2、用pyinstaller把py脚本编译成exe可执行文件。
如:pyinstaller -F test.py
3、设计如下的C#,winform界面。
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace 艺术签名
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (File.Exists("1.gif"))
{
File.Delete("1.gif");
}
if (!textBox1.Text.Trim().Equals(string.Empty))
{
string txtname = textBox1.Text;
string ph = Application.StartupPath;
Process p = new Process();
p.StartInfo.FileName = ph + "\\test1.exe";//需要执行的文件路径
p.StartInfo.UseShellExecute = false; //必需
p.StartInfo.RedirectStandardOutput = true;//输出参数设定
p.StartInfo.RedirectStandardInput = true;//传入参数设定
p.StartInfo.CreateNoWindow = true;
p.StartInfo.Arguments = txtname + $" {comboBox1.SelectedItem.ToString()}";//参数以空格分隔,如果某个参数为空,可以传入””
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();//关键,等待外部程序退出后才能往下执行}
Console.Write(output);//输出;
p.Close();
UriBuilder url = new UriBuilder(output);
Console.WriteLine(url.Uri.ToString());
webBrowser1.Url = url.Uri;
}
else
{
MessageBox.Show("请输入您的签名哦!","提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception err)
{
MessageBox.Show("报错提示", err.Message, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private void label1_Click(object sender, EventArgs e)
{
Console.WriteLine(comboBox1.SelectedItem.ToString());
}
}
}
【以下回答由 GPT 生成】
这个问题出在C#中的签名和Python中的验签算法不一致。C#的RSASignaturePadding.Pss使用的是PSS填充,而Python中的cryptography库默认使用的是PKCS1填充。为了使C#和Python能够互通,你需要修改Python代码并使用PSS填充。
下面是一个示例的Python代码:
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key, load_pem_private_key
def rsa_hash_sign(private_key, data):
signer = private_key.signer(
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
signer.update(data)
signature = signer.finalize()
return signature
def rsa_hash_verify(public_key, data, signature):
verifier = public_key.verifier(
signature,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
verifier.update(data)
try:
verifier.verify()
return "验签通过"
except:
return "验签失败"
public_key_pem = """-----BEGIN PUBLIC KEY-----
你的公钥
-----END PUBLIC KEY-----"""
private_key_pem = """-----BEGIN PRIVATE KEY-----
你的私钥
-----END PRIVATE KEY-----"""
data_to_sign = b'Hello World!'
# 加载公钥和私钥
public_key = load_pem_public_key(public_key_pem.encode('utf-8'))
private_key = load_pem_private_key(private_key_pem.encode('utf-8'), password=None)
# 进行签名
signature = rsa_hash_sign(private_key, data_to_sign)
# 将签名结果转换成16进制字符串
signature_hex = signature.hex()
print(signature_hex)
# 进行验签
verify_result = rsa_hash_verify(public_key, data_to_sign, signature)
print(f"result = {verify_result}")
确保在Python中使用与C#中相同的公钥和私钥。将你的公钥和私钥替换到public_key_pem
和private_key_pem
变量中。 这样你就可以在Python中使用与C#相同的PSS填充算法进行签名和验签了。
希望对你有所帮助!如果有任何问题,请随时向我提问。