неожиданное исключение CryptographicException: набор ключей не существует И исключение CryptographicException: доступ запрещен - PullRequest
1 голос
/ 28 января 2011

Мы пытаемся сделать это для нашего приложения 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.

Я знаю, где хранится пара ключей, так что я могу отслеживать ее, чтобы увидеть, была ли удалена пара ключей,обновлен или создан.

Я провел несколько тестов и обнаружил некоторые интересные (неожиданные) вещи, но не знаю, почему это так.Моя учетная запись пользователя - учетная запись администратора.

  1. Программа установки может удалить сохраненную key-pair, созданную нашим приложением, и сразу же создать новую с тем же именем контейнера;
  2. Программа установки можетОбновление key-pair, созданное нашим приложением (не удаляйте и не создавайте заново, я думаю, оно перезаписывается, но этого не должно происходить в соответствии с документацией): CryptographicException: Keyset does not exist. исключение произойдет, если там действительно существует пара ключей;
  3. Наше приложение не может создать новое, когда там есть пара ключей, созданная установщиком: CryptographicException: Keyset does not exist.
  4. Нашприложение не может получить доступ к паре ключей, созданной установщиком, в этом случае произойдет 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) для строки подключения в нашем приложении (без участия установщика) работает нормально.

1 Ответ

2 голосов
/ 23 мая 2011

Актуальный вопрос не очень понятен. Тем не менее, я вижу несколько вещей в вашем коде:

  • Вы экспортируете пару ключей (приватную и публичную) из провайдера в параметры. Люди запутываются в булевом параметре. Это не означает, что он экспортирует только закрытый ключ. Если вы установите его в значение true (экспортировать закрытый ключ), ваши ключи PUBLIC и PRIVATE будут экспортированы.
  • Те же ключи, которые вы экспортировали из своего экземпляра провайдера RSA, вы импортируете обратно в того же провайдера. Это не имеет никакого смысла.
  • Удалите строки ExportParameters и ImportParameters, они ничего не добьются. Ваши ключи должны быть уже в поставщике RSA, если имя контейнера, указанное вами в конструкторе, является действительным и существует.
  • С асимметричной криптографией вы используете ключ PRIVATE для шифрования, потому что вы не передаете. Затем вы используете ключ PUBLIC для дешифрования, потому что другая сторона (получатель) должна держать только ваш ключ PUBLIC, чтобы иметь возможность расшифровать. Если у них есть ваш личный ключ, вся схема будет взломана.
...