Как проверить, существует ли контейнер ключей RSA в .NET

#.net #encryption #cryptography

#.net #шифрование #криптография

Вопрос:

У нас есть

     Dim cp As New CspParameters()
    cp.KeyContainerName = ContainerName
    cp.Flags = CspProviderFlags.UseMachineKeyStore
  

Как мне убедиться, что новый ключ не создан, если ключ с именем контейнера не существует?

Ответ №1:

Попробуйте это:

     public static bool DoesKeyExists(string containerName)
    {
        var cspParams = new CspParameters
        {
            Flags = CspProviderFlags.UseExistingKey,
            KeyContainerName = containerName
        };

        try
        {
            var provider = new RSACryptoServiceProvider(cspParams);
        }
        catch (Exception e)
        {
            return false;
        }
        return true;
    }
  

Комментарии:

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

2. Переключите флаг на Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore работу для меня.

Ответ №2:

Вот сценарий powershell, который мы используем для проверки заданного имени контейнера:

 # Test if an rsa key container exists on this system.
function Test-RsaKeyContainerName(
    [Parameter(Mandatory=$true)][string] $ContainerName,
    [Parameter(Mandatory=$false)][switch] $UserContainer = $false
) {
    $csp = New-Object -TypeName "System.Security.Cryptography.CspParameters";
    $csp.KeyContainerName = $ContainerName;
    if (!($UserContainer)) {
        $csp.Flags = [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore;
    }
    $csp.Flags = $csp.Flags -bor [System.Security.Cryptography.CspProviderFlags]::UseExistingKey;
    try {
        $rsa = New-Object -TypeName "System.Security.Cryptography.RSACryptoServiceProvider" -ArgumentList ($csp);
    } catch [System.Management.Automation.MethodInvocationException] {
        if ($error[0].Exception.InnerException -ne $null -and
            $error[0].Exception.InnerException.GetType() -eq [System.Security.Cryptography.CryptographicException] -and
            $error[0].Exception.InnerException.Message.StartsWith("Keyset does not exist")) {           
            return $false;
        } else {
            throw;
        }       
    }
    return $true;
}
  

Если вам действительно нужно перечислить ключи, установленные в системе, вы можете позаимствовать код у KeyPal по адресуhttp://www.jensign.com/dotnet/keypal/source/KeyPal.txt

Комментарии:

1. поскольку страницы jensign исчезли, не могли бы вы обновить их, возможно, с помощью ссылки на репозиторий?

2. Обновлена неработающая ссылка на jensign.com

Ответ №3:

Вы можете использовать

 .PersistKeyInCsp = false
  

на вашем провайдере шифрования, который гарантирует, что ключ не останется в контейнере. Это то, что вы имеете в виду?

Комментарии:

1. Не очень хорошая идея, если бы ключ существовал до начала процесса, он был бы удален.