I am using the key-pair to sign my XML (using SignedXml) and I embed the public key in my app as embedded resources.
Here how I create the key pair
sn -k Warehouse.snk
sn -p Warehouse.snk WarehousePublic.snk
When I tried to read the WarehousePublic.snk I get an exception Bad Version of provider.
Here is my code:
using (Stream stream = assembly.GetManifestResourceStream("WareApp.Resources.WarehousePublic.snk"))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(bytes); //the exception occurred here
...
...
...
}
}
Is there a way to create RSACryptoServiceProvider from public key only?
I have also tried to use X509Certificate2
X509Certificate2 cert = new X509Certificate2(bytes); //I got exception here
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert2.PublicKey.Key;
But I get exception Cannot find the requested object.
Any idea?
Thanks
I'll accepted Shaamaan answer because he is "half" right. You can actually use SN to sign certificate. ImportCspBlob() will work! However, when you tried to to import public key that generated using sn -p Warehouse.snk WarehousePublic.snk, it won't work.
In order to make it work, you need to generate public key in XML using RSACryptoServiceProvider.ToXmlString(false) and embed it as "embedded resources".
What I did is I create a console application. Just cut and paste my code below to generate public key in XML file.
class Program
{
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("Invalid Argument");
Console.WriteLine("Usage:");
Console.WriteLine("\tExtractPublicKey [Input SNK File] [Output XML File]");
return;
}
using (FileStream fs = File.Open(args[0], FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(bytes);
using (StreamWriter sw = new StreamWriter(File.Open(args[1], FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)))
sw.Write(rsa.ToXmlString(false));
}
}
}
}
After you compile it, to use the executable simply call:
ExtractPublicKey.exe [SNK File with Private Key] [Output Public Key in XML File]
To use the embedded certificate, simply do:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(stream.ReadToEnd());
I hope this help someone that come across the similar problem.
Cheers
UPDATED
Shaamaan answer should be followed. Please READ Shaamaan comment with MSDN link. He answer stands because he is not ONLY provide a correct way for security, but also inform me why SN is not right security tool. Thank you Shaamaan!
I think using SN to generate certificates for signing (using the RSACryptoServiceProvider at least) is unsupported. That would explain the error, I think. What you're looking for, in Windows, is a .PFX file (i.e. certificate with key) and .CER file (certificate without private key).
SN (MSDN link) doesn't provide security, and is only used for identity. You can use IIS or makecert.exe to generate a self-signed certificate that should work with what you're trying to do (i.e. a .PFX file and / or certificate already imported into the Windows certificate store). You can then extract the .CER file from that and use it for your project.
Related
I've got a .PEM file that I want to convert to a PKCS12 file (PFX), and I know I can easily accomplish this using the following openssl command:
Create a PKCS#12 file:
openssl pkcs12 -export -in file.pem -out file.p12 -name "My Certificate"
Which is great, but I'd like to do this programmatically using OpenSSL calls. Unfortunately, documentation for OpenSSL is less than ideal.
I've looked into doing this using other libraries:
Using .NET: I can create a X509Certificate2 object from a PEM file, but this only grabs the first certificate and ignores any intermediate CA's in the PEM file.
Using Mentalis.org Security Library: I can create a Certificate object from a PEM file, but I see the following in the documentation:
Remarks
This implementation only reads
certificates from PEM files. It does
not read the private key from the
certificate file, if one is present.
So, that doesn't help me. I need that private key too.
I basically need to recreate the OpenSSL command line tool operation for going PEM>PFX, but in code.
Is there an easier way to do this?
You could use BouncyCastle (assuming C#, because you mentioned .NET).
Let's say localhost.pem here contains both the certificate and the private key, something like this should work:
using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Security;
namespace TestApplication
{
class Program
{
static void Main(string[] args)
{
StreamReader sr = File.OpenText("localhost.pem");
IPasswordFinder passwordFinder = new PasswordStore("testtest".ToCharArray());
PemReader pemReader = new PemReader(sr, passwordFinder);
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
X509CertificateEntry[] chain = new X509CertificateEntry[1];
AsymmetricCipherKeyPair privKey = null;
object o;
while ((o = pemReader.ReadObject()) != null)
{
if (o is X509Certificate)
{
chain[0] = new X509CertificateEntry((X509Certificate)o);
}
else if (o is AsymmetricCipherKeyPair)
{
privKey = (AsymmetricCipherKeyPair)o;
}
}
store.SetKeyEntry("test", new AsymmetricKeyEntry(privKey.Private), chain);
FileStream p12file = File.Create("localhost.p12");
store.Save(p12file, "testtest".ToCharArray(), new SecureRandom());
p12file.Close();
}
}
class PasswordStore : IPasswordFinder
{
private char[] password;
public PasswordStore(
char[] password)
{
this.password = password;
}
public char[] GetPassword()
{
return (char[])password.Clone();
}
}
}
You'll probably need something a bit more subtle for the IPasswordFinder and if you want to handle certificate chains correctly.
For more advanced features, you may be able to find more details in the BouncyCastle examples.
I'm trying to encrypt a string given a public key that I've retrieved from an API. The public key is plain text (base 64 encoded), something like:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCH9/o5IG0tu9VNYiJSltzV5ewK9TNoLeToSYkoH4lEytRM61AMeO6aBRZ3dsY1Czb+fgK6Q+M4ub/9jbcXIGmVLvTypdn+VW1dotXzMP5sfDgCUuhScjH7gqsXQAvaF5LxjLUbL5I5zCGXbPVwBCEyVhN0oNp3TtNKoMcF6AjNhwIDAQAB
I now want to encrypt a string using this public key. I've found some relevant code that reads from a PEM format, but obviously it won't work here:
byte[] dataToEncrypt = Encoding.UTF8.GetBytes(aString);
var encryptEngine = new Pkcs1Encoding(new RsaEngine());
using (var txtreader = new StringReader(key))
{
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
encryptEngine.Init(true, keyParameter);
}
var encrypted = Convert.ToBase64String(encryptEngine.ProcessBlock(dataToEncrypt, 0, dataToEncrypt.Length));
keyParameter ends up being null. The documentation for Bouncycastle seems to be pretty scant, I don't really have an idea of what I should be using to get the right AsymmetricKeyParameter type.
I suppose I could write a PEM file from the key but feels a bit wasteful.
So the broader question is: How do I encrypt using PKSC1 padding when I have the public key as a string already?
The more precise question is: What AsymmetricKeyParameter type should I be using?
Thanks in advance.
EDIT
I've found a workaround using the native RSACryptoServiceProvider here. Still, would be good to know how to do this with BC.
I am staring at this for quite a while and thanks to the MSDN documentation I cannot really figure out what's going. Basically I am loading a PFX file from the disc into a X509Certificate2 and trying to encrypt a string using the public key and decrypt using the private key.
Why am I puzzled: the encryption/decryption works when I pass the reference to the RSACryptoServiceProvider itself:
byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider);
string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider);
But if the export and pass around the RSAParameter:
byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false));
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true));
...it throws a "Key not valid for use in specified state." exception while trying to export the private key to RSAParameter. Please note that the cert the PFX is generated from is marked exportable (i.e. I used the pe flag while creating the cert). Any idea what is causing the exception?
static void Main(string[] args)
{
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test");
x.FriendlyName = "My test Cert";
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
try
{
store.Add(x);
}
finally
{
store.Close();
}
byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider);
string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider);
byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false));
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true));
}
private static byte[] EncryptRSA(string data, RSAParameters rsaParameters)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] plainData = bytConvertor.GetBytes(data);
RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
publicKey.ImportParameters(rsaParameters);
return publicKey.Encrypt(plainData, true);
}
private static string DecryptRSA(byte[] data, RSAParameters rsaParameters)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
RSACryptoServiceProvider privateKey = new RSACryptoServiceProvider();
privateKey.ImportParameters(rsaParameters);
byte[] deData = privateKey.Decrypt(data, true);
return bytConvertor.GetString(deData);
}
private static byte[] EncryptRSA(string data, RSACryptoServiceProvider publicKey)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] plainData = bytConvertor.GetBytes(data);
return publicKey.Encrypt(plainData, true);
}
private static string DecryptRSA(byte[] data, RSACryptoServiceProvider privateKey)
{
UnicodeEncoding bytConvertor = new UnicodeEncoding();
byte[] deData = privateKey.Decrypt(data, true);
return bytConvertor.GetString(deData);
}
Just to clarify in the code above the bold part is throwing:
string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider)**.ExportParameters(true)**);
I believe that the issue may be that the key is not marked as exportable. There is another constructor for X509Certificate2 that takes an X509KeyStorageFlags enum. Try replacing the line:
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test");
With this:
X509Certificate2 x = new X509Certificate2(#"C:\temp\certs\1\test.pfx", "test", X509KeyStorageFlags.Exportable);
For the issue I encountered a code change was not an option as the same library was installed and working elsewhere.
Iridium's answer lead me to look making the key exportable and I was able to this as part of the MMC Certificate Import Wizard.
Hope this helps someone else. Thanks heaps
I've met some similar issue, and X509KeyStorageFlags.Exportable solved my problem.
I'm not exactly an expert in these things, but I did a quick google, and found this:
http://social.msdn.microsoft.com/Forums/en/clr/thread/4e3ada0a-bcaf-4c67-bdef-a6b15f5bfdce
"if you have more than 245 bytes in your byte array that you pass to your RSACryptoServiceProvider.Encrypt(byte[] rgb, bool fOAEP) method then it will throw an exception."
For others that end up here through Google, but don't use any X509Certificate2, if you call ToXmlString on RSACryptoServiceProvider but you've only loaded a public key, you will get this message as well. The fix is this (note the last line):
var rsaAlg = new RSACryptoServiceProvider();
rsaAlg.ImportParameters(rsaParameters);
var xml = rsaAlg.ToXmlString(!rsaAlg.PublicOnly);
AFAIK this should work and you're likely hitting a bug/some limitations. Here's some questions that may help you figure out where's the issue.
How did you create the PKCS#12 (PFX) file ? I've seen some keys that CryptoAPI does not like (uncommon RSA parameters). Can you use another tool (just to be sure) ?
Can you export the PrivateKey instance to XML, e.g. ToXmlString(true), then load (import) it back this way ?
Old versions of the framework had some issues when importing a key that was a different size than the current instance (default to 1024 bits). What's the size of your RSA public key in your certificate ?
Also note that this is not how you should encrypt data using RSA. The size of the raw encryption is limited wrt the public key being used. Looping over this limit would only give you really bad performance.
The trick is to use a symmetric algorithm (like AES) with a totally random key and then encrypt this key (wrap) using the RSA public key. You can find C# code to do so in my old blog entry on the subject.
Old post, but maybe can help someone.
If you are using a self signed certificate and make the login with a different user, you have to delete the old certificate from storage and then recreate it. I've had the same issue with opc ua software
My application will take a set of files and sign them. (I'm not trying to sign an assembly.) There is a .p12 file that I get the private key from.
This is the code I was trying to use, but I get a System.Security.Cryptography.CryptographicException "Invalid algorithm specified.".
X509Certificate pXCert = new X509Certificate2(#"keyStore.p12", "password");
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)pXCert.PrivateKey;
string id = CryptoConfig.MapNameToOID("SHA256");
return csp.SignData(File.ReadAllBytes(filePath), id);
According to this answer it can't be done (the RSACryptoServiceProvider does not support SHA-256), but I was hoping that it might be possible using a different library, like Bouncy Castle.
I'm new to this stuff and I'm finding Bouncy Castle to be very confusing. I'm porting a Java app to C# and I have to use the same type of encryption to sign the files, so I am stuck with RSA + SHA256.
How can I do this using Bouncy Castle, OpenSSL.NET, Security.Cryptography, or another 3rd party library I haven't heard of? I'm assuming, if it can be done in Java then it can be done in C#.
UPDATE:
this is what I got from the link in poupou's anwser
X509Certificate2 cert = new X509Certificate2(KeyStoreFile, password");
RSACryptoServiceProvider rsacsp = (RSACryptoServiceProvider)cert.PrivateKey;
CspParameters cspParam = new CspParameters();
cspParam.KeyContainerName = rsacsp.CspKeyContainerInfo.KeyContainerName;
cspParam.KeyNumber = rsacsp.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2;
RSACryptoServiceProvider aescsp = new RSACryptoServiceProvider(cspParam);
aescsp.PersistKeyInCsp = false;
byte[] signed = aescsp.SignData(File.ReadAllBytes(file), "SHA256");
bool isValid = aescsp.VerifyData(File.ReadAllBytes(file), "SHA256", signed);
The problem is that I'm not getting the same results as I got with the original tool. As far as I can tell from reading the code the CryptoServiceProvider that does the actual signing is not using the PrivateKey from key store file. Is that Correct?
RSA + SHA256 can and will work...
Your later example may not work all the time, it should use the hash algorithm's OID, rather than it's name. As per your first example, this is obtained from a call to CryptoConfig.MapNameToOID(AlgorithmName) where AlgorithmName is what you are providing (i.e. "SHA256").
First you are going to need is the certificate with the private key. I normally read mine from the LocalMachine or CurrentUser store by using a public key file (.cer) to identify the private key, and then enumerate the certificates and match on the hash...
X509Certificate2 publicCert = new X509Certificate2(#"C:\mycertificate.cer");
//Fetch private key from the local machine store
X509Certificate2 privateCert = null;
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach( X509Certificate2 cert in store.Certificates)
{
if (cert.GetCertHashString() == publicCert.GetCertHashString())
privateCert = cert;
}
However you get there, once you've obtained a certificate with a private key we need to reconstruct it. This may be required due to the way the certificate creates it's private key, but I'm not really sure why. Anyway, we do this by first exporting the key and then re-importing it using whatever intermediate format you like, the easiest is xml:
//Round-trip the key to XML and back, there might be a better way but this works
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(privateCert.PrivateKey.ToXmlString(true));
Once that is done we can now sign a piece of data as follows:
//Create some data to sign
byte[] data = new byte[1024];
//Sign the data
byte[] sig = key.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
Lastly, the verification can be done directly with the certificate's public key without need for the reconstruction as we did with the private key:
key = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), sig))
throw new CryptographicException();
The use of privateKey.toXMLString(true) or privateKey.exportParameters(true) aren't usable in a secure environment, since they require your private key to be exportable, which is NOT a good practice.
A better solution is to explicitly load the "Enhanced" crypto provider as such:
// Find my openssl-generated cert from the registry
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, "myapp.com", true);
var certificate = certificates[0];
store.Close();
// Note that this will return a Basic crypto provider, with only SHA-1 support
var privKey = (RSACryptoServiceProvider)certificate.PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName);
privKey = new RSACryptoServiceProvider(cspparams);
This is how I dealt with that problem:
X509Certificate2 privateCert = new X509Certificate2("certificate.pfx", password, X509KeyStorageFlags.Exportable);
// This instance can not sign and verify with SHA256:
RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)privateCert.PrivateKey;
// This one can:
RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider();
privateKey1.ImportParameters(privateKey.ExportParameters(true));
byte[] data = Encoding.UTF8.GetBytes("Data to be signed");
byte[] signature = privateKey1.SignData(data, "SHA256");
bool isValid = privateKey1.VerifyData(data, "SHA256", signature);
I settled on changing the key file to specify the appropriate Crypto Service Provider, avoiding the issue in .NET altogether.
So when I create a PFX file out of a PEM private key and a CRT public certificate, I do it as follows:
openssl pkcs12 -export -aes256 -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -inkey priv.pem -in pub.crt -out priv.pfx
The key part being -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider".
(-inkey specifies the private key file and -in specifies the public certificate to incorporate.)
You may need to tweak this for the file formats you have on hand. The command line examples on this page can help with that:
https://www.sslshopper.com/ssl-converter.html
I found this solution here:
http://hintdesk.com/c-how-to-fix-invalid-algorithm-specified-when-signing-with-sha256/
Use can use this on more recent frameworks.
public byte[] GetSignature(byte[] inputData)
{
using (var rsa = this.signingCertificate.GetRSAPrivateKey())
{
return rsa.SignData(inputData, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
public bool ValidateSignature(byte[] inputData, byte[] signature)
{
using (var rsa = this.signingCertificate.GetRSAPublicKey())
{
return rsa.VerifyData(inputData, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
The signingCertificate above is a X509Certificate2 with a private key. This method does not require you to import any existing keys and works in a secure environment.
When you use a certificate to get your RSACryptoServiceProvider it really matters what's the underlying CryptoAPI provider. By default, when you create a certificate with 'makecert', it's "RSA-FULL" which only supports SHA1 hashes for signature. You need the new "RSA-AES" one that supports SHA2.
So, you can create your certificate with an additional option: -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (or an equivalent -sy 24) and then your code would work without the key juggling stuff.
Here is how I signed a string without having to modify the certificate (to a Microsoft Enhanced RSA and AES Cryptographic provider).
byte[] certificate = File.ReadAllBytes(#"C:\Users\AwesomeUser\Desktop\Test\ServerCertificate.pfx");
X509Certificate2 cert2 = new X509Certificate2(certificate, string.Empty, X509KeyStorageFlags.Exportable);
string stringToBeSigned = "This is a string to be signed";
SHA256Managed shHash = new SHA256Managed();
byte[] computedHash = shHash.ComputeHash(Encoding.Default.GetBytes(stringToBeSigned));
var certifiedRSACryptoServiceProvider = cert2.PrivateKey as RSACryptoServiceProvider;
RSACryptoServiceProvider defaultRSACryptoServiceProvider = new RSACryptoServiceProvider();
defaultRSACryptoServiceProvider.ImportParameters(certifiedRSACryptoServiceProvider.ExportParameters(true));
byte[] signedHashValue = defaultRSACryptoServiceProvider.SignData(computedHash, "SHA256");
string signature = Convert.ToBase64String(signedHashValue);
Console.WriteLine("Signature : {0}", signature);
RSACryptoServiceProvider publicCertifiedRSACryptoServiceProvider = cert2.PublicKey.Key as RSACryptoServiceProvider;
bool verify = publicCertifiedRSACryptoServiceProvider.VerifyData(computedHash, "SHA256", signedHashValue);
Console.WriteLine("Verification result : {0}", verify);
According to this blog it should work with FX 3.5 (see note below). However it's important to recall that most of .NET cryptography is based on CryptoAPI (even if CNG is being more and more exposed in recent FX releases).
The key point is that CryptoAPI algorithm support depends on the Crypto Service Provider (CSP) being used and that varies a bit between Windows versions (i.e. what's working on Windows 7 might not work on Windows 2000).
Read the comments (from the blog entry) to see a possible workaround where you specify the AES CSP (instead of the default one) when creating your RSACCryptoServiceProvider instance. That seems to work for some people, YMMV.
Note: this is confusing to many people because all the released .NET frameworks includes a managed implementation of SHA256 which cannot be used by CryptoAPI. FWIW Mono does not suffer from such issues ;-)
I know this is an old thread but for those still stuck in the past and looking for an answer, the following worked for me based off #BKibler's answer. The comments stated it's not using the correct key and it's because the solution is missing a couple key settings.
// Find my openssl-generated cert from the registry
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, "myapp.com", true);
var certificate = certificates[0];
store.Close();
// Note that this will return a Basic crypto provider, with only SHA-1 support
var privKey = (RSACryptoServiceProvider)certificate.PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
if (!Enum.TryParse<KeyNumber>(privKey.CspKeyContainerInfo.KeyNumber.ToString(), out var keyNumber))
throw new Exception($"Unknown key number {privKey.CspKeyContainerInfo.KeyNumber}");
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName)
{
KeyNumber = (int)keyNumber,
Flags = CspProviderFlags.UseExistingKey
};
privKey = new RSACryptoServiceProvider(cspparams);
You need to set both "KeyNumber" and "Flags" so the existing (non-exportable) key is used and you can use the public key from the certificate to verify.
I have noticed similar issues in .NET with the wrong private key being used (or was it flat-out errors? I do not recall) when the certificate I am working with is not in the user/computer certificate store. Installing it into the stored fixed the problem for my scenario and things started working as expected - perhaps you can try that.
Rsa Cryptography in c#. i have encrypted an xml file and saved it .after that i transferred this file to another pc .the main problem is that it couldn,t decrypt.i dont know why??
when iam decrypting on the same machine the xml file is decrypted..
public static byte[] decryptFile(XmlDocument Doc, RSA rsaKey, string KeyName)
{
Doc = new XmlDocument();
Doc.PreserveWhitespace = true;
Doc.Load(#"MLPACK1.xml");
EncryptedXml encXml = new EncryptedXml(Doc);
encXml.AddKeyNameMapping(KeyName, rsaKey);
encXml.DecryptDocument();
string contentOfDocument = Doc.OuterXml;
byte[] buffer = StrToByteArray(contentOfDocument);
return buffer;
}
You have used ProtectedData.Protect(....) method.
Third parameter of the method is scope(enum) type of System.Security.Cryptography.DataProtectionScope.
So seems you have set DataProtectionScope.LocalMachine (or even may be DataProtectionScope.CurrentUser) for DPS and passed it to Protect method.
Like this
DataProtectionScope DPS = DataProtectionScope.LocalMachine
ProtectedData.Protect(bytes, null, DPS);
So this can be the source of the problem.
Is your key the same on both machines? You should take the public key from the machine where this will be decrypted and use this to encrypt it on the other machine.