Move RSA Key Container from Server A to Server B - c#

My project required key recovery features where the system admin can upload RSA Key container
to restore it in the event for disaster recovery
Current implementation is when admin upload the backup RSA Key container file, the app will move it to RSA Key container folder located at C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
I tried to recover the key container from server into my local machine
Key container from server :
a953858192ce652ca077837fd55e8ea2_06454689-ae14-440b-aa53-c2eaac321be6
the bold part is Server Machine ID
When the RSACryptoServiceProvider tried to access the container, it will create a new container because the key name is not contain my local machine ID, made the decryption of encrypted data from server doesn't work.
I tried to rename the machine ID to my local machine ID
a953858192ce652ca077837fd55e8ea2_fbf0b515-e8c9-450d-bc0c-4bcb55cbd342
and the RSACryptoService throw error :
"Key not valid for use in specified state."
Code implementation in C# :
try{
// Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters); // error thrown "Key not valid for use in specified state."
try
{
var keyContainerBlob = rsaCryptoServiceProvider.ExportCspBlob(true);
using (var rsa = System.Security.Cryptography.RSA.Create())
{
rsa.KeySize = CryptoCommonHeap.RSAEncryptionKeySize;
rsaCryptoServiceProvider.ImportCspBlob(keyContainerBlob);
var privateKeyParameters = rsaCryptoServiceProvider.ExportParameters(true).ToPrivateKeyParameters();
var privateKeyParametersJson = JsonConvert.SerializeObject(privateKeyParameters);
PrivateKeyParametersJson = privateKeyParametersJson;
}
}
finally
{
// Setting This If Do Not Want To Store The File Persistently
//rsaCryptoServiceProvider.PersistKeyInCsp = false;
}
}
catch (Exception exception)
{
LogErrorToDatabase(ModuleName, "GenerateKeyAndSaveInKeyStore", exception);
}
I hope someone can enlighten me a correct way to restore RSA key container from another machine..

I've figured out myself how to properly restore the key container. Instead of copy the key container directly from Server A to Server B, I export the private key from server A to server B in PEM format and do restoration programmatically.
Dependency : Org.Bouncycastle
First you need to export the private key of your existing key in the key container, you must ensure the RSACryptoServiceProvider is loaded with your intended key container info
//Create the CspParameters object and set the key container name used to store the RSA key pair.
var parameters = new CspParameters {KeyContainerName = containerName, Flags = UseMachineKeyStore};
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container Key Container Name.
using var rsaCryptoServiceProvider = new RSACryptoServiceProvider(parameters);
Then export the key by using this :
private string ExportKey(RSACryptoServiceProvider rsa) {
var writer = new StringWriter();
var pemWriter = new PemWriter(writer);
var rsaKeyPair = DotNetUtilities.GetRsaKeyPair(rsa);
pemWriter.WriteObject(rsaKeyPair.Private);
return writer.ToString();
}
now you'll have the PEM content and save it to appropriate location :
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDCmI8XFUlZUwoGXl42GNzY2o6exeA51/7U0UF4u5+AAbS+h3xD
Pk1BQ5rlzwOu+a2SrbNnGlH5j/6n+kQqLcBdwVdHAF6CFaPmKf7xUEqKwo2RCoG9
zNYB5gc4youdppr4K7uLDQoVvM9xUVi09n2zg3KSigLpX3WM5k4lJWOiOQIDAQAB
AoGBAL6X58ZHDhFT+MSmFwZLMbufzQKLcoOVH73XupWCxsT8ZsgaMUY3NjmO+p7N
NKFjYHMCeG2qZNHXDCgAQlVBfF9fvA3SulymyYoHEAGY1ghAnky7PjuESYmCFDes
6BlyMBfjNtAPkvSA/VZi00VOuCl7Vg4FJLOesmZzHdoaflIlAkEA+W5NU3l+z5+d
rZkw86v+ZvmuDNv77Bh5DZJ1SjQ6uiWCV7LmMOc6eOETmV0d25UkBdAU4KpfRFXg
zcEh548t9wJBAMe4jVQFMjv2L35Kr0jsSEi+O3OPNn7UTNYWlCwv0FnzB3YBMFvA
ULDYmtduaBqchzqqleWrOGK8dOeiUyj+ZU8CQQCsMlX31tyRAaSdgDCnSIntFVnv
Tr9wksSfdgi7Haudbt+5I6x+/mMDqH8bVYmTWjbwPGLtZzE1wAPeiAKcFeCpAkEA
hW+OLRaTq3Ad5xjq56PF36QJgHmshSw+ccMAGE2RvKcc0wCUWJiy0JTHTyvarfzq
dI3IPHwa3gzfZmsTeI4PDQJBAI+LvqZzxzwf01DWgDqiJzKwt+bejtdfnPqQhjRD
rcZcM550Iwy0PCdrRTswDbloNhCfcyi1HXIvZTydMXzOueU=
-----END RSA PRIVATE KEY-----
Then regenerate key container in Server B based on key information in PEM file
public bool PrivateKeyRecovery(string pem)
{
try
{
//read key info
PemReader pr = new PemReader(new StringReader(pem));
var paramObject = pr.ReadObject();
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)paramObject;
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
//prepare key name and csp parameters
var keyContainerName = "RestoredContainer" + DateTime.Now.ToString("yyyyMddhmm");
var parameters = new CspParameters { KeyContainerName = keyContainerName, Flags = UseMachineKeyStore };
//import csp parameters into new instance of RSACryptoServiceProvider
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(parameters);
csp.ImportParameters(rsaParams);
//exporting new key container
var keyContainerBlob = csp.ExportCspBlob(true);
csp.ImportCspBlob(keyContainerBlob);
}
catch (Exception exception)
{
//your error handling
}
return false;
}
now you can decrypt data from Server A in Server B by loading the newly generated key container into RSACryptoServiceProvider.

