You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本返回值异常:为何证书指纹附带文件路径?

问题解决:PowerShell脚本返回多余值的原因及修复

问题描述

调用createInstallSSLCertificates.ps1脚本获取证书指纹时,返回值包含了证书文件夹路径和.ext文件路径,而非仅预期的指纹字符串。

根本原因

PowerShell的隐式返回机制:脚本中所有未被捕获或抑制输出的命令结果,都会被自动添加到脚本的输出流中。你的脚本里,创建目录和文件的New-Item命令返回了对应的对象,这些对象被包含在了最终的返回值里。

修复方案

需要将所有不需要作为返回值的命令输出进行抑制,具体操作如下:

1. 抑制New-Item命令的输出

在创建证书目录和.ext文件的New-Item命令末尾添加| Out-Null,阻止其输出进入脚本返回流:

New-item -ItemType Directory $dirname | Out-Null
New-Item -Path $ext_file -ItemType File | Out-Null

2. 抑制外部命令(openssl)的输出

将openssl命令的标准输出和错误输出重定向到null,避免混入返回值:

openssl genrsa -des3 -passout pass:$rootpassword -out $rootkey 2048 2>&1 | Out-Null

对所有openssl命令都应用此处理。

3. 确保仅返回预期值

保留脚本末尾的return语句,确保只有指纹或错误信息作为最终返回值。

修改后的完整脚本

param (
    [Parameter(Mandatory=$false, HelpMessage="创建证书后是否安装")]
    [bool]
    $InstallCerts=$false,

    [Parameter(Mandatory=$false, HelpMessage="创建EXT文件后是否暂停,以便添加更多DNS名称")]
    [bool]
    $PauseOnExtFile=$false,

    [Parameter(Mandatory=$false, HelpMessage="服务器的SAN、DNS或主机名")]
    [string]
    $SAN=$(hostname),

    [Parameter(Mandatory=$false, HelpMessage="个人签名证书的通用名称/友好名称")]
    [string]
    $PersonalCommonName=$(hostname),

    [Parameter(Mandatory=$false, HelpMessage="CA根证书的通用名称/友好名称")]
    [string]
    $RootCommonName="COMPANY123",

    [Parameter(Mandatory=$false, HelpMessage="(LocalMachine | CurrentUser)")]
    [string]
    $user="LocalMachine"
)

if (!($user.Contains("LocalMachine")) -and !($user.Contains("CurrentUser"))) {
    Write-Host "`$user必须是LocalMachine或CurrentUser,而不是'$user'"
    Exit
}

################## 变量定义 #######################
$base = "CAcerts"
$certuser = $user
$rootpassword = "password"
$pfxexportpassword = "password"
$country = "CH"
$state = "BIOBIO"
$city = "Concepcion"
$org = "mycompany"
$unit = "UNIT"

################ 文件路径与目录创建 ##################

$epochseconds = Get-Date (Get-Date).ToUniversalTime() -UFormat %s
$epochseconds = $epochseconds.Replace(".", "")
$ran = $epochseconds.Substring($epochseconds.Length-4, 4)

$cwd = Get-Location
$dirname = join-path -Path $cwd -ChildPath "$($base)_certs_$($ran)"
$rootkey= $base + "_root_key.key"
$rootpem= $base + "_root_pem.pem"
$rootcert= $base + "_root_ca.crt"
$serverkey= $base + "_server_key.key"
$servercsr= $base + "_server_csr.csr"
$servercert= $base + "_server_cert.crt"
$serverpfx= $base + "_server_pfx.pfx"
$ext_file= $base + "_server_ext.ext"

$rootkey= join-path $dirname $rootkey
$rootpem= join-path $dirname $rootpem
$rootcert= join-path $dirname $rootcert
$serverkey= join-path $dirname $serverkey
$servercsr= join-path $dirname $servercsr
$servercert= join-path $dirname $servercert
$serverpfx= join-path $dirname $serverpfx
$ext_file= join-path $dirname $ext_file

New-item -ItemType Directory $dirname | Out-Null
New-Item -Path $ext_file -ItemType File | Out-Null

