Signtool allows me to sign code but Set-AuthenticodeSignature says the "certificate is not suitable for code signing"

Scott Chamberlain picture Scott Chamberlain · Jun 7, 2012 · Viewed 14.1k times · Source

I have a self-signed code signing certificate, made with the directions from this answer, that works fine when used with signtool.exe, however if I try to sign using Set-AuthenticodeSignature, it fails.

Why can I sign using signtool, but not using Set-AuthenticodeSignature?

  • signtool:
    Signtool sign /v /n "VetWeb" SetupRDPPermissions.ps1
    
      The following certificate was selected:
        Issued to: VetWeb
        Issued by: VetWeb CA
        Expires:   Sat Dec 31 18:59:59 2039
        SHA1 hash: 84136EBF8D2603C2CD6668C955F920C6C6482EE4
    
      Done Adding Additional Store
      Successfully signed: SetupRDPPermissions.ps1
    
      Number of files successfully Signed: 1
      Number of warnings: 0
    

  • Set-AuthenticodeSignature:
    $cert = @(Get-Childitem cert:\CurrentUser\My | Where-Object -FilterScript {$_.Subject -eq 'CN=VetWeb'})[0]
    
    Set-AuthenticodeSignature SetupRDPPermissions.ps1 $cert
    
      Set-AuthenticodeSignature : Cannot sign code. The specified certificate is not suitable for code signing.
        At line:1 char:26
        + Set-AuthenticodeSignature <<<<  SetupRDPPermissions.ps1 $cert
          + CategoryInfo          : InvalidArgument: (:) [Set-AuthenticodeSignature], PSArgumentException
          + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.SetAuthenticodeSignatureCommand
    
    • Get-Childitem cert:\CurrentUser\My -CodeSigningCert returns no results

  •  $cert | Format-List *
    
       PSPath             : Microsoft.PowerShell.Security\Certificate::CurrentUser\My\84136EBF8D2603C2CD6668C955F920C6C6482EE4
       PSParentPath       : Microsoft.PowerShell.Security\Certificate::CurrentUser\My
       PSChildName        : 84136EBF8D2603C2CD6668C955F920C6C6482EE4
       PSDrive            : cert
       PSProvider         : Microsoft.PowerShell.Security\Certificate
       PSIsContainer      : False
       Archived           : False
       Extensions         : {System.Security.Cryptography.Oid}
       FriendlyName       :
       IssuerName         : System.Security.Cryptography.X509Certificates.X500DistinguishedName
       NotAfter           : 12/31/2039 5:59:59 PM
       NotBefore          : 6/1/2012 1:49:31 PM
       HasPrivateKey      : True
       PrivateKey         : System.Security.Cryptography.RSACryptoServiceProvider
       PublicKey          : System.Security.Cryptography.X509Certificates.PublicKey
       RawData            : {48, 130, 1, 235...}
       SerialNumber       : CF330347F35AC0B4427AFFA82DB51238
       SubjectName        : System.Security.Cryptography.X509Certificates.X500DistinguishedName
       SignatureAlgorithm : System.Security.Cryptography.Oid
       Thumbprint         : 84136EBF8D2603C2CD6668C955F920C6C6482EE4
       Version            : 3
       Handle             : 479608336
       Issuer             : CN=VetWeb CA
       Subject            : CN=VetWeb
    

Answer

Arpit Chauhan picture Arpit Chauhan · Sep 3, 2013

I had the same problem and the answer I figured out was that I had to create two certificates. First, a trusted root certificate authority using

makecert -n "CN=PowerShell Local Certificate Root" -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer -ss Root -sr localMachine

And then a personal certificate from the above certificate authority using

makecert -pe -n "CN=PowerShell User" -ss MY -a sha1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer

Once these are created, use

$cert = @(Get-ChildItem cert:\CurrentUser\My -CodeSigning)[0]

for signing (assuming you have only one codesigning certificate). For example, if the script's name is xyz.ps1, use this command in PowerShell

Set-AuthenticodeSignature path/to/xyz.ps1 $cert