I encrypt and decrypt data using the RSACryptoServiceProvider in C#, and when I generate a new keypair, I return the private key to the caller of the method and then save the public key to a homemade PKI (just a dictionary with the keyBlob and a unique identifier).
My problem is this: since I need to store the public key, I don’t want to accidentally store a private key in the PKI. However, since I also need to actually write the private key to a file, I am working with byte arrays exported with the ExportCspBlob method.
My question:
How do I ensure, by checking the byte[] that I parse into my StoreKey method, that it is in fact a public key and it does not contain private key information?
For clarification, here is the relevant code:
public static bool StoreKey(byte[] publicKeyParameters, string uniqueIdentifier)
{
bool success = false;
if (!keyCollection.ContainsKey(uniqueIdentifier))
{
if (!keyCollection.ContainsValue(publicKeyParameters))
{
keyCollection.Add(uniqueIdentifier, publicKeyParameters);
success = true;
}
}
return success;
}
And the GenerateKeys method:
public static byte[] GenerateKeys(string uniqueIdentifier)
{
byte[] privateKeyBlob;
using (var rsa = new RSACryptoServiceProvider(4096))
{
try
{
byte[] publicKey = rsa.ExportCspBlob(false);
privateKeyBlob = rsa.ExportCspBlob(true);
PublicKeyInfrastructure.StoreKey(publicKey, uniqueIdentifier);
}
finally
{
//// Clear the RSA key container, deleting generated keys.
rsa.PersistKeyInCsp = false;
}
}
return privateKeyBlob;
}
Since I am working on two different classes, I would like to abstain from initializing a RSACryptoServiceProvider in my PKI, just to import the key and check for it. Is this possible?
According to MSDN, the output of
ExportCspBlobis compatible with CAPI, and according to the documentation for the CAPI BLOBHEADER, the first byte represents the key type. Specifically, if the first byte is 0x07, it’s a private key, whereas 0x06 is a public key.