I'm having trouble reproducing some cryptographic functionality in dotnet core v2.0. This is code ported from a .NET 4.5 project
.NET 4.5 code
public byte[] SignData(byte[] dataToSign, X509Certificate2 certificate)
{
var rsaCryptoServiceProvider = new RSACryptoServiceProvider();
var xml = certificate.PrivateKey.ToXmlString(true);
rsaCryptoServiceProvider.FromXmlString(xml);
var signedBytes = rsaCryptoServiceProvider.SignData(dataToSign, CryptoConfig.MapNameToOID("SHA256"));
return signedBytes;
}
In dotnet core the ToXmlString()
and FromXmlString()
methods are not implemented, so I used a helper class workaround. Aside from that the dotnet core implementation works but, given the same input data and certificate it produces a different outcome.
dotnet core v2.0 code
public byte[] SignData(byte[] dataToSign, X509Certificate2 certificate)
{
var rsaCryptoServiceProvider = new RSACryptoServiceProvider();
var rsa = (RSA)certificate.PrivateKey;
var xml = RSAHelper.ToXmlString(rsa);
var parameters = RSAHelper.GetParametersFromXmlString(rsa, xml);
rsaCryptoServiceProvider.ImportParameters(parameters);
SHA256 alg = SHA256.Create();
var signedBytes = rsaCryptoServiceProvider.SignData(dataToSign, alg);
return signedBytes;
}
EDIT
The dotnet core signed data fails a signature verification check in the .NET 4.5 codebase. Theoretically it should make no difference what the signing method was, so this should work but doesn't.
public void VerifySignature(byte[] signedData, byte[] unsignedData, X509Certificate2 certificate)
using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PublicKey.Key)
{
if (rsa.VerifyData(unsignedData, CryptoConfig.MapNameToOID("SHA256"), signedData))
{
Console.WriteLine("RSA-SHA256 signature verified");
}
else
{
Console.WriteLine("RSA-SHA256 signature failed to verify");
}
}
}
Does anyone know if there are compatibility issues between the two methods of signing data?
EDIT 2
For clarification this is what both code snippets are attempting:
- Taking a X509 certificate's private key which is RSA-FULL and cannot sign using SHA256 encoding
- Creating a new private key which is RSA-AES which can sign using SHA256 encoding
- Import your X509 private key into this new private key
- Signing the required data using this private key.
The complication comes when attempting the same thing in .NEt4.5 and dotnet core v2.0.
Seems there are differences between frameworks, libraries and OS's. This answer states that the RSACryptoServiceProvider
object relies on the CryptoAPI of the machine the software is on in .NET 4.5, and this informative post shows you the difference on how this is implemented in different environments/frameworks.
I'm still working on a solution based on this information but am left the central issue, namely that signed data using this dotnet core above cannot be verified by the .NET 4.5 implementation.