如何查找msi是否带时间戳?

时间:2012-01-31 11:17:19

标签: powershell batch-file powershell-v2.0 code-signing-certificate

我正在使用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时间戳是否丢失,怎么做?

2 个答案:

答案 0 :(得分:1)

最后我自己找到答案。似乎有一个名为“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
        }

答案 1 :(得分:1)

这是一个PowerShell解决方案,由PowerShell MVP Vadims Podans提供。 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
            }
        }    
    }
}