Private Key Component

From MgmtWiki
Jump to: navigation, search

Full Title or Meme

Good Public Key Cryptography is dependent on the absolute protection of the Private Key Component of the public/private key pair.

Scope/Goal

  • The goal of a Private Key Component is give the user an Authentication factor that can be completely within their control.
  • Should some other technology for the use of secret data be found beyond the Private Key Component, it is expected that this wiki page should apply to that new technology as well.

Context

  • Protecting one's secret information, in the modern age of computers, has become synonymous with protect a secret key or a Private Key Component of a key pair.
  • This wiki uses the term Credential for any secret held by a device that can be used in authenticating a user. The best known credential (2020) is a well-protected private key component.
  • Another technology that antedates Public Key technology is a shared secret, such as One-Time Password Authenticators (OTP). Those continue to be useful.

Problems

  • Governments have been the primary customers for keeping secrets and, so, the primary customers for cryptography.
  • The challenge with providing good secrecy became a challenge to (1) find a good cryptography algorithm and (2) getting the cryptographic key security into the hands of those who need it.
  • The end user of public key encryption is typically not aware of the challenges of protecting their Private Key Components from theft or even loss through negligence.

Solutions

  • NIST SP 800-63-3B established authentication assurance level (AAL) the reports the protection level of the user's private key components.
  • Note that web URLs are case-insensitive which means that string comparisons to find keys or certificates must also be case insensitive.

Protection

Private Key Component]] protection has two components: theft and loss of access.

Windows Specific Technology

Windows has two cryptography technologies that use quite different technologies to protect Private Key Components. There is a potential issue with case as it is not significant in URLs but is significant in file names and other places.

Cryptographic API (CAPI)

This technology is based on the original bcrypt libraries acquired from RSA in the last century. The Private Key is protected in the Windows Registry as a part of the certificate key store using the Cryptographic Service Provider (CSP) specific to the type of private key. It was extended in later years to handle keys in hardware like smart cards and HSMs, but the marriage was awkward. This was the only technology supported by managed code (dotnet) until net core 2.1 or framework 4.6. Since Microsoft's ASP web platform was build on dot net, this made good key hygiene very difficult for web developers.

Cryptography Next Generation (CNG)

This is new technology that created the abstraction know a a Key Storage Provider (KSP) to differentiate the function of protecting the Private Key Component from the function of storing credentials that could be renew every year while the KSP was unaffected. Now the permissions for each key storage file can be independently set.

dir cert:\localmachine\my
certutil.exe -store my
dir C:\ProgramData\Microsoft\Crypto\Keys
  • use the value in the localmachine directory to select the thumbprint of the certificate that is needed.
  • Use that thumbprint to find the unique container name from the certutil output
  • Ensure that container name exists as a file name in the folder C:\ProgramData\Microsoft\Keys
  • The site with the script for setting the permissions on a KSP file. Call with the name of the account to get permission to use and a variable containing the certificate. The KSP may, or may not, allow export of the key itself. For the best security it should not be allowed. If you know that the key is present you be remove the part after the "else".
function setCertificatePermission {
    param($accountName, $certificate)
    if([string]::IsNullOrEmpty($certificate.PrivateKey))
    {
        $rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
        $fileName = $rsaCert.key.UniqueName
        $path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
        $permissions = Get-Acl -Path $path
        $access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule($accountName, 'FullControl', 'None', 'None', 'Allow')
        $permissions.AddAccessRule($access_rule)
        Set-Acl -Path $path -AclObject $permissions
    } else{
            $user = New-Object System.Security.Principal.NTAccount($accountName)
            $accessRule = New-Object System.Security.AccessControl.CryptoKeyAccessRule($user, 'FullControl', 'Allow')
            $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")
            $store.Open("ReadWrite")
            $rwCert = $store.Certificates | where {$_.Thumbprint -eq $certificate.Thumbprint}
            $csp = New-Object System.Security.Cryptography.CspParameters($rwCert.PrivateKey.CspKeyContainerInfo.ProviderType, $rwCert.PrivateKey.CspKeyContainerInfo.ProviderName, $rwCert.PrivateKey.CspKeyContainerInfo.KeyContainerName)
            $csp.Flags = "UseExistingKey","UseMachineKeyStore"
            $csp.CryptoKeySecurity = $rwCert.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity
            $csp.KeyNumber = $rwCert.PrivateKey.CspKeyContainerInfo.KeyNumber
            $csp.CryptoKeySecurity.AddAccessRule($AccessRule)
            $rsa2 = New-Object System.Security.Cryptography.RSACryptoServiceProvider($csp)
            $store.close()
        }
}

References