2

i use the following powershell script to generate self signed certificates on windows 2016 and above:

$cert = New-SelfSignedCertificate `
            -Subject "CN=$env:COMPUTERNAME,OU=xx,O=xx,C=xx" `
            -KeyAlgorithm RSA `
            -KeyLength 2048 `
            -KeyExportPolicy Exportable `
            -NotAfter (Get-Date).AddYears(3)

# export the certificate and dump to file
$CertBase64 = [System.Convert]::ToBase64String($cert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks)
$Crt = @"
-----BEGIN CERTIFICATE-----
$CertBase64
-----END CERTIFICATE-----
"@
$Crt | Out-File -FilePath C:\cert.crt -Encoding Ascii

# export the private key and dump to file
$RSACng = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
$KeyBase64 = [System.Convert]::ToBase64String($KeyBytes, [System.Base64FormattingOptions]::InsertLineBreaks)
$Key = @"
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
"@
$Key | Out-File -FilePath C:\cert.key -Encoding Ascii

# clean keystore
$cert | Remove-Item

On windows 2012 R2 i have to change the New-SelfSignedCeriticate command to:

$cert = New-SelfSignedCertificate `
    -DnsName "$env:COMPUTERNAME" `
    -CertStoreLocation cert:\LocalMachine\My

but when i run the $KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob) command i get this error:

PS C:\> $KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateB
lob)
Exception calling "Export" with "1" argument(s): "The requested operation is not supported.
"
At line:1 char:1
+ $KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]:: ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CryptographicException

Any idea on why this command doens't work on windows 2012?

Thanks.

PS: I cannot use openssl or other third party tools.

EDIT 1

As requested in the comments, i'm attaching the output of the $cert.GetType() and $RSACng.GetType() commands:

PS C:\> $cert.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     X509Certificate2                         System.Security.Cryptography.X509Certificates.X509Certifi...


PS C:\> $RSACng.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    RSACng                                   System.Security.Cryptography.RSA

EDIT 2

I solved this the following script that should work on all windows versions above 2012.

if ([System.Environment]::OSVersion.Version -lt [Version]"10.0.14393.0") {   # generate a self-signed certificate windows < 2016
  $policies = [System.Security.Cryptography.CngExportPolicies]::AllowPlaintextExport,[System.Security.Cryptography.CngExportPolicies]::AllowExport

  $name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
  $name.Encode("CN=$env:COMPUTERNAME,OU=xxxx,O=yyyy S.p.A.,C=IT", 0)

  $key = new-object -com "X509Enrollment.CX509PrivateKey.1"
  $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
  $key.KeySpec = 1
  $key.Length = 2048
  $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
  $key.MachineContext = 1
  $key.ExportPolicy = [System.Security.Cryptography.CngExportPolicies]::AllowPlaintextExport
  $key.Create()

  $serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
  $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
  $ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
  $ekuoids.add($serverauthoid)
  $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
  $ekuext.InitializeEncode($ekuoids)

  $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
  $cert.InitializeFromPrivateKey(2, $key, "")
  $cert.Subject = $name
  $cert.Issuer = $cert.Subject
  $cert.NotBefore = get-date
  $cert.NotAfter = $cert.NotBefore.AddYears(10)
  $cert.X509Extensions.Add($ekuext)
  $cert.Encode()

  $enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
  $enrollment.InitializeFromRequest($cert)
  $certdata = $enrollment.CreateRequest(0)
  $enrollment.InstallResponse(2, $certdata, 0, "")

  $cert = Get-ChildItem Cert:\LocalMachine\My | where{$_.Subject -like "*xxxx*yyyy*"} 
  else {   # generate a self-signed certificate windows >= 2016
  $cert = New-SelfSignedCertificate -Subject "CN=$env:COMPUTERNAME,OU=xxxx,O=yyyy S.p.A.,C=IT" -KeyAlgorithm RSA -KeyLength 2048 -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(10)
}

# export the certificate and dump to file
$CertBase64 = [System.Convert]::ToBase64String($cert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks)
$Crt = @"
-----BEGIN CERTIFICATE-----
$CertBase64
-----END CERTIFICATE-----
"@
$Crt | Out-File -FilePath C:\abc.crt -Encoding Ascii

# export the private key and dump to file
$RSACng = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
$KeyBase64 = [System.Convert]::ToBase64String($KeyBytes, [System.Base64FormattingOptions]::InsertLineBreaks)
$Key = @"
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
"@
$Key | Out-File -FilePath C:\abc.key -Encoding Ascii

# clean keystore
$cert | Remove-Item
vb8448
  • 21
  • 2
  • You are on two different machines. I would try the code on Windows 2016 to see if it works. You may not have permission to write to root folder c:\ on the 2012 machine. Check if file C:\cert.crt was generated. Also try to run As Admin. – jdweng Jul 22 '23 at 09:00
  • @jdweng Hi, i've already tried the script on win 2016 and 2019 and it works. The error is before i'm trying to write on the disk. – vb8448 Jul 22 '23 at 10:17
  • What line? That would mean New-SelfSignedCertificate is failing. What encryption mode is being used? Sha-1 has been decommissioned : https://techcommunity.microsoft.com/t5/iis-support-blog/sha-256-self-signed-certificate-for-windows-server-2012-r2/ba-p/376391 You are not specifying an encryption mode and the default one may be disabled. – jdweng Jul 22 '23 at 11:22
  • 1
    @jdweng On win server 2012, New-SelfSignedCertificate [accepts less parameters](https://learn.microsoft.com/en-us/powershell/module/pki/new-selfsignedcertificate?view=winserver2012r2-ps&redirectedfrom=MSDN). The line that is failing is `$KeyBytes = $RSACng.Key.Export` – vb8448 Jul 22 '23 at 13:26
  • What does following return : Write-Host $cert.GetType() $RSACng.GetType() – jdweng Jul 22 '23 at 14:54
  • @jdweng i added the output in the original message – vb8448 Jul 22 '23 at 20:21
  • The code runs on my Windows 11 machine, but I have to run As Admin. Windows 8 and Windows 2012 have same encryption libraries. Following are the encryption modes supported. RSA 2048 is not on the list : https://learn.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-8 – jdweng Jul 22 '23 at 21:48
  • I tried to create a certificate with 1024 key length following this [guide](https://stackoverflow.com/questions/12463297/using-powershell-to-create-self-signed-certificate) but still doesn't work. – vb8448 Jul 23 '23 at 21:38
  • From powershell use following : Get-TlsCipherSuite – jdweng Jul 23 '23 at 22:16
  • @jdweng i solved after reading this [post](https://stackoverflow.com/questions/57269726/x509certificate2-import-with-ncrypt-allow-plaintext-export-flag/57330499#57330499). The certificate need the `exportplaintext` field to be exportable. – vb8448 Jul 24 '23 at 13:23
  • What encryption mode did you end up with? You are now using the com object "X509Enrollment.CX509PrivateKey.1" – jdweng Jul 24 '23 at 14:26
  • Yes, i put the full script in the `EDIT 2` section in the main message. – vb8448 Jul 24 '23 at 14:47

0 Answers0