Reputation: 365
Im trying to make a SHA1withRSA sign/verify function on ASP.NET core using BouncyCastle library, 1st of all I need to make a keypair, I am using this page to generate the key: https://travistidwell.com/jsencrypt/demo/
However from BouncyCastle example code I found (C# Sign Data with RSA using BouncyCastle), from the Public and Private key text generated, I couldn't make the key files, which as I understand, would be a .CER file for public key and .PEM for private key.
So could you please suggest me a way to make the .CER and .PEM file? Also, I haven't found a complete example about signing SHA1withRSA using BouncyCastle library - or just core C#, I'd be so grateful if you could suggest me a complete example, thank you so much.
Upvotes: 2
Views: 5134
Reputation: 49141
The linked website generates private keys in PKCS#1 format and public keys in X.509/SPKI format, each PEM encoded.
.NET Core only supports the import of PKCS#1 and X.509 keys as of version 3.0. For .NET Core 2.2, the easiest way is to apply BouncyCastle. For loading the PEM keys the PemReader
of BouncyCastle can be used.
Option 1:
With BouncyCastle's DotNetUtilities
class, RSAParameters
instances can be derived and thus RSACryptoServiceProvider
instances:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
...
public static RSACryptoServiceProvider GetRSACryptoServiceProviderFromPem(string pem, bool isPrivate)
{
PemReader pemReader = new PemReader(new StringReader(pem));
object key = pemReader.ReadObject();
RSAParameters rsaParameters = isPrivate ?
DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)(((AsymmetricCipherKeyPair)key).Private)) :
DotNetUtilities.ToRSAParameters((RsaKeyParameters)key);
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
rsaKey.ImportParameters(rsaParameters);
return rsaKey;
}
RSACryptoServiceProvider
in turn has methods for signing/verifying:
RSACryptoServiceProvider privateCSP = GetRSACryptoServiceProviderFromPem(privateKey, true);
RSACryptoServiceProvider publicCSP = GetRSACryptoServiceProviderFromPem(publicKey, false);
byte[] dataToSign = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
byte[] signature = privateCSP.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
bool verified = publicCSP.VerifyData(dataToSign, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
Option 2:
Alternatively, the RsaPrivateCrtKeyParameters
and the RsaKeyParameters
classes of BouncyCastle can be used directly:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
...
public static AsymmetricKeyParameter GetAsymmetricKeyParameterFromPem(string pem, bool isPrivate)
{
PemReader pemReader = new PemReader(new StringReader(pem));
object key = pemReader.ReadObject();
return isPrivate ? ((AsymmetricCipherKeyPair)key).Private : (AsymmetricKeyParameter)key;
}
as well as classes for signing and verifying provided by BouncyCastle's SignerUtilities
:
RsaPrivateCrtKeyParameters privateKeyParameters = (RsaPrivateCrtKeyParameters)GetAsymmetricKeyParameterFromPem(privateKey, true);
RsaKeyParameters publicKeyParameters = (RsaKeyParameters)GetAsymmetricKeyParameterFromPem(publicKey, false);
ISigner signer = SignerUtilities.GetSigner("SHA1withRSA");
signer.Init(true, privateKeyParameters);
byte[] dataToSign = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
signer.BlockUpdate(dataToSign, 0, dataToSign.Length);
byte[] signature = signer.GenerateSignature();
signer.Init(false, publicKeyParameters);
signer.BlockUpdate(dataToSign, 0, dataToSign.Length);
bool verified = signer.VerifySignature(signature);
Console.WriteLine(verified);
Both implementations are executable under .NET Core 2.2.
Upvotes: 3