Reputation: 1908
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
Upvotes: 1
Views: 1548
Reputation: 1908
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
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!
Upvotes: 4
Reputation: 5650
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.
Upvotes: 3