I have a file testpublic.snk which holds a public key. I have created it with sn -p c:\test.snk c:\testpublic.snk.
Now, how can I convert testpublic.snk to a string like
<RSAKeyValue><Modulus>z140GwiEJvuGOVqMQUxnojILR8rn2SFOViigoloku59H5eqzqca3Hdyl/jc+Acdb5ktzhBOOyGFElE0/Btlvw9cXVVW8zcT0MBOCaq25D1rSVYLGGM6nXzBrl1XsrBEadZbCgkcF5rw8GaYcYakijaltP1/hvxhbMOARM9VCQ50=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
Thanks for your help.
Simply re-use the (MIT.X11 licensed) code from Mono.Security StrongName class, available in github, then call ToXmlString on it's RSA property. Something like:
Console.WriteLine (new StrongName (data).RSA.ToXmlString (false));
Where data is a byte[] containing the content of your snk file. Also you can use true if you want the private key in your XML (it will work if it was available fom your snk file).
Related
the following uses the System.Security.Cryptography namespace from c#
and implements the unprotect method from the ProtectedData class
byte[] output = ProtectedData.Unprotect(input, null, DataProtectionScope.LocalMachine);
I'm trying to access my pc's HKEY_LOCALMACHINE registry with python because theres a key somewhere in it that i need (to read), in order to decrypt a file.
I read the docs but I'm still just not sure what method I should use for that purpose
aReg = winreg.ConnectRegistry(None, HKEY_LOCAL_MACHINE)
I'm not quite sure what comes next so any help would be appreciated.
Turns out I needed this: https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectdata
import win32crypt
#open binary file in readmode
filecontents = fileObject.read()
unecryptedFileContents = win32crypt.CryptUnprotectData(filecontents)
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.
I want to be able to detect when a critical configuration file has been changed.
I've used Configuration Section Designer to create a simple configuration file but now I cannot find an easy way to encrypt the result or add a value to it to check that it has been changed.
I want to be able to either prevent unauthorized users from changing the config file or at least know if the file has been changed.
If authorized users can change the configuration file, a high-level approach would be use an asymmetric key to sign the file. Only authorized individuals with access to the private key would be able to generate the hash, but the application could verify the legitimacy of the hash (and thus the file itself) with only the public key. One quick implementation follows.
This implementation requires generation of three files:
The configuration file you want to sign.
A file accessible to the application that contains the configuration file hash.
A private configuration file that contains the private key parameters.
Files (1) and (2) are accessed by the application. File (3) is confidential, restricted to authorized users.
The basic mechanism is this:
Generate an RSA key pair, and save the public and private key information. Private key information saved into File (3), and public key information is incorporated into the application. This step is performed only once.
Whenever a configuration file is changed, file (3) is used to sign the file's SHA1 hash. The hash is saved into file (2).
Whenever the program loads the configuration file, it generates the configuration file hash, and uses the public key to verify the signature. If the signatures match, it continues; if they do not match, it throws an exception.
1. Generating the RSA key pair
The RSA key data can be generated as XML:
(use System.Security.Cryptography)
var csp = new RSACryptoServiceProvider();
string publicXml = csp.ToXmlString(false);
string privateXml = csp.ToXmlString(true);
This produces XML data in the following format.
publicXML:
<RSAKeyValue>
<Modulus>oQKZR9hHrqm1tauCFYpbFlwyRNIHeyc2HCX+5htF/oc1x8Nk8i+itTzwRlgQG1cICO6lX
A+J9/OO2x2b9JILtk2tQow10xJdIsuiBeRwe7wJRdS8+l21F/JPY0eu/xiKQy
ukzEWLjIxGX7UXb9e4ltIxyRUUhk5G/ia1trcxfBc=
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
privateXml:
<RSAKeyValue><Modulus>oQKZR9hHrqm1tauCFYpbFlwyRNIHeyc2HCX+5htF/oc1x8Nk8
i+itTzwRlgQG1cICO6lXA+J9/OO2x2b9JILtk2tQow10xJdIsuiBeRwe7wJRdS8+l21F/JPY0eu/xiKQ
yukzEWLjIxGX7UXb9e4ltIxyRUUhk5G/ia1trcxfBc=</Modulus><Exponent>AQAB</Exponent>
<P>zpFEWa7ave3wHL7pw7pSG0KXDPRwhCzU1Z5/fLoqSrPQzbkRqU+cwDVO/6IId3HdeXE09kVIu9/HBId
vupnY9w==</P><Q>x4pmqkmB7i8g9d3G6RSeZWYde8VOS5/OHUKgM6VrlQhgyrATpxGWAzJAe5eNO2BU
axNO8fZPe+lUSCJgY6TN4Q==</Q><DP>jaNL05ayhDLHRl6dmUiDjg+N1SMyl17KHSON1O8tmoVLchQp
CQf+ukiTP3NSDNy1eNTn9MkzAyeAphlbwf5Fpw==</DP><DQ>HhmUjw9zmBhn4m7H+JTxp94ViHwk6Wd
70hIg1GmZpuuSnkCdVlBizqyf6YTc+x323ggVmo5LQyfZXOBCpgVQQQ==</DQ><InverseQ>iO0CKRGB
2ULS6is/SwonqJw5fBsI9HTzx8rmKGA189dwlLGJSJuQo8uWmrLYhuo22BAqd0lMqxlKCHv6leeGPw==
</InverseQ><D>RSLliJkRJqnO0cRkZjVzqWVLXIvHFJWgwXN7QXlik8mhSTbYqLnVpvcUwU/dErBLTf
KTZLVza9nUdLgBGIKBrkbIqIWixq1fQ3zsEkyB/FQxwhIerTrhHyPzR+i3+5mduqQ7EBTj64u6STUf0y
TXHW2FYlfAinNz+K3iQFFarEE=</D></RSAKeyValue>
The private key strings should be saved (through any mechanism) to File (3) (private key). The application that is confirming the file's integrity will need the public key string (discussed later in step 3).
2. Signing the configuration file
To sign the configuration file, you will need the Private key Xml string generated in step (1).
private byte[] GetFileSha1Hash(string file)
{
using (var fs = new FileStream(
file, FileMode.Open))
{
return new SHA1CryptoServiceProvider().ComputeHash(fs);
}
}
static string GetConfigurationFileSignature(string configfile, string privateXml)
{
var p = new RSACryptoServiceProvider();
p.FromXmlString(privateXml);
byte[] signature = p.SignHash(GetFileSha1Hash(configfile),
CryptoConfig.MapNameToOID("SHA1"));
return Convert.ToBase64String(signature)
}
Calling GetConfigurationFileSignature will return a base64-encoded string. Save this string into File (2), where it will be referenced by the application.
3. Check the configuration file integrity
When the configuration file is loaded, the application should check the configuration file signature against the digital signature. The public key should be stored within the application rather than in a configuration file -- otherwise, the attacker can simply overwrite the public key in the configuration file with one for which he/she knows the corresponding private key pair.
static bool VerifyConfigurationFileSignature(string fileName, string publicXml, string signature)
{
var p = new RSACryptoServiceProvider();
p.FromXmlString(publicXml);
return p.VerifyHash(
GetFileSha1Hash(fileName),
CryptoConfig.MapNameToOID("SHA1"),
Convert.FromBase64String(signature));
}
(Note: you can use AppDomain.CurrentDomain.SetupInformation.ConfigurationFile to get the path of the current configuration file.)
When the application loads, it can make a call to VerifyConfigurationFileSignature with the path to the configuration file, public key XML data, and known signature. If this method returns false, it indicates the file has been tampered with; if it returns true, it is evidence that the file is legitimate.
Final Notes
The cryptography only ensures that the generated digital signature was generated with the private key. An attacker may still be able to override the application's verification logic to read malicious configuration data.
Any change to the configuration file (including adding comments, whitespace, etc.) will result in the hash becoming invalid. A more specialized implementation of GetFileSha1Hash might search for specific key/value pairs in the XML and sign only that data, allowing other modifications to the configuration file.
Including the hash itself in the XML file is not possible with the above implementation of GetFileSha1Hash, since updating the hash itself in the file would render the prior hash invalid. A specialized implementation of GetFileSha1Hash can ignore the generated hash value in generating the configuration file hash, thus preventing the need for separate configuration files.
A common approach to determining whether something has changes is to take a 'hash', for example, you could take an MD5 hash of the configuration, or part of it, then check against this has each time it is loaded in order to determine if it has been changed.
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.
I want to create 2 really simple dlls:
1) that will sign an xml document
2) that will check that the xml document hasnt been modified.
I tried using the RSACryptoServiceProvider and a key container. But when I move to a different machine this does not work as the key is being stored in the machine.
I want to store the key in the dlls im creating (I know this is not reccomended) but I just cannot work out how to write some code to simply sign an xml document and then verify that it hasn't been changed.
So do I need to use symmetric key to do what I want is this possible?
Pete
You already mention the problems with storing the private key in the dll, so I won't repeat that.
Do this:
On your own machine run this code:
var key = new RSACryptoServiceProvider(2048);
string publicKey = key.ToXmlString(false);
string privateKey = key.ToXmlString(true);
Console.WriteLine(publicKey);
Console.WriteLine(privateKey);
this outputs two (long) lines. Copy those into your code:
Sign:
var privateKey = new RSACryptoServiceProvider();
privateKey.FromXmlString(/* insert the private-key XML string here */ );
privateKey.SignData(/*...*/);
Verify:
var publicKey = new RSACryptoServiceProvider();
publicKey.FromXmlString(/* insert the public-key XML string here */ );
publicKey.VerifyData(/*...*/);
If it is just about to verify that your xml document hasn't been modified a simple MD5 checksum (or any other good hashing algorithm) would be easier to implement and is what you need. It would be also verifyable on different machines.