Related

C# - Generate X509 Certificate based on a given issuer certificate in byte[]

I want to create iothub device certificates from C# code. The root CA is stored in keyvault as a .pfx, fetched as a string, and then converted from base 64 in order to obtain the certificate bytes as it is required for a certificate stored in keyvault: Azure Key Vault Certificates does not have the Private Key when retrieved via IKeyVaultClient.GetCertificateAsync
I want to write a function that will take these bytes, along with a subject name (for the leaf certificate) and will create a x509 certificate (with both public and private keys) that would have the issuer as the root.
Here is what I have sketched so far:
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
var issuerCertificate = new X509Certificate2(issuerByteCert);
RSA keyProvider = issuerCertificate.GetRSAPrivateKey();
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", keyProvider, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
return publicOnlyDeviceCertificate; // oh no ! :(
}
The issue I am having with this solution is that the created certificate only contains a public key.
I found another solution that appears to solve my problem on another Stack Overflow question using BouncyCastle's X509V3CertificateGenerator: Generate a self-signed certificate on the fly
The issue I have with this solution is that I cannot convert my rootCA certificate's private key to an AsymmetricKeyParameter (first parameter of the X509V3CertificateGenerator.Generate method). I tried converting the issuer's key to AsymmetricKeyParameter using this solution: convert PEM encoded RSA public key to AsymmetricKeyParameter, but I got an invalid operation exception.
I was wondering if I was on the right path (as far as understanding goes) and if there is a way to generate a certificate with a private (and public key) based on the code I currently have in place.
UPDATE: I have been able to convert a private key to an AsymmetricKeyParameter by hardcoding the key as follows:
string testKey = #"-----BEGIN PRIVATE KEY-----
<THE KEY>
-----END PRIVATE KEY-----
";
var stringReader = new StringReader(testKey);
var pemReader = new PemReader(stringReader);
var pemObject = pemReader.ReadObject();
var keyParam = ((AsymmetricKeyParameter)pemObject);
Azure keyvault stores certificate in a pfx format. I am thinking of storing the private key as a secret string. I will keep testing with an hardcoded key for now until I get to a working solution.
I am now testing with BouncyCastle and will come back with a working solution if it works!
The key you pass to CertificateRequest is used as the public key in the cert... so you want to pass a new key, not the issuer's key.
Then, once you now have the subject key, you use CopyWithPrivateKey at the end to glue them back together.
public static X509Certificate2 GenerateCertificateBasedOnIssuer(string subjectName, byte[] issuerByteCert)
{
using (var issuerCertificate = new X509Certificate2(issuerByteCert))
using (RSA subjectKey = RSA.Create(2048))
{
CertificateRequest certificateRequest = new CertificateRequest($"CN={subjectName}", subjectKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
var publicOnlyDeviceCertificate = certificateRequest.Create(issuerCertificate, issuerCertificate.NotBefore, issuerCertificate.NotAfter, serialNumber.ToByteArray());
using (publicOnlyDeviceCertificate)
{
return publicOnlyDeviceCertificate.CopyWithPrivateKey(subjectKey);
}
}

How can I protect the rsacryptoserviceprovider privatekey with a password and add it in windows store

I have a publickey certificate and a privatekey. Before adding to the x509store I want to protect the privatekey with a password.
My requirement is when I find the x509certificate2 from store using subject name I should get the certiifcate with the privatekey.But privatekey should be password protected without any ui prompt.
When creating rsacryptoservice provider I tried to attach key password to the csp params and I can able to create rsacryptoserviceprovider object.I have attached that to a x509certificate2 and added to the windows store. But after retrieving from store private key is throwing cryptographic exception.
var cspParams = new CspParameters
{
ProviderType = 1,
Flags = CspProviderFlags.UseMachineKeyStore
};
string passphrase = "password";
char[] passPhrase = passphrase.ToCharArray();
SecureString keyPassword = new SecureString();
for (int i = 0; i < passPhrase.Length; i++)
{
keyPassword.AppendChar(passPhrase[i]);
}
cspParams.KeyPassword = keyPassword;
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams))
{
rsaProvider.ImportParameters(rsaParam);
rsaProvider.PersistKeyInCsp = true;
X509Certificate2 x509Certificate = new X509Certificate2(Convert.FromBase64String(cryptoCertificate),
"123",
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.PersistKeySet)
{PrivateKey = rsaProvider};
store.Add(x509Certificate);
}
The problem is here:
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams))
{
rsaProvider.ImportParameters(rsaParam);
rsaProvider.PersistKeyInCsp = true;
X509Certificate2 x509Certificate = new X509Certificate2(<...>)
{PrivateKey = rsaProvider};
<..>
}
You are creating a new RSA asymmetric key pair and attempt to attach it to a certificate. However, this key pair is brand new and doesn't match the public key stored in certificate. Instead, you have to acquire private key handle from X509Certificate2 object and work on it, do not create new keys, it will never work.
And do not use RSACryptoServiceProvider it is dead and obsolete. Instead, you must use X509Certificate.GetRSAPrivateKey() extension method to get an instance of RSA class and extract CSP parameters from that RSA object.

