BouncyCastle has FIPS DLLs for C# that I need to use for encryption instead of normal DLLs because of compliance. How do you import public and private keys and covert them to a RSACryptoServiceProvider in order to encrypt and decrypt.
This is how I encrypt and decrypt using the regular BouncyCastle. I just need to change the functions ImportPrivateKey and ImportPublicKey
public static string Decrypt(string privateKey, string base64Encrypted)
{
string ret = null;
using (var rsa = ImportPrivateKey(privateKey))
{
var cipherBytes = Convert.FromBase64String(base64Encrypted);
RSA rsaCng = new RSACng();
rsaCng.ImportParameters(rsa.ExportParameters(true));
byte[] plainBytes = rsaCng.Decrypt(cipherBytes, RSAEncryptionPadding.OaepSHA256);
string plaintext = Encoding.UTF8.GetString(plainBytes);
ret = plaintext;
}
return ret;
}
public static string Encrypt(string publicKey, string toEncrypt)
{
string cipherText = null;
using (var rsa = ImportPublicKey(publicKey))
{
var data = Encoding.UTF8.GetBytes(toEncrypt);
RSA rsaCng = new RSACng();
rsaCng.ImportParameters(rsa.ExportParameters(false));
byte[] cipherTextBytes = rsaCng.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
cipherText = Convert.ToBase64String(cipherTextBytes);
}
return cipherText;
}
public RSACryptoServiceProvider ImportPrivateKey(string pem)
{
PemReader pr = new PemReader(new StringReader(pem));
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParams);
return rsa;
}
public RSACryptoServiceProvider ImportPublicKey(string pem)
{
PemReader pr = new PemReader(new StringReader(pem));
AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParams);
return rsa;
}
Here is how I got it working. If someone else has something more simple that would be awesome!. Import the keys turn them into AsymmetricRsaPublicKey then covert them to RSAParameters and then import those.
using System.IO;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Asymmetric;
using Org.BouncyCastle.Crypto.Fips;
using Org.BouncyCastle.OpenSsl;
public RSACryptoServiceProvider ImportPublicKey(string key)
{
var reader = new OpenSslPemReader(new StringReader(key));
var publicKeyInfo = (SubjectPublicKeyInfo)reader.ReadObject();
var rpckp = new AsymmetricRsaPublicKey(FipsRsa.Pkcs1v15.Algorithm, publicKeyInfo);
RSAParameters parms = new RSAParameters
{
Modulus = rpckp.Modulus.ToByteArrayUnsigned(),
Exponent = rpckp.PublicExponent.ToByteArrayUnsigned()
};
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider();
rcsp.ImportParameters(parms);
return rcsp;
}
public RSACryptoServiceProvider ImportPrivateKey(string key)
{
var reader = new OpenSslPemReader(new StringReader(key));
var keyPair = (PemKeyPair)reader.ReadObject();
var rpckp = new AsymmetricRsaPrivateKey(FipsRsa.Pkcs1v15.Algorithm, keyPair.PrivateKeyInfo);
RSAParameters parms = new RSAParameters
{
Modulus = rpckp.Modulus.ToByteArrayUnsigned(),
P = rpckp.P.ToByteArrayUnsigned(),
Q = rpckp.Q.ToByteArrayUnsigned(),
DP = rpckp.DP.ToByteArrayUnsigned(),
DQ = rpckp.DQ.ToByteArrayUnsigned(),
InverseQ = rpckp.QInv.ToByteArrayUnsigned(),
D = rpckp.PrivateExponent.ToByteArrayUnsigned(),
Exponent = rpckp.PublicExponent.ToByteArrayUnsigned()
};
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider();
rcsp.ImportParameters(parms);
return rcsp;
}