Troubleshooting “RSA Key Container Could Not Be Opened” Error in Windows Server 2008 R2 for ASP.NET Applications


6 views

Recently while setting up a secondary ASP.NET site on a Windows Server 2008 R2 machine, I encountered a perplexing issue with RSA key container permissions. The error message "The RSA key container could not be opened" appeared despite using identical application pool configurations.

The setup involves:

- Windows Server 2008 R2
- ASP.NET 4.0 application
- Connection strings encrypted using RSA
- Multiple application pools with same identity
- Existing working site in Default App Pool
- New site failing with custom App Pool

First, I verified the application pool identity:

// Check application pool identity in IIS
// Both pools use the same domain account: dmz\UserName

Then attempted to grant permissions using:

aspnet_regiis -pa "KeyContainerName" "dmz\UserName"

But received "The RSA key container was not found" error.

The most confusing part was the conflicting messages:

aspnet_regiis -pi "KeyContainerName" "c:\keys.xml" → "Object already exists"
aspnet_regiis -pz "KeyContainerName" → "RSA key container was not found"

After extensive research, here's what worked:

1. Verify Key Container Existence

First, confirm if the key container actually exists:

// C# code to check key container existence
using System.Security.Cryptography;

try 
{
    var cspParams = new CspParameters 
    {
        Flags = CspProviderFlags.UseMachineKeyStore,
        KeyContainerName = "KeyContainerName"
    };
    
    using (var rsa = new RSACryptoServiceProvider(cspParams))
    {
        // If no exception, container exists
        Console.WriteLine("Container exists and is accessible");
    }
}
catch (CryptographicException ex)
{
    Console.WriteLine($"Error accessing container: {ex.Message}");
}

2. Machine-Level vs User-Level Containers

The key issue was the container being created at user level rather than machine level. To fix:

// Recreate container with machine-level flag
aspnet_regiis -pz "KeyContainerName"
aspnet_regiis -pi "KeyContainerName" "c:\keys.xml" -exp
aspnet_regiis -pa "KeyContainerName" "NT AUTHORITY\NETWORK SERVICE"
aspnet_regiis -pa "KeyContainerName" "dmz\UserName"

3. Permission Inheritance Problem

For applications running under different identities:

// Grant permissions to all required accounts
aspnet_regiis -pa "KeyContainerName" "IIS AppPool\DefaultAppPool"
aspnet_regiis -pa "KeyContainerName" "IIS AppPool\NewAppPool"

To ensure everything works:

  1. Restart IIS: iisreset
  2. Verify in both application pools
  3. Check Event Viewer for any cryptographic errors

For future deployments:

// PowerShell script to automate key container setup
$containerName = "KeyContainerName"
$keyFile = "C:\keys.xml"
$accounts = @("IIS AppPool\DefaultAppPool", "dmz\UserName")

aspnet_regiis -pz $containerName
aspnet_regiis -pi $containerName $keyFile -exp

foreach ($account in $accounts) {
    aspnet_regiis -pa $containerName $account
}

Remember to store your key file securely and include proper error handling in production scripts.


When deploying a secondary ASP.NET application on Windows Server 2008 R2 with identical application pool configurations to the primary site, the system fails to access the existing RSA key container despite using the same identity credentials. The error chain reveals contradictory messages:

1. Failed RSA container access in new app pool (error: "could not be opened")
2. Failed permission assignment (error: "container was not found") 
3. Failed import attempt (error: "Object already exists")
4. Failed deletion attempt (error: "container was not found")

The system maintains RSA key containers in two distinct locations:

Machine-level: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
User-level: C:\Users\[username]\AppData\Roaming\Microsoft\Crypto\RSA

When the aspnet_regiis -pi command reports "Object already exists" while -pz claims it doesn't, this typically indicates:

  • The container exists in machine storage but has restricted ACLs
  • The executing context lacks permissions to view/access the container
  • Possible cryptographic service provider (CSP) mismatch

Step 1: Verify actual container existence

# PowerShell command to list machine-level containers
Get-ChildItem -Path "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" | 
    Where-Object { $_.Name -match "[0-9a-f]{32}" } | 
    ForEach-Object {
        $acl = Get-Acl $_.FullName
        [PSCustomObject]@{
            File = $_.Name
            Owner = $acl.Owner
            Access = $acl.Access | 
                Where-Object { $_.IdentityReference -like "*YOUR_USER*" }
        }
    }

Step 2: Corrective actions for common scenarios

# Scenario 1: Reset container permissions (admin PowerShell)
$containerPath = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\[CONTAINER_GUID]"
$userAccount = "DOMAIN\USER"
$acl = Get-Acl $containerPath
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $userAccount,
    "FullControl",
    "Allow")
$acl.AddAccessRule($rule)
Set-Acl -Path $containerPath -AclObject $acl

# Scenario 2: Recreate container with proper inheritance
aspnet_regiis -pz "KeyContainerName"
aspnet_regiis -pi "KeyContainerName" "C:\keys.xml" -exp
aspnet_regiis -pa "KeyContainerName" "DOMAIN\USER"

When standard approaches fail, consider these diagnostic steps:

# Check CSP provider compatibility
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$rsa.CspKeyContainerInfo.MachineKeyStore = $true
$rsa.CspKeyContainerInfo.KeyContainerName = "KeyContainerName"
$rsa.PersistKeyInCsp = $true
$rsa.Clear()

# Verify DPAPI protection scope
Add-Type -AssemblyName System.Web
[System.Web.Configuration.MachineKeySection]::DecryptConfig(
    "connectionStrings",
    "RsaProtectedConfigurationProvider",
    "KeyContainerName")
  • Always specify -exp flag during container creation for exportable keys
  • Configure identical settings across web.config files
  • Document container GUIDs and permission assignments
  • Consider using Azure Key Vault for modern deployments