Certificate signing produces different signature when on server

I am trying to sign some data using a certificate private key. The issue I'm finding is that the signature is different depending on if I'm executing it locally or on a server.
I'm using the following code as a test, running under the same user both locally and on the server:
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace TestSignature
{
class Program
{
static void Main(string[] args)
{
var key = SigningKeyFromCertificate(StoreName.My, StoreLocation.LocalMachine, X509FindType.FindByThumbprint, "thumbprint");
var alg = CryptoConfig.MapNameToOID("SHA256");
var data = Encoding.UTF8.GetBytes("test");
var sig = key.SignData(data, alg);
Console.WriteLine(Convert.ToBase64String(sig));
}
private static RSACryptoServiceProvider SigningKeyFromCertificate(StoreName storeName, StoreLocation storeLocation, X509FindType findType, string findValue)
{
X509Store store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(findType, findValue, false);
if (certs?.Count > 0)
{
var cert = certs[0];
if (cert.HasPrivateKey)
{
// Force use of Enhanced RSA and AES Cryptographic Provider to allow use of SHA256.
var key = cert.PrivateKey as RSACryptoServiceProvider;
var enhanced = new RSACryptoServiceProvider().CspKeyContainerInfo;
var parameters = new CspParameters(enhanced.ProviderType, enhanced.ProviderName, key.CspKeyContainerInfo.UniqueKeyContainerName);
return new RSACryptoServiceProvider(parameters);
}
else
{
throw new Exception($"No private key access to cert '{findValue}.'");
}
}
else
{
throw new Exception($"Cert '{findValue}' not found!");
}
}
}
}
Locally, I get the following signature:
YUjspKhLl7v3u5VQkh1PfHytMTpEtbAftxOA5v4lmph3B4ssVlZp7KedO5NW9K5L222Kz9Ik9/55NirS0cNCz/cDhEFRtD4daJ9qLRuM8oD5hCj6Jt9Vc6WeS2he+Cqfoylnv4V9plfi1xw8y7EyAf4C77BGkXOdyP5wyz2Xubo=
On the server, I get this one instead:
u1RUDwbBlUpOgNNkAjXhYEWfVLGpMOa0vEfm6PUkB4y9PYBk1lDmCAp+488ta+ipbTdSDLM9btRqsQfZ7JlIn/dIBw9t5K63Y7dcDcc7gDLE1+umLJ7EincMcdwUv3YQ0zCvzc9RrP0jKJManV1ptQNnODpMktGYAq1KmJb9aTY=
Any idea of what could be different? I would think, with the same certificate, the same code, and the same data, the signature should be the same.
(The example is written in C# 4.5.2.)
You have some code to reopen the CAPI key handle under PROV_RSA_AES:
// Force use of Enhanced RSA and AES Cryptographic Provider to allow use of SHA256.
var key = cert.PrivateKey as RSACryptoServiceProvider;
var enhanced = new RSACryptoServiceProvider().CspKeyContainerInfo;
var parameters = new CspParameters(
enhanced.ProviderType,
enhanced.ProviderName,
key.CspKeyContainerInfo.UniqueKeyContainerName);
return new RSACryptoServiceProvider(parameters);
But key.CspKeyContainerInfo.UniqueKeyContainerName isn't the name of the key (it's the name of the file on disk where the key lives), so you're opening a brand new key (you're also generating a new ephemeral key just to ask what the default provider is). Since it's a named key it persists, and subsequent application executions resolve to the same key -- but a different "same" key on each computer.
A more stable way of reopening the key is
var cspParameters = new CspParameters
{
KeyContainerName = foo.CspKeyContainerInfo.KeyContainerName,
Flags = CspProviderFlags.UseExistingKey,
};
(since the provider type and name aren't specified they will use the defaults, and by saying UseExistingKey you get an exception if you reference a key that doesn't exist).
That said, the easiest fix is to stop using RSACryptoServiceProvider. .NET Framework 4.6 (and .NET Core 1.0) have a(n extension) method on X509Certificate2, GetRSAPrivateKey(), it returns an RSA (which you should avoid casting) which is usually RSACng (on Windows), but may be RSACryptoServiceProvider if only CAPI had a driver required for a HSM, and may be some other RSA in the future. Since RSACng handles SHA-2 better there's almost never a need to "reopen" the return object (even if it's RSACryptoServiceProvider, and even if the type isn't PROV_RSA_AES (24), that doesn't mean the HSM will fail to do SHA-2).

