Мы пытаемся сделать это для нашего приложения C # (.net 3.5) на наших машинах с XP SP2 (Win7 позже).
В нашем установщике (создан VS2008) мы шифруем наше соединениестрока с ключом AES
и iv, а затем создание RSA key-pair
и сохранение их в MachineKeyStore
.Установщик будет использовать RSA public key
для шифрования ключа AES
и iv, а также сохранять зашифрованный ключ и iv с зашифрованной строкой соединения.
После установки наше приложение будет читать зашифрованную строку соединения сзашифрованный ключ AES и iv обратно, и используйте RSA private key
(из MachineKeyStore
) для расшифровки ключа AES
и iv, а затем расшифруйте строку соединения с помощью ключа AES
и iv.
Установщик и наше приложение совместно используют constant string
для container name
из MachineKeyStore
.
Я знаю, где хранится пара ключей, так что я могу отслеживать ее, чтобы увидеть, была ли удалена пара ключей,обновлен или создан.
Я провел несколько тестов и обнаружил некоторые интересные (неожиданные) вещи, но не знаю, почему это так.Моя учетная запись пользователя - учетная запись администратора.
- Программа установки может удалить сохраненную
key-pair
, созданную нашим приложением, и сразу же создать новую с тем же именем контейнера; - Программа установки можетОбновление
key-pair
, созданное нашим приложением (не удаляйте и не создавайте заново, я думаю, оно перезаписывается, но этого не должно происходить в соответствии с документацией): CryptographicException: Keyset does not exist.
исключение произойдет, если там действительно существует пара ключей; - Наше приложение не может создать новое, когда там есть пара ключей, созданная установщиком:
CryptographicException: Keyset does not exist.
- Нашприложение не может получить доступ к паре ключей, созданной установщиком, в этом случае произойдет
CryptographicException: Access is denied.
.Шифрование в установщике работает с AES
и RSA public key
.Когда приложение пытается использовать сохраненный private key
для расшифровки, возникает исключение "Access is denied
".
Наш код следующий:
public static void CreateRSAKeyPair(string keyContainerName)
{
DeleteRSAKeyPair(keyContainerName);
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
}
}
public static void DeleteRSAKeyPair(string keyContainerName)
{
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = keyContainerName;
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams))
{
rsa.PersistKeyInCsp = false;
try
{
rsa.Clear();
}
catch (CryptographicException ex)
{
Log.logItem(LogType.Exception, "RSA key clear error, can be ignored", "SecurityMgr::DeleteRSAKeyPair()", "CryptographicException msg=" + ex.ToString());
}
}
}
Код для доступаprivate key
для расшифровки:
private static byte[] RSADecrypt(byte[] inputData, string keyContainerName)
{
byte[] resultData = null;
try
{
CspParameters cspParams = new CspParameters();
cspParams.Flags |= CspProviderFlags.UseMachineKeyStore;
cspParams.KeyContainerName = keyContainerName;
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams))
{
//rsaProvider.PersistKeyInCsp = true;
//private key
RSAParameters rsaParams = rsaProvider.ExportParameters(true);
rsaProvider.ImportParameters(rsaParams);
resultData = rsaProvider.Decrypt(inputData, false);
}
}
catch (CryptographicException ex)
{
string msg = "CryptographicException: keyContainerName=" + keyContainerName + "\nmsg=" + ex.ToString();
Log.logItem(LogType.Exception, "RSA decryption exception", "SecurityMgr::RSADecrypt()", msg);
}
return resultData;
}
Может ли асимметричное шифрование RSA использоваться следующим образом?
РЕДАКТИРОВАТЬ:
Делать то же самое (сШифрование AES и RSA) для строки подключения в нашем приложении (без участия установщика) работает нормально.