PoshCode Logo PowerShell Code Repository

Get/Set Signature 2.0 by Joel Bennett 27 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1470"></script>download | new post

Authenticode 1.8 for PowerShell 2.0: The default cert should be put in a ModuleInfo file, but it will work without that, and will prompt you for a certificate (and/or the password for it) only once per session.

Description: Wrappers for the Get-AuthenticodeSignature and Set-AuthenticodeSignature which properly parse paths and don’t kill your pipeline and script when you hit a folder by accident, and default to using timestamping

  1. #Requires -version 2.0
  2. ## Authenticode.psm1 updated for PowerShell 2.0 (with time stamping)
  3. ####################################################################################################
  4. ## Wrappers for the Get-AuthenticodeSignature and Set-AuthenticodeSignature cmdlets
  5. ## These properly parse paths, so they don't kill your pipeline and script if you include a folder
  6. ##
  7. ## Usage:
  8. ## ls | Get-AuthenticodeSignature
  9. ##    Get all the signatures
  10. ##
  11. ## ls | Select-AuthenticodeSigned -Mine -Broken | Set-AuthenticodeSignature
  12. ##    Re-sign anything you signed before that has changed
  13. ##
  14. ## ls | Select-AuthenticodeSigned -NotMine -ValidOnly | Set-AuthenticodeSignature
  15. ##    Re-sign scripts that are hash-correct but not signed by me or by someone trusted
  16. ##
  17. ####################################################################################################
  18. ## History:
  19. ## 2.0 - Updated to work with PowerShell 2.0 RTM and add -TimeStampUrl support
  20. ## 1.7 - Modified the reading of certs to better support people who only have one :)
  21. ## 1.6 - Converted to work with CTP 3, and added function help comments
  22. ## 1.5 - Moved the default certificate setting into the module info Authenticode.psd1 file
  23. ##       Note: If you get this off PoshCode, you'll have to create it yourself, see below:
  24. ## 1.4 - Moved the default certificate setting into an external psd1 file.
  25. ## 1.3 - Fixed some bugs in If-Signed and renamed it to Select-AuthenticodeSigned
  26. ##     - Added -MineOnly and -NotMineOnly switches to Select-AuthenticodeSigned
  27. ## 1.2 - Added a hack workaround to make it appear as though we can sign and check PSM1 files
  28. ##       It's important to remember that the signatures are NOT checked by PowerShell yet...
  29. ## 1.1 - Added a filter "If-Signed" that can be used like: ls | If-Signed
  30. ##     - With optional switches: ValidOnly, InvalidOnly, BrokenOnly, TrustedOnly, UnsignedOnly
  31. ##     - commented out the default Certificate which won't work for "you"
  32. ## 1.0 - first working version, includes wrappers for Get and Set
  33. ##
  34. ####################################################################################################
  35. ## README! README! README! README! #################################################################
  36. ## README! README! README! README! #################################################################
  37. ##
  38. ## You should set the location to your default signing certificate. The permanent way to do that is
  39. ## to modify (or create) the .psd1 file to set the PrivateData member variable. Otherwise you'll be
  40. ## prompted to provide a cert path whenever you try to sign a script without passing a certificate.
  41. ##
  42. ## The PrivateData variable should point at your code-signing certificate either with a full path
  43. ## or with the THUMBPRINT of a certificate you have available in your Cert:\CurrentUser\My\ provider
  44. ##
  45. ## EG:
  46. ##      4F8842037D878C1FCDC6FD1313B200449716C353
  47. ## OR:
  48. ##      "Cert:\CurrentUser\My\4F8842037D878C1FCDC6FD1313B200449716C353"
  49. ## OR a file name:
  50. ##      "C:\Users\Joel\Documents\WindowsPowerShell\PoshCerts\Joel-Bennett_Code-Signing.pfx"
  51. ##
  52. ## The simplest thing is to just update the PSD1
  53. ##
  54. ##    New-ModuleManifest .\Authenticode.psd1 -Nested .\Authenticode.psm1 `
  55. ##    -Author "" -COmpany "" -Copy "" -Desc "" `
  56. ##    -Types @() -Formats @() -RequiredMod @() -RequiredAs @() -Other @() `
  57. ##    -PrivateData 4F8842037D878C1FCDC6FD1313B200449716C353
  58. ##
  59. ####################################################################################################
  60.  
  61. ####################################################################################################
  62. function Get-UserCertificate {
  63. <#.SYNOPSIS
  64.  Gets the user's default signing certificate so we don't have to ask them over and over...
  65. .DESCRIPTION
  66.  The Get-UserCertificate function retrieves and returns a certificate from the user. It also stores the certificate so it can be reused without re-querying for the location and/or password ...
  67. .RETURNVALUE
  68.  An X509Certificate2 suitable for code-signing
  69. #>
  70. [CmdletBinding()]
  71. Param()
  72.    Write-Debug "PrivateData: $($ExecutionContext.SessionState.Module | fl * | Out-String)"
  73.    $UserCertificate = Get-AuthenticodeCertificate $ExecutionContext.SessionState.Module.PrivateData
  74.    $ExecutionContext.SessionState.Module.PrivateData = $UserCertificate.Thumbprint
  75.    return $UserCertificate
  76. }
  77.  
  78. function Get-AuthenticodeCertificate {
  79. [CmdletBinding()]
  80. PARAM (
  81.    $Name = $ExecutionContext.SessionState.Module.PrivateData
  82. )
  83.  
  84. BEGIN {
  85.    if(!$ExecutionContext.SessionState.Module.PrivateData -and $Name) {
  86.       $ExecutionContext.SessionState.Module.PrivateData = $Name
  87.    }
  88. }
  89.  
  90. PROCESS {
  91.    trap {
  92.       Write-Host "The authenticode script module requires configuration to function fully!"
  93.       Write-Host
  94.       Write-Host "You must put the path to your default signing certificate in the module metadata"`
  95.                  "file before you can use the module's Set-Authenticode cmdlet or to the 'mine'"`
  96.                  "feature of the Select-AuthenticodeSigned or Test-AuthenticodeSignature. To set it up, you can do this:"
  97.       Write-Host
  98.       Write-Host "PrivateData = 'C:\Users\${Env:UserName}\Documents\WindowsPowerShell\PoshCerts\Code-Signing.pfx'"
  99.       Write-Host
  100.       Write-Host "If you load your certificate into your 'CurrentUser\My' store, or put the .pfx file"`
  101.                  "into the folder with the Authenthenticode module script, you can just specify it's"`
  102.                  "thumprint or filename, respectively. Otherwise, it should be a full path."
  103.       Write-Error $_
  104.       return      
  105.    }
  106.    # Import-LocalizedData -bindingVariable CertificatePath -EA "STOP"
  107.    if(!$Name) {
  108.       $certs = ls Cert:\CurrentUser\My
  109.       if($certs.Count) {
  110.          Write-Host "You have $($certs.Count) certs in your local cert storage which you can specify by Thumbprint:" -fore cyan
  111.          $certs | Out-Host
  112.       }
  113.       $Name = $(Read-Host "Please specify a user certificate")
  114.    }
  115.    if($Name -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
  116.       Write-Debug "CertificatePath: $Name"
  117.       $ResolvedPath = $Null
  118.       $ResolvedPath = Resolve-Path $Name -ErrorAction "SilentlyContinue"
  119.       if(!$ResolvedPath -or !(Test-Path $ResolvedPath -ErrorAction "SilentlyContinue")) {
  120.          Write-Debug "Not a full path: $ResolvedPath"
  121.          $ResolvedPath = Resolve-Path (Join-Path $PsScriptRoot $Name -ErrorAction "SilentlyContinue") -ErrorAction "SilentlyContinue"
  122.       }
  123.       if(!$ResolvedPath -or !(Test-Path $ResolvedPath -ErrorAction "SilentlyContinue")) {
  124.          Write-Debug "Not a file Path: $ResolvedPath"
  125.          $ResolvedPath = Resolve-Path (Join-Path "Cert:\CurrentUser\My" $("$Name".ToUpper()) -ErrorAction "SilentlyContinue") -ErrorAction "SilentlyContinue"
  126.          Write-Debug "ResolvedPath: $ResolvedPath"
  127.       }
  128.  
  129.       $Certificate = get-item $ResolvedPath -ErrorAction "SilentlyContinue"
  130.       if($Certificate -is [System.IO.FileInfo]) {
  131.          $Certificate = Get-PfxCertificate $Certificate -ErrorAction "SilentlyContinue"
  132.       }
  133.       Write-Verbose "Certificate: $($Certificate | Out-String)"
  134.       $Name = $Certificate
  135.    }
  136.    return $Name
  137. }
  138. }
  139.  
  140. ####################################################################################################
  141. function Test-AuthenticodeSignature {
  142. <#.SYNOPSIS
  143.  Tests a script signature to see if it is valid, or at least unaltered.
  144. .DESCRIPTION
  145.  The Test-AuthenticodeSignature function processes the output of Get-AuthenticodeSignature to determine if it
  146.  is Valid, OR **unaltered** and signed by the user's certificate
  147. .NOTES
  148.  Test-AuthenticodeSignature returns TRUE even if the root CA certificate can't be verified, as long as the signing certificate's thumbnail matches the one specified by Get-UserCertificate.
  149. .EXAMPLE
  150.    ls *.ps1 | Get-AuthenticodeSignature | Where {Test-AuthenticodeSignature $_}
  151.  To get the signature reports for all the scripts that we consider safely signed.
  152. .EXAMPLE
  153.    ls | ? { gas $_ | Test-AuthenticodeSignature }
  154.  List all the valid signed scripts (or scripts signed by our cert)
  155. .INPUTTYPE
  156.   System.Management.Automation.Signature
  157. .PARAMETER Signature
  158.   Specifies the signature object to test. This should be the output of Get-AuthenticodeSignature.
  159. .PARAMETER ForceValid
  160.   Switch parameter, forces the signature to be valid -- otherwise, even if the certificate chain can't be verified, we will accept the cert which matches the "user" certificate (see Get-UserCertificate).
  161.   Aliases                      Valid
  162. .RETURNVALUE
  163.    Boolean value representing whether the script's signature is valid, or YOUR certificate
  164. ##################################################################################################
  165. #>
  166. [CmdletBinding()]
  167. PARAM (
  168.    [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
  169. #  The signature to test.
  170.    $Signature
  171. ,
  172.    [Alias("Valid")]
  173.    [Switch]$ForceValid
  174. )
  175.  
  176. return ( $Signature.Status -eq "Valid" -or
  177.       ( !$ForceValid -and
  178.          ($Signature.Status -eq "UnknownError") -and
  179.          ($_.SignerCertificate.Thumbprint -eq $(Get-UserCertificate).Thumbprint)
  180.       ) )
  181. }
  182.  
  183. ####################################################################################################
  184. function Set-AuthenticodeSignature {
  185. <#.SYNOPSIS
  186.    Adds an Authenticode signature to a Windows PowerShell script or other file.
  187. .DESCRIPTION
  188.    The Set-AuthenticodeSignature function adds an Authenticode signature to any file that supports Subject Interface Package (SIP).
  189.  
  190.    In a Windows PowerShell script file, the signature takes the form of a block of text that indicates the end of the instructions that are executed in the script. If there is a signature  in the file when this cmdlet runs, that signature is removed.
  191. .NOTES
  192.    After the certificate has been validated, but before a signature is added to the file, the function checks the value of the $SigningApproved preference variable. If this variable is not set, or has a value other than TRUE, you are prompted to confirm the signing of the script.
  193.  
  194.    When specifying multiple values for a parameter, use commas to separate the values. For example, "<parameter-name> <value1>, <value2>".
  195. .EXAMPLE
  196.    ls *.ps1 | Set-AuthenticodeSignature -Certificate $Certificate
  197.    
  198.    To sign all of the files with the specified certificate
  199. .EXAMPLE
  200.    ls *.ps1,*.psm1,*.psd1 | Get-AuthenticodeSignature | Where {!(Test-AuthenticodeSignature $_ -Valid)} | gci | Set-AuthenticodeSignature
  201.  
  202.    List all the script files, and get and test their signatures, and then sign all of the ones that are not valid, using the user's default certificate.
  203. .INPUTTYPE
  204.    String. You can pipe a file path to Set-AuthenticodeSignature.
  205. .PARAMETER FilePath
  206.    Specifies the path to a file that is being signed.
  207.    Aliases                      Path, FullName
  208. .PARAMETER Certificate
  209.    Specifies the certificate that will be used to sign the script or file. Enter a variable that stores an object representing the certificate or an expression that gets the certificate.
  210.  
  211.    To find a certificate, use Get-PfxCertificate or use the Get-ChildItem cmdlet in the Certificate (Cert:) drive. If the certificate is not valid or does not have code-signing authority, the command fails.
  212. .PARAMETER Force
  213.    Allows the cmdlet to append a signature to a read-only file. Even using the Force parameter, the cmdlet cannot override security restrictions.
  214. .Parameter HashAlgorithm
  215.    Specifies the hashing algorithm that Windows uses to compute the digital signature for the file. The default is SHA1, which is the Windows default hashing algorithm.
  216.  
  217.    Files that are signed with a different hashing algorithm might not be recognized on other systems.
  218. .PARAMETER IncludeChain
  219.    Determines which certificates in the certificate trust chain are included in the digital signature. "NotRoot" is the default.
  220.  
  221.    Valid values are:
  222.  
  223.    -- Signer: Includes only the signer's certificate.
  224.  
  225.    -- NotRoot: Includes all of the certificates in the certificate chain, except for the root authority.
  226.  
  227.    --All: Includes all the certificates in the certificate chain.
  228.  
  229. .PARAMETER TimestampServer
  230.    Uses the specified time stamp server to add a time stamp to the signature. Type the URL of the time stamp server as a string.
  231.    Defaults to Verisign's server: http://timestamp.verisign.com/scripts/timstamp.dll
  232.  
  233.    The time stamp represents the exact time that the certificate was added to the file. A time stamp prevents the script from failing if the certificate expires because users and programs can verify that the certificate was valid atthe time of signing.
  234. .RETURNVALUE
  235.    System.Management.Automation.Signature
  236. ###################################################################################################>
  237. [CmdletBinding()]
  238. PARAM (
  239.    [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)]
  240.    [Alias("FullName","Path")]
  241.    [ValidateScript({
  242.       if((resolve-path $_).Provider.Name -ne "FileSystem") {
  243.          throw "Specified Path is not in the FileSystem: '$_'"
  244.       }
  245.       return $true
  246.    })]
  247.    [string[]]
  248.    $FilePath
  249. ,  
  250.    [Parameter(Position=2, Mandatory=$false)]
  251.    $Certificate = $(Get-UserCertificate)
  252. ,
  253.    [Switch]$Force
  254. ,
  255.    [ValidateSet("SHA","MD5","SHA1","SHA256","SHA384","SHA512")]
  256.    [String]$HashAlgorithm #="SHA1"
  257. ,
  258.    [ValidateSet("Signer","NotRoot","All")]
  259.    [String]$IncludeChain #="NotRoot"
  260. ,
  261.    [String]$TimestampServer = "http://timestamp.verisign.com/scripts/timstamp.dll"
  262. )
  263. BEGIN {
  264.    if($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
  265.       $Certificate = Get-AuthenticodeCertificate $Certificate
  266.    }
  267.    $PSBoundParameters["Certificate"] = $Certificate
  268. }
  269. PROCESS {
  270.    Write-Verbose "Set Authenticode Signature on $FilePath with $($Certificate | Out-String)"
  271.    $PSBoundParameters["FilePath"] = $FilePath = $(Resolve-Path $FilePath)
  272.    if(Test-Path $FilePath -Type Leaf) {
  273.       Microsoft.PowerShell.Security\Set-AuthenticodeSignature @PSBoundParameters
  274.    } else {
  275.       Write-Warning "Cannot sign folders: '$FilePath'"
  276.    }
  277. }
  278. }
  279.  
  280. ####################################################################################################
  281. function Get-AuthenticodeSignature {
  282. <#.SYNOPSIS
  283.    Gets information about the Authenticode signature in a file.
  284. .DESCRIPTION
  285.    The Get-AuthenticodeSignature function gets information about the Authenticode signature in a file. If the file is not signed, the information is retrieved, but the fields are blank.
  286. .NOTES
  287.    For information about Authenticode signatures in Windows PowerShell, type "get-help About_Signing".
  288.  
  289.    When specifying multiple values for a parameter, use commas to separate the values. For example, "-<parameter-name> <value1>, <value2>".
  290. .EXAMPLE
  291.    Get-AuthenticodeSignature script.ps1
  292.    
  293.    To get the signature information about the script.ps1 script file.
  294. .EXAMPLE
  295.    ls *.ps1,*.psm1,*.psd1 | Get-AuthenticodeSignature
  296.    
  297.    Get the signature information for all the script and data files
  298. .EXAMPLE
  299.    ls *.ps1,*.psm1,*.psd1 | Get-AuthenticodeSignature | Where {!(Test-AuthenticodeSignature $_ -Valid)} | gci | Set-AuthenticodeSignature
  300.  
  301.    This command gets information about the Authenticode signature in all of the script and module files, and tests the signatures, then signs all of the ones that are not valid.
  302. .INPUTTYPE
  303.    String. You can pipe the path to a file to Get-AuthenticodeSignature.
  304. .PARAMETER FilePath
  305.    The path to the file being examined. Wildcards are permitted, but they must lead to a single file. The parameter name ("-FilePath") is optional.
  306.    Aliases                      Path, FullName
  307. .RETURNVALUE
  308.    System.Management.Automation.Signature
  309. ###################################################################################################>
  310. [CmdletBinding()]
  311. PARAM (
  312.    [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
  313.    [Alias("FullName","Path")]
  314.    [ValidateScript({
  315.       if((resolve-path $_).Provider.Name -ne "FileSystem") {
  316.          throw "Specified Path is not in the FileSystem: '$_'"
  317.       }
  318.       if(!(Test-Path -PathType Leaf $_)) {
  319.          throw "Specified Path is not a File: '$_'"
  320.       }
  321.       return $true
  322.    })]
  323.    [string[]]
  324.    $FilePath
  325. )
  326.  
  327. PROCESS {
  328.    Microsoft.PowerShell.Security\Get-AuthenticodeSignature -FilePath $FilePath
  329. }
  330. }
  331.  
  332. ####################################################################################################
  333. function Select-AuthenticodeSigned {
  334. <#.SYNOPSIS
  335.    Select files based on the status of their Authenticode Signature.
  336. .DESCRIPTION
  337.    The Select-AuthenticodeSigned function filters files on the pipeline based on the state of their authenticode signature.
  338. .NOTES
  339.    For information about Authenticode signatures in Windows PowerShell, type "get-help About_Signing".
  340.  
  341.    When specifying multiple values for a parameter, use commas to separate the values. For example, "-<parameter-name> <value1>, <value2>".
  342. .EXAMPLE
  343.    ls *.ps1,*.ps[dm]1 | Select-AuthenticodeSigned
  344.    
  345.    To get the signature information about the script.ps1 script file.
  346. .EXAMPLE
  347.    ls *.ps1,*.psm1,*.psd1 | Get-AuthenticodeSignature
  348.    
  349.    Get the signature information for all the script and data files
  350. .EXAMPLE
  351.    ls *.ps1,*.psm1,*.psd1 | Get-AuthenticodeSignature | Where {!(Test-AuthenticodeSignature $_ -Valid)} | gci | Set-AuthenticodeSignature
  352.  
  353.    This command gets information about the Authenticode signature in all of the script and module files, and tests the signatures, then signs all of the ones that are not valid.
  354. .INPUTTYPE
  355.    String. You can pipe the path to a file to Get-AuthenticodeSignature.
  356. .PARAMETER FilePath
  357.    The path to the file being examined. Wildcards are permitted, but they must lead to a single file. The parameter name ("-FilePath") is optional.
  358.    Aliases                      Path, FullName
  359. .RETURNVALUE
  360.    System.Management.Automation.Signature
  361. ###################################################################################################>
  362. [CmdletBinding()]
  363. PARAM (
  364.    [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
  365.    [Alias("FullName")]
  366.    [ValidateScript({
  367.       if((resolve-path $_).Provider.Name -ne "FileSystem") {
  368.          throw "Specified Path is not in the FileSystem: '$_'"
  369.       }
  370.       return $true
  371.    })]
  372.    [string[]]
  373.    $FilePath
  374. ,
  375.    [Parameter()]
  376.    # Return only files that are signed with the users' certificate (as returned by Get-UserCertificate).
  377.    [switch]$MineOnly
  378. ,
  379.    [Parameter()]
  380.    # Return only files that are NOT signed with the users' certificate (as returned by Get-UserCertificate).
  381.    [switch]$NotMineOnly
  382. ,
  383.    [Parameter()]
  384.    [Alias("HashMismatch")]
  385.    # Return only files with signatures that are broken (where the file has been edited, and the hash doesn't match).
  386.    [switch]$BrokenOnly
  387. ,
  388.    [Parameter()]
  389.    # Returns the files that are Valid OR signed with the users' certificate (as returned by Get-UserCertificate).
  390.    #
  391.    # That is, TrustedOnly returns files returned by -ValidOnly OR -MineOnly (if you specify both parameters, you get only files that are BOTH -ValidOnly AND -MineOnly)
  392.    [switch]$TrustedOnly
  393. ,
  394.    [Parameter()]
  395.    # Return only files that are "Valid": This means signed with any cert where the certificate chain is verifiable to a trusted root certificate.  This may or may not include files signed with the user's certificate.
  396.    [switch]$ValidOnly
  397. ,
  398.    [Parameter()]
  399.    # Return only files that doesn't have a "Valid" signature, which includes files that aren't signed, or that have a hash mismatch, or are signed by untrusted certs (possibly including the user's certificate).
  400.    [switch]$InvalidOnly
  401. ,
  402.    [Parameter()]
  403.    # Return only signable files that aren't signed at all. That is, only files that support Subject Interface Package (SIP) but aren't signed.
  404.    [switch]$UnsignedOnly
  405.  
  406. )
  407. PROCESS {
  408.    if(!(Test-Path -PathType Leaf $FilePath)) {
  409.       # if($ErrorAction -ne "SilentlyContinue") {
  410.       #    Write-Error "Specified Path is not a File: '$FilePath'"
  411.       # }
  412.    } else {
  413.  
  414.       foreach($sig in Get-AuthenticodeSignature -FilePath $FilePath) {
  415.      
  416.       # Broken only returns ONLY things which are HashMismatch
  417.       if($BrokenOnly   -and $sig.Status -ne "HashMismatch")
  418.       {
  419.          Write-Debug "$($sig.Status) - Not Broken: $FilePath"
  420.          return
  421.       }
  422.      
  423.       # Trusted only returns ONLY things which are Valid
  424.       if($ValidOnly    -and $sig.Status -ne "Valid")
  425.       {
  426.          Write-Debug "$($sig.Status) - Not Trusted: $FilePath"
  427.          return
  428.       }
  429.      
  430.       # AllValid returns only things that are SIGNED and not HashMismatch
  431.       if($TrustedOnly  -and (($sig.Status -ne "HashMismatch") -or !$sig.SignerCertificate) )
  432.       {
  433.          Write-Debug "$($sig.Status) - Not Valid: $FilePath"
  434.          return
  435.       }
  436.      
  437.       # NOTValid returns only things that are SIGNED and Valid
  438.       if($InvalidOnly  -and ($sig.Status -eq "Valid"))
  439.       {
  440.          Write-Debug "$($sig.Status) - Valid: $FilePath"
  441.          return
  442.       }
  443.      
  444.       # Unsigned returns only things that aren't signed
  445.       # NOTE: we don't test using NotSigned, because that's only set for .ps1 or .exe files??
  446.       if($UnsignedOnly -and $sig.SignerCertificate )
  447.       {
  448.          Write-Debug "$($sig.Status) - Signed: $FilePath"
  449.          return
  450.       }
  451.      
  452.       # Mine returns only things that were signed by MY CertificateThumbprint
  453.       if($MineOnly     -and (!($sig.SignerCertificate) -or ($sig.SignerCertificate.Thumbprint -ne $((Get-UserCertificate).Thumbprint))))
  454.       {
  455.          Write-Debug "Originally signed by someone else, thumbprint: $($sig.SignerCertificate.Thumbprint)"
  456.          Write-Debug "Does not match your default certificate print: $((Get-UserCertificate).Thumbprint)"
  457.          Write-Debug "     $FilePath"
  458.          return
  459.       }
  460.  
  461.       # NotMine returns only things that were signed by MY CertificateThumbprint
  462.       if($NotMineOnly  -and (!($sig.SignerCertificate) -or ($sig.SignerCertificate.Thumbprint -eq $((Get-UserCertificate).Thumbprint))))
  463.       {
  464.          if($sig.SignerCertificate) {
  465.             Write-Debug "Originally signed by you, thumbprint: $($sig.SignerCertificate.Thumbprint)"
  466.             Write-Debug "Matches your default certificate print: $((Get-UserCertificate).Thumbprint)"
  467.             Write-Debug "     $FilePath"
  468.          }
  469.          return
  470.       }
  471.      
  472.       if(!$BrokenOnly  -and !$TrustedOnly -and !$ValidOnly -and !$InvalidOnly -and !$UnsignedOnly -and !($sig.SignerCertificate) )
  473.       {
  474.          Write-Debug "$($sig.Status) - Not Signed: $FilePath"
  475.          return
  476.       }
  477.      
  478.       get-childItem $sig.Path
  479.    }}
  480. }
  481. }
  482. Set-Alias gas          Get-AuthenticodeSignature -Description "Authenticode Module Alias"
  483. Set-Alias sas          Set-AuthenticodeSignature -Description "Authenticode Module Alias"
  484. Set-Alias sign         Set-AuthenticodeSignature -Description "Authenticode Module Alias"
  485.  
  486. Export-ModuleMember -Alias gas,sas,sign -Function Set-AuthenticodeSignature, Get-AuthenticodeSignature, Test-AuthenticodeSignature, Select-AuthenticodeSigned, Get-UserCertificate
  487.                    
  488.  
  489. # SIG # Begin signature block
  490. # MIIRDAYJKoZIhvcNAQcCoIIQ/TCCEPkCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  491. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  492. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUGC9Hxzt7IltBOFHwDqZdsid6
  493. # yBSggg5CMIIHBjCCBO6gAwIBAgIBFTANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQG
  494. # EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
  495. # Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
  496. # dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjIwMTQ1WhcNMTIxMDI0MjIw
  497. # MTQ1WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
  498. # BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
  499. # BAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgT2JqZWN0
  500. # IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyiOLIjUemqAbPJ1J
  501. # 0D8MlzgWKbr4fYlbRVjvhHDtfhFN6RQxq0PjTQxRgWzwFQNKJCdU5ftKoM5N4YSj
  502. # Id6ZNavcSa6/McVnhDAQm+8H3HWoD030NVOxbjgD/Ih3HaV3/z9159nnvyxQEckR
  503. # ZfpJB2Kfk6aHqW3JnSvRe+XVZSufDVCe/vtxGSEwKCaNrsLc9pboUoYIC3oyzWoU
  504. # TZ65+c0H4paR8c8eK/mC914mBo6N0dQ512/bkSdaeY9YaQpGtW/h/W/FkbQRT3sC
  505. # pttLVlIjnkuY4r9+zvqhToPjxcfDYEf+XD8VGkAqle8Aa8hQ+M1qGdQjAye8OzbV
  506. # uUOw7wIDAQABo4ICfzCCAnswDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYD
  507. # VR0OBBYEFNBOD0CZbLhLGW87KLjg44gHNKq3MIGoBgNVHSMEgaAwgZ2AFE4L7xqk
  508. # QFulF2mHMMo0aEPQQa7yoYGBpH8wfTELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0
  509. # YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRl
  510. # IFNpZ25pbmcxKTAnBgNVBAMTIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9y
  511. # aXR5ggEBMAkGA1UdEgQCMAAwPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzAChiFo
  512. # dHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9zZnNjYS5jcnQwYAYDVR0fBFkwVzAsoCqg
  513. # KIYmaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3Nmc2NhLWNybC5jcmwwJ6AloCOG
  514. # IWh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL3Nmc2NhLmNybDCBggYDVR0gBHsweTB3
  515. # BgsrBgEEAYG1NwEBBTBoMC8GCCsGAQUFBwIBFiNodHRwOi8vY2VydC5zdGFydGNv
  516. # bS5vcmcvcG9saWN5LnBkZjA1BggrBgEFBQcCARYpaHR0cDovL2NlcnQuc3RhcnRj
  517. # b20ub3JnL2ludGVybWVkaWF0ZS5wZGYwEQYJYIZIAYb4QgEBBAQDAgABMFAGCWCG
  518. # SAGG+EIBDQRDFkFTdGFydENvbSBDbGFzcyAyIFByaW1hcnkgSW50ZXJtZWRpYXRl
  519. # IE9iamVjdCBTaWduaW5nIENlcnRpZmljYXRlczANBgkqhkiG9w0BAQUFAAOCAgEA
  520. # UKLQmPRwQHAAtm7slo01fXugNxp/gTJY3+aIhhs8Gog+IwIsT75Q1kLsnnfUQfbF
  521. # pl/UrlB02FQSOZ+4Dn2S9l7ewXQhIXwtuwKiQg3NdD9tuA8Ohu3eY1cPl7eOaY4Q
  522. # qvqSj8+Ol7f0Zp6qTGiRZxCv/aNPIbp0v3rD9GdhGtPvKLRS0CqKgsH2nweovk4h
  523. # fXjRQjp5N5PnfBW1X2DCSTqmjweWhlleQ2KDg93W61Tw6M6yGJAGG3GnzbwadF9B
  524. # UW88WcRsnOWHIu1473bNKBnf1OKxxAQ1/3WwJGZWJ5UxhCpA+wr+l+NbHP5x5XZ5
  525. # 8xhhxu7WQ7rwIDj8d/lGU9A6EaeXv3NwwcbIo/aou5v9y94+leAYqr8bbBNAFTX1
  526. # pTxQJylfsKrkB8EOIx+Zrlwa0WE32AgxaKhWAGho/Ph7d6UXUSn5bw2+usvhdkW4
  527. # npUoxAk3RhT3+nupi1fic4NG7iQG84PZ2bbS5YxOmaIIsIAxclf25FwssWjieMwV
  528. # 0k91nlzUFB1HQMuE6TurAakS7tnIKTJ+ZWJBDduUbcD1094X38OvMO/++H5S45Ki
  529. # 3r/13YTm0AWGOvMFkEAF8LbuEyecKTaJMTiNRfBGMgnqGBfqiOnzxxRVNOw2hSQp
  530. # 0B+C9Ij/q375z3iAIYCbKUd/5SSELcmlLl+BuNknXE0wggc0MIIGHKADAgECAgFR
  531. # MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRD
  532. # b20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2ln
  533. # bmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3MgMiBQcmltYXJ5IEludGVybWVk
  534. # aWF0ZSBPYmplY3QgQ0EwHhcNMDkxMTExMDAwMDAxWhcNMTExMTExMDYyODQzWjCB
  535. # qDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMRcwFQYDVQQHEw5XZXN0
  536. # IEhlbnJpZXR0YTEtMCsGA1UECxMkU3RhcnRDb20gVmVyaWZpZWQgQ2VydGlmaWNh
  537. # dGUgTWVtYmVyMRUwEwYDVQQDEwxKb2VsIEJlbm5ldHQxJzAlBgkqhkiG9w0BCQEW
  538. # GEpheWt1bEBIdWRkbGVkTWFzc2VzLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
  539. # ADCCAQoCggEBAMfjItJjMWVaQTECvnV/swHQP0FTYUvRizKzUubGNDNaj7v2dAWC
  540. # rAA+XE0lt9JBNFtCCcweDzphbWU/AAY0sEPuKobV5UGOLJvW/DcHAWdNB/wRrrUD
  541. # dpcsapQ0IxxKqpRTrbu5UGt442+6hJReGTnHzQbX8FoGMjt7sLrHc3a4wTH3nMc0
  542. # U/TznE13azfdtPOfrGzhyBFJw2H1g5Ag2cmWkwsQrOBU+kFbD4UjxIyus/Z9UQT2
  543. # R7bI2R4L/vWM3UiNj4M8LIuN6UaIrh5SA8q/UvDumvMzjkxGHNpPZsAPaOS+RNmU
  544. # Go6X83jijjbL39PJtMX+doCjS/lnclws5lUCAwEAAaOCA4EwggN9MAkGA1UdEwQC
  545. # MAAwDgYDVR0PAQH/BAQDAgeAMDoGA1UdJQEB/wQwMC4GCCsGAQUFBwMDBgorBgEE
  546. # AYI3AgEVBgorBgEEAYI3AgEWBgorBgEEAYI3CgMNMB0GA1UdDgQWBBR5tWPGCLNQ
  547. # yCXI5fY5ViayKj6xATCBqAYDVR0jBIGgMIGdgBTQTg9AmWy4SxlvOyi44OOIBzSq
  548. # t6GBgaR/MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSsw
  549. # KQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYD
  550. # VQQDEyBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eYIBFTCCAUIGA1Ud
  551. # IASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgEwggEgMC4GCCsGAQUFBwIBFiJodHRw
  552. # Oi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIBFihodHRw
  553. # Oi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3BggrBgEFBQcC
  554. # AjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJpbGl0eSwg
  555. # c2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3RhcnRDb20g
  556. # Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBhdCBodHRw
  557. # Oi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGMGA1UdHwRcMFowK6ApoCeG
  558. # JWh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydGMyLWNybC5jcmwwK6ApoCeGJWh0
  559. # dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2NydGMyLWNybC5jcmwwgYkGCCsGAQUFBwEB
  560. # BH0wezA3BggrBgEFBQcwAYYraHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9j
  561. # bGFzczIvY29kZS9jYTBABggrBgEFBQcwAoY0aHR0cDovL3d3dy5zdGFydHNzbC5j
  562. # b20vY2VydHMvc3ViLmNsYXNzMi5jb2RlLmNhLmNydDAjBgNVHRIEHDAahhhodHRw
  563. # Oi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEBACY+J88ZYr5A
  564. # 6lYz/L4OGILS7b6VQQYn2w9Wl0OEQEwlTq3bMYinNoExqCxXhFCHOi58X6r8wdHb
  565. # E6mU8h40vNYBI9KpvLjAn6Dy1nQEwfvAfYAL8WMwyZykPYIS/y2Dq3SB2XvzFy27
  566. # zpIdla8qIShuNlX22FQL6/FKBriy96jcdGEYF9rbsuWku04NqSLjNM47wCAzLs/n
  567. # FXpdcBL1R6QEK4MRhcEL9Ho4hGbVvmJES64IY+P3xlV2vlEJkk3etB/FpNDOQf8j
  568. # RTXrrBUYFvOCv20uHsRpc3kFduXt3HRV2QnAlRpG26YpZN4xvgqSGXUeqRceef7D
  569. # dm4iTdHK5tIxggI0MIICMAIBATCBkjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoT
  570. # DVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmlj
  571. # YXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJ
  572. # bnRlcm1lZGlhdGUgT2JqZWN0IENBAgFRMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3
  573. # AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
  574. # AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEWMCMGCSqGSIb3DQEJBDEWBBS8GjyBUI2Q
  575. # ToTKzbh1b32xYCH55jANBgkqhkiG9w0BAQEFAASCAQCOkFKmiRUIVVrwHXJPrlhH
  576. # 5mahN+xXjcPYH135ABo/+T2Nx42eA6Ekl3NRoyo/NJp9w0y5s5bQmLUhwp926ff2
  577. # LofOumK0qzcL8/dZ/mct3xJqqpX9O+WWCwFxFz4nj+X8R8OaQfMNBPgDL37a4ZEK
  578. # 7U52The31AgUCpQByUlJDE4/bf5egTbMXl7T+CvojAffxyjAljHAiYsT9b/GSFHz
  579. # nq8iwCskpM9K7Oy3PVAv0ieNR7KodovxNZZm5wkD914OZyGbCjqb08hNvXiSJcEj
  580. # O6a2gAYQHL+ic0XFTO7WKQv5TxF9bN0faSz2d1lysDbhfD3349oKaUJd1OjOHoeT
  581. # SIG # End signature block

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me