I want to create .pem file for the public key generated by this method
public static Tuple<string, string> CreateKeyPair()
{
CspParameters cspParams =
new CspParameters {
ProviderType = 1 /* PROV_RSA_FULL */
};
RSACryptoServiceProvider rsaProvider =
new RSACryptoServiceProvider(1024, cspParams);
string publicKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(false));
string privateKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(true));
return new Tuple<string, string>(privateKey, publicKey);
}
Because I was generating this key for mobile application and they can not read it, they requested .pem file instead of public key as string
Please advice,
Recently I need to save PublicKey and PrivateKey generated in my C# application to file, and works with it later. I use for this purpose such library as CSharp-easy-RSA-PEM.
It is very simple and quick solution, so I will recommend this library to other guys.
I use following code to get PublicKey as string (and save it to pem file in format Base64):
string publicKeyStr = Crypto.ExportPublicKeyToX509PEM(_cryptoServiceProvider);
it returns something like this:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxnBvS8cdsnAev2sRDRYWxznm1
QxZzaypfNXLvK7CDGk8TR7K+Pzsa+tpJfoyN/Z4B6xdlpsERo2Cu6AzolvrDLx5w
ZoI0kgdfaBMbUkdOB1m97zFYjKWoPeTskFzWZ3GHcQ3EXT0NJXXFXAskY45vEpbc
5qFgEhcPy3BMqHRibwIDAQAB
-----END PUBLIC KEY-----
And I use following code to get PrivateKey as string:
string privateKeyStr = Crypto.ExportPrivateKeyToRSAPEM(_cryptoServiceProvider);
it returns something like this:
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCxnBvS8cdsnAev2sRDRYWxznm1QxZzaypfNXLvK7CDGk8TR7K+
Pzsa+tpJfoyN/Z4B6xdlpsERo2Cu6AzolvrDLx5wZoI0kgdfaBMbUkdOB1m97zFY
jKWoPeTskFzWZ3GHcQ3EXT0NJXXFXAskY45vEpbc5qFgEhcPy3BMqHRibwIDAQAB
AoGAAdwpqm7fxh0S3jOYpJULeQ45gL11dGX7Pp4CWHYzq1vQ14SDtFxYfnLWwGLz
499zvSoSHP1pvjPgz6lxy9Rw8dUxCgvh8VQydMQzaug2XD1tkmtcSWInwFKBAfQ7
rceleyD0aK8JHJiuzM1p+yIJ/ImGK0Zk2U/svqrdJrNR4EkCQQDo3d5iWcjd3OLD
38k1GALEuN17KNpJqLvJcIEJl0pcHtOiNnyy2MR/XUghDpuxwhrhudB/TvX4tuI0
MUeVo5fjAkEAw0D6m9jkwE5uuEYN/l/84rbQ79p2I7r5Sk6zbMyBOvgl6CDlJyxY
434DDm6XW7c55ALrnlratEW5HPiPxuHZBQJANnE4vtGy7nvn4Fd/mRQmAYwe695f
On1iefP9lxpx3huu6uvGN6IKPqS2alQZ/nMdCc0Be+IgC6fmNsGWtNtsdQJAJvB4
ikgxJqD9t8ZQ2CAwgM5Q0OTSlsGdIdKcOeB3DVmbxbV5vdw8RfJFjcVEbkgWRYDH
mKcp4rXc+wgfNFyqOQJATZ1I5ER8AZAn5JMMH9zK+6oFvhLUgKyWO18W+dbcFrBd
AzlTB+HHYEIyTmaDtXWAwgBvJNIHk4BbM1meCH4QnA==
-----END RSA PRIVATE KEY-----
Then you can use
RSACryptoServiceProvider publicX509key = Crypto.DecodeX509PublicKey(publicKeyStr);
RSACryptoServiceProvider privateRSAkey = Crypto.DecodeRsaPrivateKey(privateKeyStr);
to restore saved keys back to RSACryptoServiceProvider.
So, if someone need to resolve similar issue, you can just download this library, go to Solution Explorer -> (Right click on your project) -> Add -> Reference -> Overview in your Visual Studio to add this library in your project, and add using CSharp_easy_RSA_PEM; where you need it :)
First off, a so-called .pem file is not really a fixed specification or format. Several different kinds of distinct file formats are generally described as "PEM" files. When the SSLeay (now OpenSSL) project needed to produce a base64 encoded output file containing key information they borrowed formatting concepts from the old Privacy-Enhanced Mail RFCs 1421-1424 and they added the extension .pem to the end of these files. But such a file may contain public keys, private keys, certificate requests, certificates, certificate lists, and so on. Each is different. So if all you're told is to produce a .pem file you're going to have to guess what's really needed.
The easiest way to write such files is to use the Bouncycastle C# library. The package Org.BouncyCastle.OpenSsl contains a number of utilities including a PemWriter class that should help you.
Related
I have an RSA private key loaded in an RSACryptoServiceProvider object. I need to export this to a .pvk file for use with SQL Server.
Is there a way to do this from within c#? I see it's possible using openssl... https://stackoverflow.com/a/51207929/5924962
This is the only documentation I could find on the pvk file format: https://web.archive.org/web/20141117214716/http://www.drh-consultancy.demon.co.uk/pvk.html
Mono project has an open source implementation of the PVK format,
https://github.com/mono/mono/blob/master/mcs/class/Mono.Security/Mono.Security.Authenticode/PrivateKey.cs
Note the Mono.Security NuGet package is not official.
If you look at the output of RSACryptoServiceProvider.ExportCspBlob you'll see that it starts with the same sequence of bytes as offset 24 of an unencrypted PVK file. So a PVK file is just the CSP blob with a header:
using (var output = new BinaryWriter(File.Create("rsa.pvk")))
{
output.Write(0xB0B5F11Eu); // PVK magic number
output.Write(0u);
output.Write(1u); // KEYTYPE_KEYX for RSA
output.Write(0u); // not encrypted
output.Write(0u); // encryption salt length
var cspBlob = rsaCSP.ExportCspBlob(true);
output.Write((uint)cspBlob.Length);
output.Write(cspBlob);
}
I've verified that OpenSSL will read this
openssl rsa -in rsa.pvk -inform PVK
and will generate the same PEM private key export as the code in this answer that generates the PEM private key directly from the RSACryptoServiceProvider.
I have DER encoded RSA keypair created in Crypto++, as well as cipher. They are Base64Encoded string. I first decode the data from Base64 to byte array, but I am not sure how to load them into RSACryptoServiceProvider.
static void Main()
{
string pbkeystr = "mypublickey";
string pvkeystr = "myprivatekey";
string cipherstr = "mycipher";
byte[] pbkey = Convert.FromBase64String(pbkeystr);
byte[] pvkey = Convert.FromBase64String(pvkeystr);
byte[] cipher = Convert.FromBase64String(cipherstr);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//Set keys here..
//Decrypt the cipher using private key
rsa.Decrypt(pvkey, false);
}
There are no functions to set keys. The only thing I found was ImportParameters method, which takes RSAParameters class which consists of p, q, n, modulus, exponent etc. I don't have access to these.
Is there any way I can load the keys as string? How can I load the key into RSACryptoServiceProvider?
Is there any way I can load the keys as string? How can I load the key into RSACryptoServiceProvider?
From your other Crypto++ question, How to load Base64 RSA keys in Crypto++, it looks like you have only the public and private keys because you used DEREncode and BERDecode. That is, you have the RSA parameters, and not the subject public key info and the private key info. Your keys lack the OID identifiers and version numbers. Things are fine that way.
From Cryptographic Interoperability: Keys on the Code Project, you will need a C# class that parses the ASN.1/DER after you Base64 decode it. The CodeProject article provides a C# class called AsnKeyParser to read the ASN.1/DER and returns a RSAParameters to load into a CSP.
The code for the AsnKeyParser class is about 800 lines, and there are five other supporting files to make it all happen, so its not really appropriate to place it here. You should download it yourself. The file of interest is called CSInteropKeys.zip.
Once you wire-in the AsnKeyParser class, it will be as simple as the following for a RSA Public key. The private key will be similar, and the code is given on the CodeProject site.
// Your ASN.1/DER parser class
AsnKeyParser keyParser = new AsnKeyParser("rsa-public.der");
RSAParameters publicKey = keyParser.ParseRSAPublicKey();
// .Net class
CspParameters csp = new CspParameters;
csp.KeyContainerName = "RSA Test (OK to Delete)";
csp.ProviderType = PROV_RSA_FULL; // 1
csp.KeyNumber = AT_KEYEXCHANGE; // 1
// .Net class
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
rsa.PersistKeyInCsp = false;
rsa.ImportParameters(publicKey);
Linking to files on another site is frowned upon, but I don't know how to provide the information otherwise. There's too much source code involved to place in an answer.
For completeness, .Net does not make interop easy. They do not accept ASN.1/DER or PEM. Rather, .Net accepts some XML representation of the keys. I believe you can find it in RFC 3275, XML-Signature Syntax and Processing. Microsoft does not state that for you. I kind of pieced it together when I wrote the Code Project article.
Maybe we should add a class to Crypto++ to regurgitate XML in addition to ASN.1/DER and PEM.
I'm trying to re-use the key pair I generated for creating a PKCS10 Certificate Signing request, but I cannot figure out what the format of this private key is.
To create the key, I'm using the CERTENROLLLib CX509PrivateKey class.
I've set the Private Key ProviderType to XCV_PROV_RSA_FULL, and when I export it (trying to figure out what format it is) I use
Export("PRIVATEBLOB", EncodingType.XCN_CRYPT_STRING_BASE64)
When I export it, the private key always starts with "BwIAAACkAABSU0E"
Does anyone know what format this is? I thought ANS.1 DER Encoding always started with "MII" or someting like that.
I think I answered my own question:
The command
Export("PRIVATEBLOB", EncodingType.XCN_CRYPT_STRING_BASE64)
exports the private key as a BASE64 encoded CSP blob. In order to import is using the C# RSA libraries I had to use the following:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] CryptoKey = Convert.FromBase64String(base64CspBlob);
rsa.ImportCspBlob(CryptoKey);
That did it!
We use C# code we build X509Certificate2 with .p12 file, in the constructor we insert the path to certificate, certificate's password. We also marked it as Exportable as shown below:
X509Certificate2 x509Certificate2 = new X509Certificate2
("...\\MyCerificate.p12", "P#ssw0rd", X509KeyStorageFlags.Exportable);
we get the private key as AsymmetricAlgorithm format by the following:
x509Certificate2.PrivateKey
Now, we want to get the private key from the certificate as Base64 format - but we don't have any idea how to do it, and its so important for us.
The important question is why base64 ?
If this is for your own application then you can keep the private key as an XML string (much easier :-).
string xml = x509Certificate2.PrivateKey.ToXmlString (true);
If you want base64 (again just for your application) you can export the key (RSAParameters) then concat every byte[] and turn the merged output to a base64 string.
But if you want to interop with other applications that requires a base64 private key then you need to know the format (inside the base64 string). E.g. in many case private keys are PEM encoded (which is base64 with a special header/footer, see an example for X509Certificate).
If that what's you're looking for then you'll need to encode the private key within a PKCS#8 structure first, then turn in into base64 and add the header/footer. You can find some helpful code to do so inside Mono.Security.dll (MIT.X11 licensed code from the Mono project).
You can simply use the PrivateKey property of X509Certificate2.
The actual returned private key implementation depends on the algorithm used in the certificate - usually this is RSA:
rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
Afterwards you should be able to get the RSA key information from it's ExportParameters property.
You can do that with OpenSSL Library for .NET:
using DidiSoft.OpenSsl;
...
X509Certificate2 x509Certificate2 = new X509Certificate2
("...\\MyCerificate.p12", "P#ssw0rd", X509KeyStorageFlags.Exportable);
PrivateKey privKey = PrivateKey.Load(x509Certificate2.PrivateKey);
bool withNewLines = true;
string base64PrivateKey = privKey.ToBase64String(withNewLines);
If your only problem is to get the private key Base64 encoded, you can simply do like this:
var privateKey = x509Certificate2.PrivateKey;
var encoding = new System.Text.ASCIIEncoding();
var base64String = Convert.ToBase64String(encoding.GetBytes(privateKey.ToString()));
I'm working on project that involves reading public key data used to sign Android APKs. I am able to successfully extract the signatures as public keys. When I look inside the binary pubkey files produced by this, I see some plain-text such as a name and a city.
How can I safely extract this name/city information embedded inside the public key using PHP (or even Java or C#)? And hopefully do it in such a way that I know exactly what these fields are (i.e. not blindly grabbing text, but knowing which string is a city and which is a name)
For clarification: I don't have the private key or a certificate file. I'm currently not interested in signing or encrypting anything, I would just like to extract the plaintext inside the pubkey without using kludgy approaches like regex.
Update: Here's a sample (base64-encoded) public key from one of my APKs
MIICBzCCAXCgAwIBAgIES6KlazANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzELMAkGA1UECBMCUkkxFTATBgNVBAcTDE5hcnJhZ2Fuc2V0dDEVMBMGA1UEAxMMQ29saW4gTydEZWxsMB4XDTEwMDMxODIyMTI1OVoXDTQ1MDMwOTIyMTI1OVowSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlJJMRUwEwYDVQQHEwxOYXJyYWdhbnNldHQxFTATBgNVBAMTDENvbGluIE8nRGVsbDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmPetcBW+ITURXY0LsI2ZfgM3R7K2kwicgpd0W+BYAXQBh76SXyN9MYvtfnUY3SNz37FW/lDQgAO3pbhEFqGwfADh2ctXlYmlE9DtcRQw0ojGVPIDlWBX+9IUxyL/89CPaN84R/1lvdosco4V0BqQYR300S9ZwmwFA2Vh9hSUZmsCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBezKu4G11Z68NTPIBro8xsnbkdYxObzW7BsSr6t9MS5x6EQVs75R/nnKrsMcQ+9ImdT940jhQgZT3ZrYla5VhdbelxnLhBVbJfBdipV3Hv2bG7MnXzFqHYwQqYp+UrP8zWm1YHQf5I/P9VBjlkgwFyNKr0TxP4t/qS08oGX2wvZg==
The string you put in is a base 64 encoded x509 certificate, not simply a public key.
You'll need to parse the Distinguished Name fields to get the desired info.
Here's a C# example:
using System;
using System.Security.Cryptography.X509Certificates;
namespace Sample
{
class Program
{
static void Main(string[] args)
{
string base64EncodedX509 =
"MIICBzCCAXCgAwIBAgIES6KlazANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQGEwJVUzELMAkGA1UECBMCUkkxFTATBgNVBAcTDE5hcnJhZ2Fuc2V0dDEVMBMGA1UEAxMMQ29saW4gTydEZWxsMB4XDTEwMDMxODIyMTI1OVoXDTQ1MDMwOTIyMTI1OVowSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlJJMRUwEwYDVQQHEwxOYXJyYWdhbnNldHQxFTATBgNVBAMTDENvbGluIE8nRGVsbDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmPetcBW+ITURXY0LsI2ZfgM3R7K2kwicgpd0W+BYAXQBh76SXyN9MYvtfnUY3SNz37FW/lDQgAO3pbhEFqGwfADh2ctXlYmlE9DtcRQw0ojGVPIDlWBX+9IUxyL/89CPaN84R/1lvdosco4V0BqQYR300S9ZwmwFA2Vh9hSUZmsCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBezKu4G11Z68NTPIBro8xsnbkdYxObzW7BsSr6t9MS5x6EQVs75R/nnKrsMcQ+9ImdT940jhQgZT3ZrYla5VhdbelxnLhBVbJfBdipV3Hv2bG7MnXzFqHYwQqYp+UrP8zWm1YHQf5I/P9VBjlkgwFyNKr0TxP4t/qS08oGX2wvZg==";
var rawBytes = Convert.FromBase64String(base64EncodedX509);
X509Certificate cert = new X509Certificate(rawBytes);
// Parse the distinguished name to get your desired fields
Console.WriteLine(cert.Subject); // writes CN=Colin O'Dell, L=Narragansett, S=RI, C=US
Console.WriteLine(cert.Issuer); // writes CN=Colin O'Dell, L=Narragansett, S=RI, C=US
}
}
}
The "binary pubkey files produced by this" is an X.509 certificate.
Just about any platform has support for reading X.509 certificates, and creating a structure from them, from which you can reliably extract the "subject name," and often extended information that includes an email address or host name.
For example, if you have OpenSSL installed, use the following command:
openssl x509 -text -noout -inform der -in <yourfilehere>
You can extract specific fields with additional options. For example, adding -subject yields:
subject= /C=US/ST=RI/L=Narragansett/CN=Colin O'Dell
In php, I am not sure but maybe this function could be your friend. There is a whole section of ssl related functions that could come in handy if you are playing with certificates.