C# 使用 RSA 签名和验证签名。编码问题
C# Signing and verifying signatures with RSA. Encoding issue
我的问题与 2011 年的表格非常相似,Signing and verifying signatures with RSA C#。尽管如此,当我比较签名数据和原始消息时,我也会得到 false。请指出我的错误。
代码:
public static void Main(string[] args)
{
//Generate a public/private key pair.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Save the public key information to an RSAParameters structure.
RSAParameters RSAPublicKeyInfo = RSA.ExportParameters(false);
RSAParameters RSAPrivateKeyInfo = RSA.ExportParameters(true);
string message = "2017-04-10T09:37:35.351Z";
string signedMessage = SignData(message, RSAPrivateKeyInfo);
bool success = VerifyData(message, signedMessage, RSAPublicKeyInfo);
Console.WriteLine($"success {success}");
Console.ReadLine();
}
签名方式:
public static string SignData(string message, RSAParameters privateKey)
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
// Write the message to a byte array using ASCII as the encoding.
byte[] originalData = byteConverter.GetBytes(message);
try
{
// Import the private key used for signing the message
rsa.ImportParameters(privateKey);
// Sign the data, using SHA512 as the hashing algorithm
signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
finally
{
// Set the keycontainer to be cleared when rsa is garbage collected.
rsa.PersistKeyInCsp = false;
}
}
// Convert the byte array back to a string message
return byteConverter.GetString(signedBytes);
}
验证方式:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] bytesToVerify = byteConverter.GetBytes(originalMessage);
byte[] signedBytes = byteConverter.GetBytes(signedMessage);
try
{
rsa.ImportParameters(publicKey);
success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
return success;
}
基本上问题出在字符串到 byte[] 的编码上。我在使用 ASCIIEncoding 和 UTF8Encoding 时遇到同样的问题。
提前致谢!
您不能对编码消息使用 ASCIIEncoding
,因为它包含无效 ASCII 字符的字节。存储编码消息的典型方式是在 base64 字符串中。
在SignData
中,使用以下代码将字节数组编码为字符串:
return Convert.ToBase64String(signedBytes);
并在 VerifyData
中,使用以下代码将字符串解码回相同的字节数组:
byte[] signedBytes = Convert.FromBase64String(signedMessage);
我的问题与 2011 年的表格非常相似,Signing and verifying signatures with RSA C#。尽管如此,当我比较签名数据和原始消息时,我也会得到 false。请指出我的错误。
代码:
public static void Main(string[] args)
{
//Generate a public/private key pair.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Save the public key information to an RSAParameters structure.
RSAParameters RSAPublicKeyInfo = RSA.ExportParameters(false);
RSAParameters RSAPrivateKeyInfo = RSA.ExportParameters(true);
string message = "2017-04-10T09:37:35.351Z";
string signedMessage = SignData(message, RSAPrivateKeyInfo);
bool success = VerifyData(message, signedMessage, RSAPublicKeyInfo);
Console.WriteLine($"success {success}");
Console.ReadLine();
}
签名方式:
public static string SignData(string message, RSAParameters privateKey)
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
// Write the message to a byte array using ASCII as the encoding.
byte[] originalData = byteConverter.GetBytes(message);
try
{
// Import the private key used for signing the message
rsa.ImportParameters(privateKey);
// Sign the data, using SHA512 as the hashing algorithm
signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
finally
{
// Set the keycontainer to be cleared when rsa is garbage collected.
rsa.PersistKeyInCsp = false;
}
}
// Convert the byte array back to a string message
return byteConverter.GetString(signedBytes);
}
验证方式:
public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)
{
bool success = false;
using (var rsa = new RSACryptoServiceProvider())
{
ASCIIEncoding byteConverter = new ASCIIEncoding();
byte[] bytesToVerify = byteConverter.GetBytes(originalMessage);
byte[] signedBytes = byteConverter.GetBytes(signedMessage);
try
{
rsa.ImportParameters(publicKey);
success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
return success;
}
基本上问题出在字符串到 byte[] 的编码上。我在使用 ASCIIEncoding 和 UTF8Encoding 时遇到同样的问题。
提前致谢!
您不能对编码消息使用 ASCIIEncoding
,因为它包含无效 ASCII 字符的字节。存储编码消息的典型方式是在 base64 字符串中。
在SignData
中,使用以下代码将字节数组编码为字符串:
return Convert.ToBase64String(signedBytes);
并在 VerifyData
中,使用以下代码将字符串解码回相同的字节数组:
byte[] signedBytes = Convert.FromBase64String(signedMessage);