У вас есть код для повторного открытия дескриптора клавиши CAPI в PROV_RSA_AES
:
// Force use of Enhanced RSA and AES Cryptographic Provider to allow use of SHA256.
var key = cert.PrivateKey as RSACryptoServiceProvider;
var enhanced = new RSACryptoServiceProvider().CspKeyContainerInfo;
var parameters = new CspParameters(
enhanced.ProviderType,
enhanced.ProviderName,
key.CspKeyContainerInfo.UniqueKeyContainerName);
return new RSACryptoServiceProvider(parameters);
Но key.CspKeyContainerInfo.UniqueKeyContainerName
- это не имя ключа (это имя файла на диске, где хранится ключ), поэтому вы открываете новый ключ (вы также генерируете новый эфемерный ключ просто спросить, какой поставщик по умолчанию). Поскольку он является именованным ключом, он сохраняется, и последующие выполнения приложений разрешаются на один и тот же ключ - но разные «одинаковые» ключи на каждом компьютере.
Более стабильный способ повторного открытия ключа -
var cspParameters = new CspParameters
{
KeyContainerName = foo.CspKeyContainerInfo.KeyContainerName,
Flags = CspProviderFlags.UseExistingKey,
};
(поскольку тип и имя провайдера не указаны, они будут использовать значения по умолчанию, и, сказав UseExistingKey
, вы получите исключение, если ссылаетесь на несуществующий ключ).
Тем не менее, самое простое решение - перестать использовать RSACryptoServiceProvider
. В .NET Framework 4.6 (и .NET Core 1.0) есть метод (n extension) для X509Certificate2
, GetRSAPrivateKey()
, он возвращает RSA
(что вам следует избегать приведения), обычно это RSACng
(в Windows) , но может быть RSACryptoServiceProvider
, если только CAPI имел драйвер, необходимый для HSM, и может быть некоторым другим RSA в будущем. Так как RSACng
обрабатывает SHA-2 лучше, почти никогда не возникает необходимости «вновь открывать» возвращаемый объект (даже если он RSACryptoServiceProvider
, и даже если тип не PROV_RSA_AES
(24), это не означает, что HSM не сможет выполнить SHA-2).