通过PowerShell创建PEM文件

eufgjt7s  于 2023-04-30  发布在  Shell
关注(0)|答案(5)|浏览(277)

我正在尝试编写一个脚本来在powershell中创建PEM证书文件。我不确定我所做的是否完全错误,但是当我试图在和socat OPENSSL中使用PEM文件时,它返回了错误:

$ socat OPENSSL-LISTEN:1337,cert=cert.pem,verify=0 -

socat[1209] E SSL_CTX_use_certificate_file(): error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag
#create certificate
$cert = New-SelfSignedCertificate `
    -Subject "MYHOSTNAME" `
    -TextExtension @("2.5.29.17={text}DNS=MYHOSTNAME&IPAddress=192.168.1.100") `
    -KeySpec Signature `
    -HashAlgorithm SHA256 `
    -KeyExportPolicy Exportable

#publicKey
$PublicKey = $cert.GetPublicKey();
$PublicKeyB64 = [Convert]::ToBase64String($PublicKey,"InsertLineBreaks");

#privateKey
$RSACng  = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert);
$PrivateKey = $RSACng.Key;
$PrivateKeyByte = $PrivateKey.Export("PRIVATEBLOB");
$PrivateKeyB64 = [Convert]::ToBase64String($PrivateKeyByte,"InsertLineBreaks");

#createFile
$out = New-Object string[] -ArgumentList 6;
$out[0] = "-----BEGIN PRIVATE KEY-----";
$out[1] = $PrivateKeyB64;
$out[2] = "-----END PRIVATE KEY-----"

$out[3] = "-----BEGIN CERTIFICATE-----"
$out[4] = $publicKeyB64;
$out[5] = "-----END CERTIFICATE-----"

[IO.File]::WriteAllLines("C:\Users\Public\cert.pem",$out)

我不确定我所做的是否完全错误,但我找不到任何资源来帮助我继续下去。
一些在powershell中执行类似创建PEM文件的操作的脚本或一些关于如何继续的提示可能对帮助我解决这个问题很有价值。

gcuhipw9

gcuhipw91#

您也可以使用CertUtil。exe。执行一次
Certutil.exe是一个命令行程序,作为证书服务的一部分安装。
如此简单的脚本创建。使用powershell的PEM如下:

$certpwd = '***'
$certpwd1 = ConvertTo-SecureString -String $certpwd -Force –AsPlainText
$certpwd2 = 'pass:' + $certpwd
$certname = $env:COMPUTERNAME
del c:\temp\$certname.*

$cert = New-SelfSignedCertificate -DnsName $certname -certStorelocation cert:\localmachine\my -KeyLength 2048  -KeyFriendlyName $certname -FriendlyName $friendlyName -HashAlgorithm sha256 -keyexportpolicy exportableencrypted -keyspec KeyExchange -NotAfter (Get-Date).AddYears(2) | Out-Null

$cert2=Get-ChildItem Cert:\LocalMachine\my |
Where-Object { $_.FriendlyName -match $friendlyName }

$path = ‘cert:\localMachine\my\’ + $cert2.thumbprint
Export-Certificate -cert $path -FilePath c:\temp\$certname.der -type CERT –noclobber | Out-Null
certutil -encode c:\temp\$certname.der c:\temp\$certname.pem | Out-Null

剧本的作用是
1)首先,它创建自签名证书
2)然后以形式导出到某个物理路径。德尔
3)使用Certutil进行编码并创建。pem文件(在本例中,.pem将保存在c:\temp\中)

ifsvaxew

ifsvaxew2#

正如注解所述,您在两个PEM文件的主体中放置的数据是错误的。
对于证书,很简单,只需要使用$cert.RawData(转换为base64,使用linebreak,正如您已经使用的那样)。
对于私钥,根据GetRSAPrivateKey($cert)返回的RSA摘要文档(not.Key),因此它的实现(如RSACng)具有方法ExportPkcs8PrivateKey(),这应该是放入BEGIN/END PRIVATE KEY类型的PEM文件的正确数据,并且ExportRSAPrivateKey()应该是正确的BEGIN/END RSA PRIVATE KEY类型的PEM文件的旧格式--但仅限于Core 3。0+和5,我没有,因此无法测试。
如果你有openssl命令行,一个解决办法是将Export-PfxCertificate转换为一个文件,然后openssl pkcs12 [-nodes]可以将其转换为OpenSSL(以及socat)喜欢的PEM格式。但是如果你有openssl命令行,你可以很容易地使用它来直接生成私钥和(自签名/虚拟)证书,而不需要使用powershell。

fiei3ece

fiei3ece3#

你很接近了,这是它的工作方式:

$cert = ...

# Public key to Base64
$CertBase64 = [System.Convert]::ToBase64String($cert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks)

# Private key to Base64
$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)

# Put it all together
$Pem = @"
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
$CertBase64
-----END CERTIFICATE-----
"@

# Output to file
$Pem | Out-File -FilePath cert.pem -Encoding Ascii

如果你想得到openssl pkcs12 -in cert.pfx -out cert.pem -nodes(e.包括整个证书链),在这里:

$cert = ...

# Collect certificates
$CertChain = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Chain
$CertChain.Build($cert)
$certs = $CertChain.ChainElements | ForEach-Object {$_.Certificate}
[System.Array]::Reverse($certs)

# Private key to Base64
$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)

# Put it all together
$Pem = @"
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
"@
foreach ($cert in $certs) {
    $Pem += @"

-----BEGIN CERTIFICATE-----
$([System.Convert]::ToBase64String($cert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks))
-----END CERTIFICATE-----
"@
}

# Output to file
$Pem | Out-File -FilePath cert.pem -Encoding Ascii
roejwanj

roejwanj4#

使用stackprotector's approach,我遇到了一些其他人无疑会遇到的障碍:
1.目标证书必须是可导出的。是的,这应该是显而易见的,但如果您使用PowerShell创建证书,您可能会错过它。如果您运行此操作所针对的密钥不可导出,您将收到一个错误:
不支持请求的操作。
如果要创建证书,请在命令末尾添加-KeyExportPolicy Exportable
1.如何设置$cert变量很重要。它不仅仅是一个字符串值。使用get-item命令设置要使用的对象。其他的一切都工作得很好。

# Create a self-signed exportable certificate
New-SelfSignedCertificate -DnsName hostname.domain.com -KeyExportPolicy Exportable  

# Identify the cert to export with the script
$cert = get-item "cert:\localmachine\my\2F61C944634AA90A4AD7D1FE89BBEFAA3C0B6FDD"

# Public key to Base64
$CertBase64 = [System.Convert]::ToBase64String($cert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks)

# Private key to Base64
$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)

# Put it all together
$Pem = @"
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
$CertBase64
-----END CERTIFICATE-----
"@

# Output to file
$Pem | Out-File -FilePath cert.pem -Encoding Ascii
axr492tv

axr492tv5#

我对前面的两个答案都有困难。经过大量的搜索和测试,我发现了一个方法,与香草powershell和少数(没有?)权限。
此脚本还将自签名证书作为pfx、der和pem文件提供。

$dir = "c:\temp\"

$subj = "CN=YOUR_SUBJECT" #need either DnsName or Subject when calling New-SelfSignedCertificate

$friendlyName = "YOUR_FRIENDLY_NAME"

$pfxFilePath = $dir, $friendlyName, ".pfx" -join ""

$derFilePath = $dir, $friendlyName, ".der" -join ""

$pemFilePath = $dir, $friendlyName, ".pem" -join ""

#create new certificate in cert:\currentuser\my and store in variable $cert
$cert = New-SelfSignedCertificate -CertStoreLocation cert:\currentuser\my -Subject $subj -KeyAlgorithm RSA -KeyLength 2048 -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -KeyExportPolicy Exportable -FriendlyName $friendlyName -NotAfter (Get-Date).AddYears(2)

#get password for pfx file
$pw = Read-Host "Enter Password:"

#export cert to pfx and write to file 
[io.file]::WriteAllBytes($pfxFilePath,$cert.Export(3, $pw))

#export cert to der and write to file
Export-Certificate -FilePath $derFilePath -Cert $cert

#encode der file as pem file and write to file
certutil -encode $derFilePath $pemFilePath | Out-Null

相关问题