Certificate recipes

See also: all the recipes and the intro

See also my series of posts about the certificates. The recipes here partially overlap with the information from these posts.

 # Machine Certificates
https://msdn.microsoft.com/en-us/library/windows/desktop/cc542475%28v=vs.85%29.aspx

# how to create certs in .NET
https://stackoverflow.com/questions/13806299/how-to-create-a-self-signed-certificate-using-c
# how to create self-signed certs with makecert.exe
https://msdn.microsoft.com/en-us/library/ms733813%28v=vs.110%29.aspx
# cert EKU values
https://support.microsoft.com/en-us/kb/287547
https://stackoverflow.com/questions/10019412/certificates-oid-reference-for-extended-key-usages
# JsonWebKey format
https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
# On Certificates and keys in Windows
https://paulstovell.com/blog/x509certificate2
# A .Net encryption example
https://www.sghaida.com/howto-write-net-encrypt-using-x509-certificate-in-c/
# Conversion between PEM (OpenSSL) cert format and X509 cert format
https://stackoverflow.com/questions/7400500/how-to-get-private-key-from-pem-file
https://www.codeproject.com/Articles/162194/Certificates-to-DB-and-Back
# about CryptAcquireCertificatePrivateKey
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/c4b38e17-5637-4679-8b20-30a0d8348110/cryptacquirecertificateprivatekey-fails-with-cng-certificates
# native encryption/decryption
https://msdn.microsoft.com/en-us/library/windows/desktop/aa382037%28v=vs.85%29.aspx
# source code of .NET - public reference
https://referencesource.microsoft.com/#System/security/system/security/cryptography/x509/x509certificate2collection.cs,256
# about the private key getting automatically deleted
https://stackoverflow.com/questions/10498580/private-keys-get-deleted-unexpectedly-in-windows-server-2008-r2
# FindPrivateKey
https://msdn.microsoft.com/en-us/library/aa717039%28v=vs.110%29.aspx
# how private keys are stored
https://technet.microsoft.com/en-us/library/cc962112.aspx
# machine location of private keys
c:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\

# get the private key, works only with admin privileges (as opposed to $cert.PrivateKey that doesn't work for CNG keys)
$k = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
# GetRSAPrivateKey()/GetRSAPublicKey() were added in 4.6 as the only way to get CNG-based private keys, 
# GetECDsaPrivateKey()/GetECDsaPublicKey() were added in 4.6.1 as the only way of using an ECDSA cert in .NET.

# import back the bytes
$c2 = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 @(,$cbytes)

# Check the contents of the file
certutil.exe "${env:temp}\cert.pfx"

# the good provider
makecert.exe -r -pe -a sha1 -n "CN=MyHost" -ss My -sr CurrentUser -len 2048 -sky exchange -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" -sy 24 C:\Temp\cert.pfx
# this provider is no good, and must use the password for the file
makecert.exe -r -pe -a sha1 -n "CN=MyHost" -ss My -sr CurrentUser -len 2048 -sky exchange -sp "Microsoft Enhanced Cryptographic Provider v1.0" -sy 24 C:\Temp\cert.pfx

# get the list of cert providers
(dir HKLM:Software\Microsoft\Cryptography\Defaults\Provider).Name

# Create a cert from scratch, based on https://stackoverflow.com/questions/13806299/how-to-create-a-self-signed-certificate-using-c
$dn = New-Object System.Security.Cryptography.X509Certificates.X500DistinguishedName @('CN=MyHost')

# in CoreCLR X509Certificate2.PrivateKey was removed for being a bug-farm.  
# The replacements are X509Certificate2.GetRSAPrivateKey() and GetECDsaPrivateKey()

# decrypting an encrypted envelope with a cert
$t = "...base-64-encoded secret data..."
$envelope = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms
$envelope.decode([Convert]::FromBase64String($t))
Add-type -Path C:\vmagent\publish\System.Security.Cryptography.Pkcs.dll
$cert = (get-item Cert:\LocalMachine\My\9CA8283CC644FAF6F73071A182FED04ADFCA4819)
# see if the cert has a private key
[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
# very antique: [System.Security.Cryptography.X509Certificates.DSACertificateExtensions]::GetDSAPrivateKey($cert)
[System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions]::GetECDsaPrivateKey($cert)
$coll = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection $cert
$envelope.decrypt($coll)
[System.Text.Encoding]::UTF8.GetString( $envelope.ContentInfo.Content)

# exporting-importing a cert
$collcc = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection $cc
$ccb = $collcc.Export(X509ContentType.Pkcs12, "")
$impc = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$impc.Import($ccb, "", @("MachineKeySet","Exportable","PersistKeySet"))
[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($impc[0])
$sto = New-Object System.Security.Cryptography.X509Certificates.X509Store @("My", "LocalMachine")
$sto.Open(@("OpenExistingOnly","ReadWrite"))
$sto.Add($impc[1])