Reputation: 51
I am new here.
I am learning the digital signature in C#. The certificates are generated followed by this document. Other documents I read: RSACng, X509Certificate2.
I am working on Windows 10 Pro 1809, .Net Core 2.1, VSCode.
class Program
{
static void Main(string[] args)
{
var passwd = "password";
// Get client certificate.
var clientCertPath = @"./Certificates/test.pfx";
var clientCert = new X509Certificate2(clientCertPath, passwd);
// Get server certificate.
var serverCertPath = @"./Certificates/test.cer";
var serverCert = new X509Certificate2(serverCertPath);
// Generate data.
var translateResultData = BuildData();
var content = String.Join('&', translateResultData.Select(p => String.Join('=', p.Key, p.Value)));
// Sign
var sign = SignatureUtil.Sign(data: content, clientCert: clientCert);
// translateResultData.TryAdd(key: "sign", value : sign);
// Copy content ONLY for test.
var checkSign = sign;
var checkContent = content;
// Verify
var valid = SignatureUtil.Verify(data: checkContent, signature: checkSign, serverCert: serverCert);
System.Console.WriteLine(valid);
}
}
public class SignatureUtil
{
public static string Sign(string data, X509Certificate2 clientCert)
{
using(var privateKey = clientCert.GetRSAPrivateKey())
{
var dataByteArray = Encoding.UTF8.GetBytes(data);
var signatureByteArray = privateKey.SignData(
data: dataByteArray,
hashAlgorithm: HashAlgorithmName.SHA256,
padding: RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signatureByteArray);
}
}
public static bool Verify(string data, string signature, X509Certificate2 serverCert)
{
try
{
using(var publicKey = serverCert.GetRSAPublicKey())
{
var dataByteArray = Encoding.UTF8.GetBytes(data);
var signatureByteArray = Convert.FromBase64String(signature);
return publicKey.VerifyData(
data: dataByteArray,
signature: signatureByteArray,
hashAlgorithm: HashAlgorithmName.SHA256,
padding: RSASignaturePadding.Pkcs1);
}
}
catch (System.Exception)
{
return false;
}
}
}
Expected result: valid
should be true
because I am checking the original data.
Fact: The Verify
method always returns false
even the original data are passed.
Can you tell me what I did wrong?
Upvotes: 5
Views: 19610
Reputation: 343
I cannot tell you what is going wrong in your code since I cannot reproduce it. Here is a very detailed answer how you can sign using RSA and SHA256. Your approach and the one described in this answer are conceptually the same, but maybe there is a difference in your code compared to this answer.
And here is a example how in my company certificates associated with smart cards are used for signing and verifying signatures. One big difference is that we do not store the signature as a string but rather keep it as an array of bytes.
public byte[] SignData(byte[] data)
{
using (var sha256 = SHA256.Create())
{
using (var rsa = Certificate.GetRSAPrivateKey())
{
return rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
}
}
}
public bool VerifySignature(byte[] data, byte[] signature)
{
using (var sha256 = SHA256.Create())
{
using (var rsa = Certificate.GetRSAPublicKey())
{
return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
}
}
}
Upvotes: 7