Environment: VS 2019, Core 3.1, C# 8.0
I'm getting the following error while trying to add a .cer and .key file to my httpClientHandler:
{"ASN1 corrupted data."}
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233087
HelpLink: null
InnerException: null
Message: "ASN1 corrupted data."
Source: "System.Security.Cryptography.Algorithms"
StackTrace: " at System.Security.Cryptography.Asn1.AsnReader.CheckExpectedTag(Asn1Tag tag, Asn1Tag expectedTag, UniversalTagNumber tagNumber)\r\n at System.Security.Cryptography.Asn1.AsnReader.ReadSequence(Asn1Tag expectedTag)\r\n at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(AsnReader reader, Asn1Tag expectedTag, RSAPrivateKeyAsn& decoded)\r\n at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(Asn1Tag expectedTag, ReadOnlyMemory`1 encoded, AsnEncodingRules ruleSet)\r\n at System.Security.Cryptography.Asn1.RSAPrivateKeyAsn.Decode(ReadOnlyMemory`1 encoded, AsnEncodingRules ruleSet)\r\n at System.Security.Cryptography.RSAKeyFormatHelper.FromPkcs1PrivateKey(ReadOnlyMemory`1 keyData, AlgorithmIdentifierAsn& algId, RSAParameters& ret)\r\n at System.Security.Cryptography.RSA.ImportRSAPrivateKey(ReadOnlySpan`1 source, Int32& bytesRead)\r\n at BnyMellon.Program.CreateFromCertFile(String cerFile, String keyFile) in C:\\Users\\bbernzweig.AD\\source\\repos\\HttpClientExample\\
BnyMellon\\Program.cs:line 150"
TargetSite: {Void CheckExpectedTag(System.Security.Cryptography.Asn1.Asn1Tag, System.Security.Cryptography.Asn1.Asn1Tag, System.Security.Cryptography.Asn1.UniversalTagNumber)}
Error is raised here on line rsa.ImportRSAPrivateKey(privateKeyBytes, out _);:
private static X509Certificate2 CreateFromCertFile(string cerFile, string keyFile)
{
try
{
var cert = new X509Certificate2 (cerFile);
var privateKeyBytes = LoadPrivateKeyBytes(keyFile);
using var rsa = RSA.Create();
rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
var certWithKey = cert.CopyWithPrivateKey(rsa);
cert.Dispose();
return certWithKey;
}
catch(Exception e)
{
Console.WriteLine(e);
}
return null;
}
Called from:
var clientCertificate = new X509Certificate2();
clientCertificate = CreateFromCertFile(certificateFile, keyFile);
httpClientHandler.ClientCertificates.Add(clientCertificate);
Note: I'm able to make the request using both of these files via curl and Postman without any problem.
I'm trying to attaching both files to the request so not tied to this specific approach. If there is a better way I'm interested in hearing about it.
Super late to this, and faced the same problem ASN1 corrupted data and managed to resolve my problem from both your question and the question answered by #bartonjs
The advice on Create X509Certificate2 from Cert and Key, without making a PFX file question is
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(binaryEncoding, out _);
// do stuff with the key now
}
The clue for me was binaryEncoding, the answer is commented as part of the same question is...
if you had a PEM you need to "de-PEM" it, by extracting the contents between the BEGIN and END delimiters and running it through Convert.FromBase64String in order to get binaryEncoding
So based on your code... the following imports the PEM file without issue.
private static byte[] LoadPrivateKeyBytes(string keyFile)
{
// remove these lines
// -----BEGIN RSA PRIVATE KEY-----
// -----END RSA PRIVATE KEY-----
var pemFileData = File.ReadAllLines(keyFile).Where(x => !x.StartsWith("-"));
// Join it all together, convert from base64
var binaryEncoding = Convert.FromBase64String(string.Join(null, pemFileData));
// this is the private key byte data
return binaryEncoding;
}
private static X509Certificate2 CreateFromCertFile(string cerFile, string keyFile)
{
try
{
var cert = new X509Certificate2(cerFile);
var privateKeyBytes = LoadPrivateKeyBytes(keyFile);
using var rsa = RSA.Create();
rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
var certWithKey = cert.CopyWithPrivateKey(rsa);
cert.Dispose();
return certWithKey;
}
catch (Exception e)
{
Console.WriteLine(e);
}
#pragma warning disable CS8603 // Possible null reference return.
return null;
#pragma warning restore CS8603 // Possible null reference return.
}
Related
I'm writing a .NET 6 application for Windows that is intended to extract the private key from a PFX file containing an RSA cert/key bundle.
public static Boolean ToCertAndKey(String pfxFilePath, String? unlockPassword, String certFilePath, String keyFilePath, String? keyPassword, out String error) {
try {
error = String.Empty;
using var bundle = new X509Certificate2(pfxFilePath, unlockPassword);
RSA key = bundle.GetRSAPrivateKey();
Byte[] publicKeyBytes = key.ExportSubjectPublicKeyInfo();
Byte[] privateKeyBytes;
//We fail here.
if (String.IsNullOrEmpty(keyPassword)) {
privateKeyBytes = key.ExportPkcs8PrivateKey();
} else {
privateKeyBytes = key.ExportEncryptedPkcs8PrivateKey(keyPassword,
new PbeParameters(
PbeEncryptionAlgorithm.Aes256Cbc,
HashAlgorithmName.SHA256,
iterationCount: 1));
}
String encodedCert = new(PemEncoding.Write("PUBLIC KEY", publicKeyBytes));
File.WriteAllText(certFilePath, encodedCert);
String encodedKey = new(PemEncoding.Write("PRIVATE KEY", privateKeyBytes));
File.WriteAllText(keyFilePath, encodedKey);
return true;
} catch (Exception ex) {
error = $"An exception occurred: '{ex.Message}'\r\n\r\nStack Trace:\r\n{ex.StackTrace}";
return false;
}
}
It fails at both ExportPkcs8PrivateKey (When I don't specify a password to encrypt the key) and ExportEncryptedPkcs8PrivateKey (when I do) with the same exception text:
WindowsCryptographicException: The requested operation is not supported
I came across this answer however, I'm still receiving the same exception at RSA.ExportEncryptedPkcs8PrivateKey.
There doesn't appear to be anything wrong with the PFX files I've been testing with; I'm able to import them into my certstore via the UI or PowerShell with no issues.
Hoping someone else has run into this issue.
You need to mark the keys as exportable.
Change
using var bundle = new X509Certificate2(pfxFilePath, unlockPassword);
to
using var bundle = new X509Certificate2(pfxFilePath, unlockPassword, X509KeyStorageFlags.Exportable);
I received from a client public certificate and private RSA key, as follows (only partially displayed here):
-----BEGIN CERTIFICATE-----
MIIFKDCCAxACAQEwDQYJKoZIhvcNAQELBQAwbjELMAkGA1UEBhMCVVMxETAPBgNV
BAgMCElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRMwEQYDVQQKDApDbG91ZFF1
YW50MSUwIwYJKoZIhvcNAQkBFhZjcWFpb3BzQGNsb3VkcXVhbnQuY29tMB4XDTIw
MDkyMzIwMTgyN1oXDTQwMDkxODIwMTgyN1owRjELMAkGA1UEBhMCVVMxETAPBgNV
iESEKmYvylUwce7TcOuVnLtufyXxr8egu43jPvWDHsK0QvhMbx0q2KvyxGneQJ5E
...........
U0oIrq7M0qZTAf1BXEw9wgfQlIKfLzWDbIYKIg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAuxHk8lBZaqRTzhi/jvlj59pehTkK/u2fVHLuHWZPGOvPiAjq
HqrAgM1urPpmQPC2QuWObmhvQ1uluo/tq6V56WZNUEYALZnXhGvVNrvnYfoFooI0
F+1dJI2xQ8AC11Khinj+yAPtKymMhZFOHzQaFnGvjhKWTn/I0MaoJc+TQ8JKbDQ0
ycvopM2finujmIb62cxxhkhkEC5T+yMUJ8MbCnfmWpYux/oU2CXSHrnPympCbx7x
cReH0BeZEZPMI7+1Yi7U+XKGc7RP+zt9AoIBAQDE0BZb3WfertNqmyj9TF73VAwq
SDtSa6MTC8bOdtQewCz9/zC13MSI+jZGRDKSh7nxNL+bgM0OgmM6n/5B/61SIRjM
hswgOU9AHewIFSB/5C/ZcxWqM+PrgYXXYfOl9ZeWs1x+YRKuqk/CW/Z2rHJXykNx
.............
czG95J+2TWdGAjPuFLA596PRXT5KN2ITOWXUym3UksHmonbJ9om+k0ckPr4J
-----END RSA PRIVATE KEY-----
Initially, I scanned many postings here and realized that the easiest way to combine the puplic PEM certificate with private RSA key (PEM format) is by using .NET 5:
// Needs .NET 5, that is .NET Core and VS2019 16.8 or higher
X509Certificate2 X509Cert = X509Certificate2.CreateFromPemFile("cert.cer", "cert.key");
X509Certificate2 cert = new X509Certificate2(mX509Cert.Export(X509ContentType.Pfx, "12345678"), "12345678");
This worked great.
However, later on I realized that the type of project I am targeting (VSTO Excel Add-In) is not supporting .NET 5 yet...
Therefore, I changed the above code to the following, (which also worked) not realizing that it also requires .NET 5...
X509Certificate2 pubOnly = new X509Certificate2("cert.cer");
RSA rsa = RSA.Create();
rsa.ImportRSAPrivateKey(keyBuffer, out _);
X509Certificate2 pubPrivEphemeral = pubOnly.CopyWithPrivateKey(rsa);
X509Certificate2 cert = new X509Certificate2(pubPrivEphemeral.Export(X509ContentType.Pfx, "12345678"), "12345678");
Then when I finally switched to .NET 4.7.2 and now 4.8 I was looking for compatible way to do the same, and tired several methods offered here, but in vain, none did not work - they had complex routines that threw exceptions...
So I am trying now BouncyCastle that helped a lot in the past and came up with this code:
string cerFilePath = Path.Combine(InstallDir, "cert.cer");
X509Certificate2 dotnetCertificate2 = new X509Certificate2(cerFilePath);
string keyFilePath = Path.Combine(InstallDir, "cert.key");
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(File.OpenText(keyFilePath));
var pemObject = pemReader.ReadObject();
var rsa = DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)pemObject);
Unfortunately, the last line throws exception - there is something incompatible here and I do not know what it is... The exception message states:
"Unable to cast object of type 'Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair' to type 'Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters'."
So if anyone can either correct me with the above BouncyCastle code or show me pure .NET 4.6 - 4.8 code - I'd really appreciate.
EDIT:
So I did find another code from here
private X509Certificate2 CreateCertWithKey()
{
using (Log.VerboseCall())
{
X509Certificate2 x509Cert = null;
try
{
string cerFilePath = Path.Combine(InstallDir, "cert.cer");
using (TextReader tr = new StreamReader(cerFilePath))
{
publicPemCert = tr.ReadToEnd();
}
string keyFilePath = Path.Combine(InstallDir, "cert.key");
using (TextReader tr = new StreamReader(keyFilePath))
{
privatePemKey = tr.ReadToEnd();
}
var keyPair = (AsymmetricCipherKeyPair)new PemReader(new StringReader(privatePemKey)).ReadObject();
var cert = (Org.BouncyCastle.X509.X509Certificate)new PemReader(new StringReader(publicPemCert)).ReadObject();
var builder = new Pkcs12StoreBuilder();
builder.SetUseDerEncoding(true);
var store = builder.Build();
var certEntry = new X509CertificateEntry(cert);
store.SetCertificateEntry("", certEntry);
store.SetKeyEntry("", new AsymmetricKeyEntry(keyPair.Private), new[] { certEntry });
byte[] data;
using (var ms = new MemoryStream())
{
//store.Save(ms, Array.Empty<char>(), new SecureRandom());
data = ms.ToArray();
x509Cert = new X509Certificate2(data);
}
}
catch(Exception ex)
{
Log.Verbose(ex);
}
return x509Cert;
}
}
It runs without problem but with the generated certificate my HttpWebRequest does not work, claiming that TSL/SSL connection cannot be created (and I tries 1.1, 1.2, and 1.3, although I recall that just Tls negotiates the version by itself...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
The .NET 5 code ran without a problem with exactly the same code for HttpWebRequest...
Just came across this while working through similar issues and I found a way to create the X509Certificate2 object that includes the private key (which I use for XML Signing). It requires that you create a PFX record using the public/private keys, I used OpenSSL:
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
You can either open just instantiate the instance directly with the file name:
var cert = new X509Certificate2(filePath);
Or if you have already opened the file somewhere and stored it in base64 format, you can use the bytes:
var bytes = Convert.FromBase64String(pfx_base64);
var cert = new X509Certificate2(bytes);
A lot of credit for this goes to reading Scott Brady's blog.
I am fetching my certificate from Azure Key Vault using GetSecretAsync() method and then I am expecting to get the byte[] of the private key and the certificate eventually.
I have my application in .netcore3.1
This is how my code looks like :
var certWithPrivateKey = Client.GetSecretAsync(ConfigurationSettings.AppSettings["AKVEndpoint"], ConfigurationSettings.AppSettings["CertName"]).GetAwaiter().GetResult();
var privateKeyBytes = Convert.FromBase64String(certWithPrivateKey.Value);
X509Certificate2 x509Certificate = new X509Certificate2(privateKeyBytes);
var privateKey = x509Certificate.GetRSAPrivateKey() as RSA;
I get a valid privateKey of type RSACng, but any operation (tried ExportRSAPrivateKey()) on that throws an error of "'privateKey.ExportRSAPrivateKey()' threw an exception of type 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException'" and "The requested operation is not supported."
I am not sure how to proceed next here to get the byte[] of the private key and certificate.
Since you do actually seem to need to export: Your current code doesn't load the private key as exportable, so it can't be exported. The fix is to assert exportability:
X509Certificate2 x509Certificate =
new X509Certificate2(privateKeyBytes, "", X509KeyStorageFlags.Exportable);
If that's not enough, then you're encountering the difference between CAPI exportability and CNG exportability (Windows older, and newer, crypto libraries). If the private key from a PFX/PKCS#12 gets loaded into CNG it's only "encrypted exportable", but ExportParameters is plaintext-export.
There's a workaround, though... export it encrypted, then import that somewhere else with a more flexible export policy, then export again.
This snippet uses the .NET Core 3.0+ ExportPkcs8PrivateKey() method, since that's the format you want your data in, and new .NET 5 PemEncoding class to simplify turning the DER encoded output into PEM+DER output. If your exporter is on .NET Framework, this is a more complex problem. For .NET Standard 2.0 there's not really a clean solution (reflect call the methods for .NET Core/.NET 5, otherwise use the Windows-specific version for .NET Framework?).
byte[] pkcs8PrivateKey;
using (RSA privateKey = x509Certificate.GetRSAPrivateKey())
{
pkcs8PrivateKey = ExportPrivateKey(privateKey);
}
File.WriteAllText(
"tls.cer",
new string(PemEncoding.Write("CERTIFICATE", x509Certificate.RawData));
File.WriteAllText(
"tls.key",
new string(PemEncoding.Write("PRIVATE KEY", pkcs8PrivateKey));
...
private static byte[] ExportPrivateKey(RSA privateKey)
{
try
{
// If it's plaintext exportable, just do the easy thing.
return privateKey.ExportPkcs8PrivateKey();
}
catch (CryptographicException)
{
}
using (RSA exportRewriter = RSA.Create())
{
// Only one KDF iteration is being used here since it's immediately being
// imported again. Use more if you're actually exporting encrypted keys.
exportRewriter.ImportEncryptedPkcs8PrivateKey(
"password",
privateKey.ExportEncryptedPkcs8PrivateKey(
"password",
new PbeParameters(
PbeEncryptionAlgorithm.Aes128Cbc,
HashAlgorithmName.SHA256,
1)),
out _);
return exportRewriter.ExportPkcs8PrivateKey();
}
}
I'm facing a couple of issues with a Java app and another in C#. Here is the thing. There's a server application that receives request through HTTP, process it and sends
back the response. This server is writting in Java with Bouncy Castle and we use PKI to encrypt sensitive data in the request. We have many operations that the server recognizes
and one of the them is used to generate the the public and private keys used to exchange with the clients. Each client has a unique ID, so when this operation named
GetEncryptionKey is executed, it generates the private key and save it locally in the server and generates the public key which is sent back in PEM format, like this:
encryptionKey=-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAon1WDHdarN7yq0UOevzW
5PiFsSC8bEkTUOZ6X3RIth+RCU42pUj/Z8fp9T8rbWp8CqbhlFDxU4c+YucpGljC
7A10nkrPoBT0lpHEuXJiSgx+9qqsyo9q6GddhOpdMa+Z6VCfI+JCM3kdJNMH3r+o
i+WLPHLB8lxnfT2CHyZVQGhkzrH9fk1XhdenXxjtPGpwYBOsUZUwRt8EeW6JUwSI
mKXiXag0IViEcyAa2BvProkxklbQB3BczLHdXjIDwnE6u1aMA7pYPSkBtY6tuQ0F
5sNWXHsaKWON33MnbhlM7sieYDi9L4dWksala/m/mdIeHIXzX4ZCYdOhayWWKZ1N
HwIDAQAB
-----END PUBLIC KEY-----
This is working ok. The code used to generate the key is the following one:
private void getEncryptedKey() throws GWTranException {
PEMWriter pemWriter;
Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = null;
KeyPairGenerator keyPairGenerator = null;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
StringWriter writer = new StringWriter();
try {
pemWriter = new PEMWriter(new PrintWriter(writer));
pemWriter.writeObject(keyPair.getPublic());
pemWriter.flush();
String pem = writer.toString();
savePrivateKey(keyPair, pem); // save the private key locally
} catch (IOException e) {
e.printStackTrace();
}
}
Now I have a client written in C# that connects to the server, retrieves the Public Key sent in the response and use it to encrypt a string that will travel encrypted.
This is the .NET code (very simple, as I'm just testing the functionality):
private string EncryptDataWithRSA(string data) {
string cryptedData = string.Empty;
RsaKeyParameters rsaParams;
using (var reader = new StringReader(txtKey.Text)) {
rsaParams = (RsaKeyParameters)new PemReader(reader).ReadObject();
reader.Close();
}
IAsymmetricBlockCipher eng = new RsaEngine();
eng = new OaepEncoding(eng);
eng.Init(true, rsaParams);
var dataBytes = Encoding.UTF8.GetBytes(data);
var cryptedDataBytes = eng.ProcessBlock(dataBytes, 0, dataBytes.Length);
cryptedData = Convert.ToBase64String(cryptedDataBytes);
return cryptedData;
}
Everything looks nice but the problem is that when the server (Java app) tries to decrypt the data I get an exception:
javax.crypto.BadPaddingException: data hash wrong
at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.verifone.gateway.security.RSAEncryptUtil.decrypt(RSAEncryptUtil.java:127)
at com.verifone.gateway.security.RSAEncryptUtil.decrypt(RSAEncryptUtil.java:152)
at com.verifone.gateway.preonline.PreOnlineJob.decryptData(PreOnlineJob.java:1661)
at com.verifone.gateway.preonline.PreOnlineJob.extractCardData(PreOnlineJob.java:989)
at com.verifone.gateway.preonline.PreOnlineJob.run(PreOnlineJob.java:288)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
This is working fine with another client writting in iOS but I don't have access to the source code. I'm writting a simulator in .NET but I'm not being able to
get the information decrypted correctly. On the server side this is part of the code used to decrypt the data:
public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception
{
byte[] dectyptedText = null;
try {
// decrypt the text using the private key
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
}
catch (Exception e) {
//_log.error(e, e);
throw e;
}
return dectyptedText;
}
I'm out of ideas, I've tried everything. Do you see something I don't?
Thanks for your help.
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 ");
}