################## 安装OPENSSL #######################
if (!(Get-Command openssl -ErrorAction SilentlyContinue)) {
    Write-Host "未识别openssl命令,将通过chocolatey安装。" -ForegroundColor Yellow
    if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
        Set-ExecutionPolicy Bypass -Scope Process -Force; 
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; 
        Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
    }

    if (!(Get-Command openssl -ErrorAction SilentlyContinue)) {
        choco install openssl.light -y
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
    }
}
################## 创建证书 #######################

Write-Host "创建根密钥"
openssl genrsa -des3 -passout pass:$rootpassword -out $rootkey 2048 2>&1 | Out-Null
if ( !(Test-Path -Path $rootkey -PathType Leaf)) {
    Write-Host("$rootkey未创建成功")
}

Write-Host "创建根CA证书"
openssl req -x509 -new -nodes -key $rootkey -sha256 -days 3650 -out $rootcert -passin pass:$rootpassword -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$RootCommonName" 2>&1 | Out-Null
if ( !(Test-Path -Path $rootcert -PathType Leaf)) {
    Write-Host("$rootcert未创建成功")
}

Write-Host "创建根PEM密钥"
openssl req -x509 -new -nodes -key $rootkey -sha512 -days 3650 -out $rootpem -passin pass:$rootpassword -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$RootCommonName" 2>&1 | Out-Null
if ( !(Test-Path -Path $rootpem -PathType Leaf)) {
    Write-Host("$rootpem未创建成功")
}

Write-Host "创建服务器私钥"
openssl genrsa -out $serverkey 2048 2>&1 | Out-Null
if ( !(Test-Path -Path $serverkey -PathType Leaf)) {
    Write-Host("$serverkey未创建成功")
}

Write-Host "创建Ext文件"
$content = 
"authorityKeyIdentifier=keyid,issuer 
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = @alt_names

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1 = $SAN"

$content | Out-File -FilePath $ext_file -Encoding utf8
if ($pauseOnExtFile) {
    Write-Host "暂停执行,你可以手动修改EXT文件: '$ext_file'
添加更多DNS名称。"
    $_pause = Read-Host "按回车键继续"
}

Write-Host "创建服务器CSR文件"
openssl req -new -key $serverkey -out $servercsr -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$PersonalCommonName" 2>&1 | Out-Null
if ( !(Test-Path -Path $servercsr -PathType Leaf)) {
    Write-Host("$servercsr未创建成功")
}

Write-Host "创建服务器证书"
openssl x509 -req -in $servercsr -CA $rootpem -CAkey $rootkey -CAcreateserial -out $servercert -days 3650 -sha512 -extfile $ext_file -extensions 'req_ext' -passin pass:$rootpassword 2>&1 | Out-Null
if ( !(Test-Path -Path $servercert -PathType Leaf)) {
    Write-Host("$servercert未创建成功")
}

Write-Host "将证书转换为PFX格式"
openssl pkcs12 -export -inkey $serverkey -in $servercert -passout pass:$pfxexportpassword -name $base -out $serverpfx 2>&1 | Out-Null
if ( !(Test-Path -Path $serverpfx -PathType Leaf)) {
    Write-Host("$serverpfx未创建成功")
}

################## 安装证书 #######################
if ($InstallCerts) {
$pfxexportpassword = ConvertTo-SecureString -String $pfxexportpassword -Force -AsPlainText
    try {
        $rootobj = Import-Certificate -FilePath $rootcert -CertStoreLocation "cert:\$certuser\Root"
        $personalobj = Import-PfxCertificate -FilePath $serverpfx -CertStoreLocation "cert:\$certuser\My" -Password $pfxexportpassword
        Write-Host "根证书已安装到$certuser\Trust Root CA,名称为$RootCommonName"
        Write-Host "服务器证书已安装到$certuser\Personal,名称为$PersonalCommonName。指纹: ${personalobj.Thumbprint}"
        Write-Host "证书创建程序执行成功,前缀为$base。"
        Write-Host "退出程序..."

        if ($personalobj -and $rootobj) {
            Write-Host "根证书指纹: $($rootobj.Thumbprint)`n 个人证书指纹: $($personalobj.Thumbprint)"
            return $personalobj.Thumbprint
        } else {
            return "证书安装出错"
        }
    } catch {
        Write-Host "证书安装失败,请检查权限后重试。"
        Exit
    }
}

内容的提问来源于stack exchange,提问作者Lacrosse343

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:10:58