使用 Python 进行 RSA 签名并使用 C# 进行验证
RSA signing with Python verifying with C#
我正在尝试在 Python 中使用 RSA 对消息进行签名,然后在 C# 中验证数据,但在 testing/fighting 小时后仍然失败。
Python签名码:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
message = b"Test string"
with open("id_rsa", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
)
signature = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA256()
)
signaturefile = open('signed.dat', 'wb')
signaturefile.write(signature)
signaturefile.close()
datafile = open('message.dat', 'wb')
datafile.write(message)
datafile.close()
以及用于验证的 C# 代码:
private void button_Click(object sender, EventArgs e)
{
byte[] data = File.ReadAllBytes("message.dat");
byte[] signature = File.ReadAllBytes("signed.dat");
try
{
using (var reader = File.OpenText("id_rsa.pub"))
{
var pem = new PemReader(reader);
var o = (RsaKeyParameters)pem.ReadObject();
using (var rsa = new RSACryptoServiceProvider())
{
var parameters = new RSAParameters();
parameters.Modulus = o.Modulus.ToByteArray();
parameters.Exponent = o.Exponent.ToByteArray();
rsa.ImportParameters(parameters);
bool ok = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
if (ok) Console.WriteLine("Verified");
}
}
}
catch (CryptographicException exc)
{
Console.WriteLine(exc.Message);
}
}
rsa.VerifyData 我总是失败。谁能指出我的问题是什么?
同样的文件可以在Python中得到很好的验证。
RSAParameters#Modulus
和 RSAParameters#Exponent
期望模数和指数 无符号 ,因此必须使用 Org.BouncyCastle.Math.BigInteger#ToByteArrayUnsigned()
而不是 Org.BouncyCastle.Math.BigInteger#ToByteArray()
。有了这个改动,验证就成功了。
另外,big endian 字节顺序是必需的,但这适用于两种方法。
请注意 System.Numerics.BigInteger#ToByteArray()
returns 数据以小端顺序签名。
您当前的方法使用 BC 进行密钥导入,并使用内置的 .NET 方法进行验证。或者,BC 类 也可以用于验证,使整体实施效率更高。
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
...
ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
signer.Init(false, o);
signer.BlockUpdate(data, 0, data.Length);
bool verified = signer.VerifySignature(signature);
我正在尝试在 Python 中使用 RSA 对消息进行签名,然后在 C# 中验证数据,但在 testing/fighting 小时后仍然失败。
Python签名码:
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
message = b"Test string"
with open("id_rsa", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
)
signature = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA256()
)
signaturefile = open('signed.dat', 'wb')
signaturefile.write(signature)
signaturefile.close()
datafile = open('message.dat', 'wb')
datafile.write(message)
datafile.close()
以及用于验证的 C# 代码:
private void button_Click(object sender, EventArgs e)
{
byte[] data = File.ReadAllBytes("message.dat");
byte[] signature = File.ReadAllBytes("signed.dat");
try
{
using (var reader = File.OpenText("id_rsa.pub"))
{
var pem = new PemReader(reader);
var o = (RsaKeyParameters)pem.ReadObject();
using (var rsa = new RSACryptoServiceProvider())
{
var parameters = new RSAParameters();
parameters.Modulus = o.Modulus.ToByteArray();
parameters.Exponent = o.Exponent.ToByteArray();
rsa.ImportParameters(parameters);
bool ok = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
if (ok) Console.WriteLine("Verified");
}
}
}
catch (CryptographicException exc)
{
Console.WriteLine(exc.Message);
}
}
rsa.VerifyData 我总是失败。谁能指出我的问题是什么?
同样的文件可以在Python中得到很好的验证。
RSAParameters#Modulus
和 RSAParameters#Exponent
期望模数和指数 无符号 ,因此必须使用 Org.BouncyCastle.Math.BigInteger#ToByteArrayUnsigned()
而不是 Org.BouncyCastle.Math.BigInteger#ToByteArray()
。有了这个改动,验证就成功了。
另外,big endian 字节顺序是必需的,但这适用于两种方法。
请注意 System.Numerics.BigInteger#ToByteArray()
returns 数据以小端顺序签名。
您当前的方法使用 BC 进行密钥导入,并使用内置的 .NET 方法进行验证。或者,BC 类 也可以用于验证,使整体实施效率更高。
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
...
ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
signer.Init(false, o);
signer.BlockUpdate(data, 0, data.Length);
bool verified = signer.VerifySignature(signature);