8

We have

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

How do I make sure that new key is not created if the key with ContainerName does not exist?

Matthew Rygiel
  • 1,247
  • 2
  • 15
  • 17

3 Answers3

9

Try this:

    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;
    }
hdev
  • 6,097
  • 1
  • 45
  • 62
  • This isn't great as it assumes that a general exception means that it doesn't exist which isn't good practice. However, from what I've been able to find, this seems like the only way. – Jake Nov 02 '18 at 13:41
  • 1
    Switch flag to `Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore` work for me. – Kerwen Dec 27 '19 at 05:37
4

Here's a powershell script we use to test for a given container name:

# 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;
}

If you actually need to enumerate the keys installed on the system, you can borrow the code from KeyPal at http://www.jensign.com/dotnet/keypal/source/KeyPal.txt

Jamey
  • 1,595
  • 9
  • 23
1

You can use

.PersistKeyInCsp = false

on your crypto provider which will ensure that the key doesn't get left over in the container. Is this what you mean?

Wolfwyrd
  • 15,716
  • 5
  • 47
  • 67