Search code examples
monox509certificate2

Why is SignHash from RSACng (dotNetCore) different from BoncyCastle (running in Mono)?


I'm trying summarize: I have a self-signed certificate (created by OpenSSL) being used in a aspnetCore API to verify hash (or message digest, if you prefer) signature. I can run tests to sign the hash and run in the API and everything goes well.

Now, I'm trying do my client sign such hashs and consume the API. It's an application running on Mono. I'm tried do exactly the same thing as my tests, but Mono has a bug in X509Certificate2, when pfx certificate is protected by password. So, I replaced it the by the famous BouncyCastle. However, the results are different... Checking the pk algorithm, I can see some differences, but nothing so remarkable (at least to me).

Can you give me advices? I gonna put the codes:

Good code running on tests (dotNet Core):

Console.WriteLine("Entry text:");
var text = Console.ReadLine();

X509Certificate2 certificate = new X509Certificate2((byte[])Resource1._2dbb1721_281d_4990_836c_7e46909b8767, "1509a96c-d56b-4e17-af5b-c11f5f214c74");

SHA1Managed sha1Hasher = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
byte[] hash = sha1Hasher.ComputeHash(data);

RSA provider = (RSA)certificate.PrivateKey;

var signatureData = provider.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
var signature = Convert.ToBase64String(signatureData);

Bad code, running on Mono and BouncyCastle:

SHA1Managed sha1Hasher = new SHA1Managed();
var encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(uuid);
byte[] hash = sha1Hasher.ComputeHash(data);

var rsaParameters = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)privateKeyParam);
var provider = RSA.Create();
provider.ImportParameters(rsaParameters);

var signatureData = provider.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
var signature = Convert.ToBase64String(signatureData);

Both certificates are the same. Debugging, I could see the dotNet instantiates on provider as RSACng. The SignatureAlgorithm property is "RSA" as the KeyExchangeAlgorithm so.

In the BoncyCastle over Mono, the provider is RSACrytoServiceProvider. According some articles that I read, this shouldn't make any difference. However, SignatureAlgorithm is "http://www.w3.org/2000/09/xmldsig#rsa-sha1", while KeyExchangeAlgorithm is "RSA-PKCS1-KeyEx".

Thanks in advance


Solution

  • My bad: I've just realized my program wasn't using the string it is supposed might use to calculate the hash...

    The Mono's version using BouncyCastle is working perfect fine.