Construct RSACryptoServiceProvider from public key (not certificate)

I am working on a project where I need to use a "public key" to encrypt a message using RSA algorithm. I was provided with a certificate and my first thought was to use Public Key from that certificate and after investigation I learned I need to use RSACryptoServiceProvider for encryption.
I have checked msdn and only method I thought I should use is RSACryptoServiceProvider.ImportCspBlob(byte[] keyBlob).
When I tried to use public key exported from certificate I was getting an error that the header data for certificate is invalid.
I know I can cast X509certificate2.PublicKey.Key to RSACryptoServiceProvider but from what I understood from my client is that going forward I will be given only a public key and not the certificate. This key will have to be saved in .xml configuration file.
So to summarize: Is there a way to generate an RSACryptoServiceProvider given only a certificate's public key?
You can try to look at this example: RSA public key encryption in C#
var publicKey = "<RSAKeyValue><Modulus>21wEnTU+mcD2w0Lfo1Gv4rtcSWsQJQTNa6gio05AOkV/Er9w3Y13Ddo5wGtjJ19402S71HUeN0vbKILLJdRSES5MHSdJPSVrOqdrll/vLXxDxWs/U0UT1c8u6k/Ogx9hTtZxYwoeYqdhDblof3E75d9n2F0Zvf6iTb4cI7j6fMs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
var testData = Encoding.UTF8.GetBytes("testing");
using ( var rsa = new RSACryptoServiceProvider(1024))
{
try
{
// client encrypting data with public key issued by server
//
rsa.FromXmlString(publicKey);
var encryptedData = rsa.Encrypt(testData, true);
var base64Encrypted = Convert.ToBase64String(encryptedData);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
You are OK and following a good typical pattern. The Sender of the data does not need the private key.
The following may confirm some of the code you already have figured out.
The one line where I set the private key for the receiver/decoder I left out.
I took this from a test case I have in my build deploy stuff.
byte[] certBytAr; // This is the certificate as bianry in a .cer file (no private key in it - public only)
X509Certificate2 cert2 = new X509Certificate2(certBytAr);
string strToEncrypt = "Public To Private Test StackOverFlow PsudeoCode. Surfs Up at Secret Beach.";
byte[] bytArToEncrypt = Encoding.UTF8.GetBytes(strToEncrypt);
RSACryptoServiceProvider rsaEncryptor = (RSACryptoServiceProvider)cert2.PublicKey.Key;
byte[] dataNowEncryptedArray = rsaEncryptor.Encrypt(bytArToEncrypt, true);
// done - you now have encrypted bytes
//
// somewhere elxe ...
// this should decrpyt it - simulate the destination which will decrypt the data with the private key
RSACryptoServiceProvider pk = // how this is set is complicated
// set the private key in the x509 oobject we created way above
cert2.PrivateKey = pk;
RSACryptoServiceProvider rsaDecryptor = (RSACryptoServiceProvider)cert2.PrivateKey;
byte[] dataDecrypted = rsaDecryptor.Decrypt(dataNowEncryptedArray, true);
Console.WriteLine(" encrypt 1 Way Intermediate " + BitConverter.ToString(dataDecrypted));
string strDecodedFinal = Encoding.UTF8.GetString(dataDecrypted);
if (strDecodedFinal == strToEncrypt)
{
}
else
{
Console.WriteLine(" FAILURE OF ENCRYPTION ROUND TRIP IN SIMPLE TEST (Direction: Public to Private). No Surfing For You ");
}

unexpected CryptographicException: Keyset does not exist AND CryptographicException: Access is denied

We're trying to do this for our C# (.net 3.5) application on our XP SP2 machines (Win7 later).
In our installer (created by VS2008), we're encrypting our connection string with AES key and iv, and then creating a RSA key-pair and storing them in MachineKeyStore. The installer will use the RSA public key to encrypt the AES key and iv, and store the encrpted key and iv with the encrypted connection string.
After installation, our application will read the encrypted connection string with the encrypted AES key and iv back, and use the RSA private key (from MachineKeyStore) to decrypt the AES key and iv and then decrypt the connection string with the AES key and iv.
The installer and our application share a constant string for the container name of the MachineKeyStore.
I know where the key-pair is stored, so I can monitor it to see if key-pair is deleted, updated or created.
I did some tests and found some interesting things (unexpected) but don't know why it is like that. My user account is Admin account.
The installer can delete the stored key-pair created by our application and create a new one immediately with the same container name;
The installer can update key-pair created by our application (not delete and create again, it is overwriting, I think - but this should not happen according to the doc)
Our application cannot delete the key-pair created by the installer: CryptographicException: Keyset does not exist. exception will happen when the key-pair actually exists there;
Our application cannot create a new one when the installer-created key-pair is there: CryptographicException: Keyset does not exist.
Our application cannot access the key-pair created by the installer,
CryptographicException: Access is denied. will happen in that case. The encryption in the installer works with AES and RSA public key. When the application tries to use the stored private key to do decryption, an "Access is denied" exception will occur.
Our code follows:
public static void CreateRSAKeyPair(string keyContainerName)
{
DeleteRSAKeyPair(keyContainerName);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
}
}
public static void DeleteRSAKeyPair(string keyContainerName)
{
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
try
{
rsa.Clear();
}
catch (CryptographicException ex)
{
Log.logItem(LogType.Exception, "RSA key clear error, can be ignored", "SecurityMgr::DeleteRSAKeyPair()", "CryptographicException msg=" + ex.ToString());
}
}
}
Code to access private key for decryption:
private static byte[] RSADecrypt(byte[] inputData, string keyContainerName)
{
byte[] resultData = null;
try
{
CspParameters cspParams = new CspParameters();
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
cspParams.KeyContainerName = keyContainerName;
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams))
{
//rsaProvider.PersistKeyInCsp = true;
//private key
RSAParameters rsaParams = rsaProvider.ExportParameters(true);
rsaProvider.ImportParameters(rsaParams);
resultData = rsaProvider.Decrypt(inputData, false);
}
}
catch (CryptographicException ex)
{
string msg = "CryptographicException: keyContainerName=" + keyContainerName + "\nmsg=" + ex.ToString();
Log.logItem(LogType.Exception, "RSA decryption exception", "SecurityMgr::RSADecrypt()", msg);
}
return resultData;
}
Can RSA asymmetric encryption be used like this?
EDIT:
Doing the same thing (with AES and RSA encryption) for the connection string within our application (without the installer involved) works fine.
The actual question is not very clear. However, I see a few things in your code:
You export the key pair (private and public) from the Provider into the parameters. People get confused about the boolean parameter. IT does not mean it exports ONLY the private key. If you set it to true (export private key) both your PUBLIC and PRIVATE keys will be exported.
The same keys you exported from your RSA Provider instance, you are importing back into the same provider. That does not make any sense.
Remove the ExportParameters and ImportParameters lines, they accomplish nothing. Your key(s) should already be into the RSA Provider if the container name you specified in the constructor is valid and exists.
With asymmetric cryptography you use the PRIVATE key to encrypt because that you do not share. You then use the PUBLIC key to decrypt because the other party (receiver) should only hold your PUBLIC key to be able to decrypt. If they have your PRIVATE key the whole scheme is compromised.

Categories

Resources