Reputation: 428
I am currently looking into implementing asymmetric encryption to be able to for example in one form user can encrypt the data. After the encryption, the user closes the form and opens the second form where the user can then see the decrypted message. So, I created a class where two forms will be using the encryption class and it can be found below the question.
So, I managed to pinpoint the reason which is that the private key is different in decryption than when I implement the encryption. As I keep on getting error around the following line byte[] decryptedBytes = rsa.Decrypt(encrypteddata, false);
with an error saying the parameter is incorrect. Will it be possible to find out the mistake in the code that would lead to this problem? Also, Am I approaching this in an incorrect way?
private RSACryptoServiceProvider rsa;
private RSAParameters _privateKey;
private RSAParameters _publicKey;
private static bool keysGenerated;
public Encryption()
{
rsa = new RSACryptoServiceProvider();
}
public bool RegistryKeyVerification(string RegistyKeyName, string RegistryKeyValueName)
{
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistyKeyName);
if (key == null)
{
keysGenerated = false;
}
else
{
keysGenerated = true;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return keysGenerated;
}
public void EncryptionKeysGeneration(string RegistyKeyName, string RegistryKeyValueName)
{
bool regkeyvalver = RegistryKeyVerification(RegistyKeyName, RegistryKeyValueName);
if (regkeyvalver == true)
{
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistyKeyName);
object keyvalue = key.GetValue(RegistryKeyValueName);
if (keyvalue == null || keyvalue is byte[])
{
GenerateandSaveEncryptionKeys(RegistyKeyName, RegistryKeyValueName);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
public void GenerateandSaveEncryptionKeys(string RegistyKeyName, string RegistryKeyValueName)
{
try
{
_publicKey = rsa.ExportParameters(false);
_privateKey = rsa.ExportParameters(true);
RSAParameters privatekey = _privateKey;
// Saving the private key into the registry:
SavePrivateKeytoRegistry(privatekey, RegistyKeyName, RegistryKeyValueName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public string Encrypt(string data, string RegistyKeyName, string RegistryKeyValueName)
{
try
{
RSAParameters publickey = _publicKey;
string privateKeyXmlString = LoadPrivateKeyfromRegistry(RegistyKeyName, RegistryKeyValueName);
RSAParameters privatekey = DecryptPrivateKey(privateKeyXmlString);
// Assign the decrypted private key to the RSA instance
rsa.ImportParameters(privatekey);
byte[] databytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedData = rsa.Encrypt(databytes, false);
return Convert.ToBase64String(encryptedData);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
throw new InvalidOperationException("Data was not able to be encrypted");
}
public string Decrypt(string data, string RegistyKeyName, string RegistryKeyValueName)
{
try
{
string privateKeyXmlString = LoadPrivateKeyfromRegistry(RegistyKeyName, RegistryKeyValueName);
RSAParameters privatekey = DecryptPrivateKey(privateKeyXmlString);
var encrypteddata = Convert.FromBase64String(data);
rsa.ImportParameters(privatekey);
byte[] decryptedBytes = rsa.Decrypt(encrypteddata, false);
string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
return decryptedText;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
throw new InvalidOperationException("Data was not able to be decrypted");
}
public void SavePrivateKeytoRegistry(RSAParameters privatekey, string RegistyKeyName, string RegistryKeyValueName)
{
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistyKeyName, true);
string privateKeyXml = PrivateKeyToXmlString(privatekey);
byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKeyXml);
byte[] encryptedPrivateKeyBytes = ProtectedData.Protect(privateKeyBytes, null, DataProtectionScope.CurrentUser);
key.SetValue(RegistryKeyValueName, encryptedPrivateKeyBytes, RegistryValueKind.Binary);
key.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private string PrivateKeyToXmlString(RSAParameters privateKey)
{
rsa.ImportParameters(privateKey);
return rsa.ToXmlString(true);
}
public string LoadPrivateKeyfromRegistry(string RegistyKeyName, string RegistryKeyValueName)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistyKeyName, true);
if (key != null)
{
RegistryValueKind valueKind = key.GetValueKind(RegistryKeyValueName);
if (valueKind == RegistryValueKind.Binary)
{
byte[] encryptedPrivateKeyBytes = (byte[])key.GetValue(RegistryKeyValueName);
byte[] decryptedPrivateKeyBytes = ProtectedData.Unprotect(encryptedPrivateKeyBytes, null, DataProtectionScope.CurrentUser);
string privateKeyXmlString = Encoding.UTF8.GetString(decryptedPrivateKeyBytes);
return privateKeyXmlString;
}
else if (valueKind == RegistryValueKind.String)
{
string privateKeyString = (string)key.GetValue(RegistryKeyValueName);
byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKeyString);
byte[] decryptedPrivateKeyBytes = ProtectedData.Unprotect(privateKeyBytes, null, DataProtectionScope.CurrentUser);
string privateKeyXmlString = Encoding.UTF8.GetString(decryptedPrivateKeyBytes);
return privateKeyXmlString;
}
}
key.Close();
throw new InvalidOperationException("Invalid registry value kind.");
}
public RSAParameters DecryptPrivateKey(string privateKeyXmlString)
{
var privateKeyParams = new RSAParameters();
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(privateKeyXmlString);
if (xmlDoc.DocumentElement != null && xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
{
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
switch (node.Name)
{
case "Modulus":
privateKeyParams.Modulus = Convert.FromBase64String(node.InnerText);
break;
case "Exponent":
privateKeyParams.Exponent = Convert.FromBase64String(node.InnerText);
break;
case "P":
privateKeyParams.P = Convert.FromBase64String(node.InnerText);
break;
case "Q":
privateKeyParams.Q = Convert.FromBase64String(node.InnerText);
break;
case "DP":
privateKeyParams.DP = Convert.FromBase64String(node.InnerText);
break;
case "DQ":
privateKeyParams.DQ = Convert.FromBase64String(node.InnerText);
break;
case "InverseQ":
privateKeyParams.InverseQ = Convert.FromBase64String(node.InnerText);
break;
case "D":
privateKeyParams.D = Convert.FromBase64String(node.InnerText);
break;
}
}
}
return privateKeyParams;
}
}
Upvotes: 0
Views: 72