3

我正在使用 signtool 对我的 msi 和 setup.exe 文件进行签名。

大多数 msi 的时间戳都失败了,现在我想分别给它们加上时间戳。

如何查找时间戳是否丢失?

以下 cmdlet 可帮助我查找它是否已签名

$AuthStatus= (Get-AuthenticodeSignature $FILENAME)

    If ($AuthStatus.status -ne "Valid") {

               $SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
        }

现在我需要检查 msi 时间戳是否丢失,怎么办?

4

2 回答 2

2

最后我自己找到了答案。似乎有一个名为“TimeStamperCertificate”的属性。以下是代码片段。

如果 msi 没有签名或时间戳,它将再次签名和时间戳。

$MsiAuthInfo= (Get-AuthenticodeSignature $FILENAME)

    If ($MsiAuthInfo.status -ne "Valid" -or $MsiAuthInfo.TimeStamperCertificate -eq $Null) {

               $SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
        }
于 2012-02-02T14:06:53.447 回答
1

这是由 PowerShell MVP Vadims Podans 提供的 PowerShell 解决方案。Get-AuthenticodeSignatureEx在结果中添加一个 SigningTime 属性,该值是作为通用时间(不是本地时间)的日期时间,您始终可以在 datetime 对象上调用 ToLocalTime() 以获取您所在时区的结果。您可以使用以下命令快速测试它:

dir $pshome\*.ps1xml | Get-AuthenticodeSignatureEx | ft SignerCertificate,Status,SigningTime,Path


function Get-AuthenticodeSignatureEx
{
    [CmdletBinding()]

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String[]]$FilePath
    )

    begin
    {
        $signature = @"
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptQueryObject(
            int dwObjectType,
            [MarshalAs(UnmanagedType.LPWStr)]string pvObject,
            int dwExpectedContentTypeFlags,
            int dwExpectedFormatTypeFlags,
            int dwFlags,
            ref int pdwMsgAndCertEncodingType,
            ref int pdwContentType,
            ref int pdwFormatType,
            ref IntPtr phCertStore,
            ref IntPtr phMsg,
            ref IntPtr ppvContext
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptMsgGetParam(
            IntPtr hCryptMsg,
            int dwParamType,
            int dwIndex,
            byte[] pvData,
            ref int pcbData
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptMsgClose(
            IntPtr hCryptMsg
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CertCloseStore(
            IntPtr hCertStore,
            int dwFlags
        );
"@
        Add-Type -AssemblyName System.Security
        Add-Type -MemberDefinition $signature -Namespace PKI -Name Crypt32
    }

    process
    {
        Get-AuthenticodeSignature @PSBoundParameters | ForEach-Object {
            $Output = $_
            if ($Output.SignerCertificate -ne $null) {
                $pdwMsgAndCertEncodingType =  0
                $pdwContentType =  0
                $pdwFormatType =  0
                [IntPtr]$phCertStore = [IntPtr]::Zero
                [IntPtr]$phMsg = [IntPtr]::Zero
                [IntPtr]$ppvContext = [IntPtr]::Zero
                $return = [PKI.Crypt32]::CryptQueryObject(
                    1,
                    $_.Path,
                    16382,
                    14,
                    $null,
                    [ref]$pdwMsgAndCertEncodingType,
                    [ref]$pdwContentType,
                    [ref]$pdwFormatType,
                    [ref]$phCertStore,
                    [ref]$phMsg,
                    [ref]$ppvContext
                )

                $pcbData = 0
                $return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$null,[ref]$pcbData)
                $pvData = New-Object byte[] -ArgumentList $pcbData
                $return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$pvData,[ref]$pcbData)
                $SignedCms = New-Object Security.Cryptography.Pkcs.SignedCms
                $SignedCms.Decode($pvData)
                foreach ($Infos in $SignedCms.SignerInfos) {
                    foreach ($CounterSignerInfos in $Infos.CounterSignerInfos) {
                        $sTime = ($CounterSignerInfos.SignedAttributes | Where-Object {$_.Oid.Value -eq "1.2.840.113549.1.9.5"}).Values | Where-Object {$_.SigningTime -ne $null}
                    }
                }
                $Output | Add-Member -MemberType NoteProperty -Name SigningTime -Value $sTime.SigningTime -PassThru -Force
                [void][PKI.Crypt32]::CryptMsgClose($phMsg)
                [void][PKI.Crypt32]::CertCloseStore($phCertStore,0)
            } else {
                $Output
            }
        }    
    }
}
于 2012-02-13T07:35:38.633 回答