I've been digging into the .NET System.Security.Cryptography
namespace, specifically the RSACryptoServiceProvider
class. It has two methods using in signing data, SignHash()
and VerifyHash()
and I have a few questions regarding the usage of this class and methods.
1) When instantiated, RSACryptoServiceProvider
creates a keypair, like so:
// 1 = RSA compatible. http://msdn.microsoft.com/en-us/library/1dh4wac4.aspx
CspParameters cspParams = new CspParameters( 1 );
cspParams.Flags = CspProviderFlags.NoFlags;
rsa = new RSACryptoServiceProvider( 2048, cspParams ); // rsa is a class member
rsa.PersistKeyInCsp = false;
Then the private and public keys can be saved to disk using the following code:
public void WriteKeys( FileInfo file, bool includePrivateKey )
{
using( FileStream fs = new FileStream( file.FullName, FileMode.Create, FileAccess.Write, FileShare.None ) ) {
string xml = rsa.ToXmlString( includePrivateKey );
byte[] b = Encoding.UTF8.GetBytes( xml );
string base64 = Convert.ToBase64String( b );
b = Encoding.UTF8.GetBytes( base64 );
fs.Write( b, 0, b.Length );
fs.Close();
}
}
Q: Is there anything that can prevent the subsequent loading of the public key on a client computer at a later time (exempting file access rights etc.), using code such as this:
private void ReadKeyFromFile( FileInfo keyFile )
{
byte[] b = File.ReadAllBytes( keyFile.FullName );
string base64 = Encoding.UTF8.GetString( b );
byte[] b = Convert.FromBase64String( base64 );
string xml = Encoding.UTF8.GetString( b );
rsa.FromXmlString( xml );
}
Q: If specifying Csp flag CspProviderFlags.UseArchivableKey instead of CspProviderFlags.None, the loading of the file fails (at rsa.FromXmlString()) with a CryptographicException "Invalid flags specified.", why is that? The 'Achivable' sound just like what is I want, no?
Q: Is there anyway of creating a RSACryptoServiceProvider
without also creating a new keypair (as I will load an existing key shortly after) ?
2) According to MSDN, the two methods SignHash
and VerifyHash
can be used to sign a hash of some arbitrary data, using the private key, then be verified using the public key to ensure the validity of the data.
Q: What if I distribute the public key with my application (embedded resource or base64 encoded string etc.) to validate a license key that has been hashed and signed using my private key - can I be certain that no one else can generate license keys that are considered valid by the application (assuming I keep the private key private)? After all, that is what the public/private keys are for, are they not?
Example signing code:
using( SHA1 sha = SHA1.Create() ) {
byte[] hash = sha.ComputeHash( data );
byte[] signature = rsa.SignHash( hash, CryptoConfig.MapNameToOID( "SHA1" ) );
}
Thanks in advance.