RSA Signing In C# using Microsoft Cryptography Library
Sample class library implementing RSA signing using Microsoft’s Cryptography Library
Introduction
RSA (Rivest–Shamir–Adleman) is a public-key cryptosystem. In such a cryptosystem, a pair of keys is used often called private and public key pair.
Public key cryptosystems are used for 2 major use cases
- Encryption
- Verification
Focus of this article is signing/verification. With a public key cryptosystem, private key is always kept secure by the owner and public key is publically accessible. Process of verification involves signing of data with a private key that can be verified using associated public key. Signing is always done with a private key that is only accessible by owner. Verification is done using a public key accessible by any member of the public. Anybody can use it (public key) to verify a data signature, if successful meaning it is genuinely coming from the owner of the private key.
RSA In .NET Core
RSA represents the abstract base class from which all implementations of RSA mush inherit. .NET provides following implementations of RSA at the time of writing.
- RSACng
- RSACryptoServiceProvider - used on windows
- RSAOpenSsl - used on linux/osx if openssl is installed
RSA abstract base class also provides static methods to create an instance of an implementation
- Create() - creates an instance based on platform
Implementation
Lets start using RSA in our code for signing/verifying data. We would need to include System.Security.Cryptography
namespace.
using System.Security.Cryptography;
Key Generation
GenerateKeyPair method creates a new instance of RSA, sets desired key size and export parameters and convert to RsaPrivateKeyParameters
/RsaPublicKeyParameters
helper classes and export those as json strings.
Sign Data
SignData method accepts a string and RsaPrivateKeyParameters
serialized as json, signs data with key using a hash and padding and finally returns a base64 encoded data signature.
We will start by creating an instance of RSA and importing key.
var rsa = RSA.Create();
var rsaParameters = JsonConvert.DeserializeObject<RsaPrivateKeyParameters>(privateKeyJson).ToRSAParameters();
rsa.ImportParameters(rsaParameters);
Call SignData
method on rsa
instance to encrypt data.
var signature = rsa.SignData(dataToSign, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
We then convert signature to base64 string and return to caller.
Complete code for the method is below
public string SignData(string data, string privateKeyJson)
{
using (var rsa = RSA.Create())
{
var rsaParameters = JsonConvert.DeserializeObject<RSAParameters>(privateKeyJson);
rsa.ImportParameters(rsaParameters);
var dataToSign = Encoding.UTF8.GetBytes(data);
var signature = rsa.SignData(dataToSign, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signature);
}
}
Verify Signature
VerifySignature method works in conjunction with SignData method above, it accepts data, base64 encoded signature and RsaPublicKeyParameters
serialized as json. It imports key, performs verification and returns a boolean result.
We will start by creating an instance of RSA and importing key.
var rsa = RSA.Create();
var rsaParameters = JsonConvert.DeserializeObject<RsaPublicKeyParameters>(publicKeyJson).ToRSAParameters();
rsa.ImportParameters(rsaParameters);
Call VerifyData
method on rsa
instance to decrypt data.
rsa.VerifyData(dataToVerify, signatureData, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
And return the result of VerifyData back to caller.
Complete code for the method is below
public bool VerifySignature(string data, string signature, string publicKeyJson)
{
using (var rsa = RSA.Create())
{
var rsaParameters = JsonConvert.DeserializeObject<RSAParameters>(publicKeyJson);
rsa.ImportParameters(rsaParameters);
var dataToVerify = Encoding.UTF8.GetBytes(data);
var signatureData = Convert.FromBase64String(signature);
return rsa.VerifyData(dataToVerify, signatureData, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
}
Complete code for the wrapper class that implements signing and its verification using RSA can be found at RsaCrypto.cs. Unit tests for the wrapper class can be found at RsaCryptoTests.cs. Complete project as class library along with tests is at CryptoSandbox.
References
https://en.wikipedia.org/wiki/RSA_(cryptosystem) https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsa?view=netcore-2.2
Leave a Comment
Your email address will not be published. Required fields are marked *