如何在Windows上创建用于代码签名的自签名证书?

292

我该如何使用Windows SDK中的工具创建用于代码签名的自签名证书?


2
请查看此答案:https://dev59.com/T-k5XIcBkEYKwwoY59_h - Cartucho
7个回答

412

更新的答案

如果您正在使用以下版本或更高版本的Windows:Windows Server 2012、Windows Server 2012 R2或Windows 8.1,则MakeCert现在已经过时,微软建议使用PowerShell Cmdlet New-SelfSignedCertificate

如果您使用的是较旧的版本,例如Windows 7,则需要继续使用MakeCert或其他解决方案。一些人建议使用公钥基础设施PowerShell (PSPKI)模块

原始答案

虽然您可以一次性创建自签名代码签名证书(SPC-软件发布者证书),但我更喜欢按照以下步骤进行:

创建自签名证书颁发机构(CA)

makecert -r -pe -n "CN=My CA" -ss CA -sr CurrentUser ^
         -a sha256 -cy authority -sky signature -sv MyCA.pvk MyCA.cer

(^ = 允许批处理命令行换行)

这将创建一个自签名(-r)证书,带有可导出的私钥(-pe)。它被命名为“我的CA”,应该放在当前用户的CA存储中。我们正在使用SHA-256算法。该密钥用于签名(-sky)。

私钥应存储在MyCA.pvk文件中,证书应存储在MyCA.cer文件中。

导入CA证书

因为如果您不信任它,拥有CA证书就没有意义,您需要将其导入Windows证书存储中。您可以使用证书MMC插件,但也可以从命令行中执行:

certutil -user -addstore Root MyCA.cer

创建代码签名证书(SPC)

makecert -pe -n "CN=My SPC" -a sha256 -cy end ^
         -sky signature ^
         -ic MyCA.cer -iv MyCA.pvk ^
         -sv MySPC.pvk MySPC.cer

这基本上与上面的内容相同,但我们提供了一个发行者密钥和证书(使用-ic和-iv开关)。

我们还需要将证书和密钥转换为PFX文件:

pvk2pfx -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx

如果您正在使用密码,请使用以下内容。
pvk2pfx -pvk MySPC.pvk -spc MySPC.cer -pfx MySPC.pfx -po fess

如果您想保护PFX文件,请添加-po开关,否则PVK2PFX将创建一个没有密码短语的PFX文件。

使用证书签署代码

signtool sign /v /f MySPC.pfx ^
              /t http://timestamp.url MyExecutable.exe

(点击查看时间戳的重要性)

如果你将PFX文件导入证书存储中(可以使用PVKIMPRT或MMC snapin),则可以按照以下方式签署代码:

signtool sign /v /n "Me" /s SPC ^
              /t http://timestamp.url MyExecutable.exe

signtool /t 可能用到的时间戳URL地址:

  • http://timestamp.verisign.com/scripts/timstamp.dll
  • http://timestamp.globalsign.com/scripts/timstamp.dll
  • http://timestamp.comodoca.com/authenticode
  • http://timestamp.digicert.com

完整的微软文档

下载

MakeCert可以通过Visual Studio命令提示符获得。在Windows 7系统中,它可以从“VS2015 x64本机工具命令提示符”或“面向VS 2015开发人员的命令提示符”启动(可能都在同一个文件夹中)。


9
要在证书的电子邮件字段中填写内容,只需添加E=your@email。例如:makecert -pe -n "CN=My SPC,E=email@domain" ........ - Rob W
1
你不需要Extended Use key标志-eku 1.3.6.1.5.5.7.3.3吗?这样证书才能用于代码签名(我知道如果缺少它,PowerShell无法对脚本进行签名)。 - Scott Chamberlain
我注意到你在评论中提到你的示例适用于“测试/内部目的”,这种方法是否适用于分发?(允许足够的人点击“仍然运行”,以便Windows可以学习信任您的证书?) - Adam Phelps
1
@AdamPhelps,Windows不会“学习”信任您的证书。您的用户需要在根存储中安装CA证书。一般来说,这是一个不好的主意(因为根CA证书可以用于恶意目的)。但在企业场景中,这可能是有意义的。 - Roger Lipscombe
@RogerLipscombe 感谢您的帮助。我阅读了微软关于Smartscreen和代码签名的这篇文章,我理解它也适用于自签名代码。所以,为了澄清,这只适用于Authenticode CAs吗? - Adam Phelps
显示剩余14条评论

107

如答案所述,为了使用非弃用的方式对自己的脚本进行签名,应使用New-SelfSignedCertificate

  1. 生成密钥:
New-SelfSignedCertificate -DnsName email@yourdomain.com -Type CodeSigning -CertStoreLocation cert:\CurrentUser\My
  1. 导出不包含私钥的证书:
Export-Certificate -Cert (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[0] -FilePath code_signing.crt

如果你有多个证书,[0]可以让这个工作变得可行...显然,使索引与你想要使用的证书匹配...或者使用一种过滤的方式(通过指纹或颁发机构)。

  1. 将其作为受信任的发布者导入
Import-Certificate -FilePath .\code_signing.crt -Cert Cert:\CurrentUser\TrustedPublisher
  1. 将其导入为根证书颁发机构。
Import-Certificate -FilePath .\code_signing.crt -Cert Cert:\CurrentUser\Root
  1. 对脚本进行签名(假设脚本名为script.ps1,请根据实际路径进行修正)。
Set-AuthenticodeSignature .\script.ps1 -Certificate (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)

明显地,一旦您设置了密钥,您可以使用它来签署任何其他脚本。
您可以在此文章中获取更详细的信息和一些故障排除帮助。


1
除了 script.ps1 之外,一切都很棒,尽管对于每个人来说都应该是显而易见的,但我却不明白。这真是讨厌。我收到了“找不到文件 script.ps1”的错误提示,就是这样。 - user1908746
1
@Lara,感谢您的反馈。我已经添加了一些上下文信息,使得即使在低咖啡因状态下尝试也更容易理解。;-) - chaami
@chammi,非常感谢您的快速回复。但是,出于某种原因,我现在看到的只有空的灰色矩形。所有代码都从“代码”块中消失了。只显示灰色背景。 - user1908746
1
@Lara谢谢你的提示,我在编辑时没有仔细注意。现在StackOverflow对代码块的语法更加挑剔,需要在代码开始前加入一个新行。 - chaami
1
最后一个命令也应该有一个正确的索引: Set-AuthenticodeSignature ... -Certificate (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert)[1] - Spongebob Comrade
显示剩余2条评论

40

使用 Powershell 中的 New-SelfSignedCertificate 命令相当简单。

打开 Powershell 并运行下列三个命令:

  • 创建证书

  • $cert = New-SelfSignedCertificate -DnsName www.yourwebsite.com -Type CodeSigning -CertStoreLocation Cert:\CurrentUser\My
    
  • 设置密码

    $CertPassword = ConvertTo-SecureString -String "my_passowrd" -Force -AsPlainText
    
  • 导出它

    Export-PfxCertificate -Cert "cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath "d:\selfsigncert.pfx" -Password $CertPassword
    
  • 您的证书 selfsigncert.pfx 将位于 D:/


    可选步骤:您还需要将证书密码添加到系统环境变量中。通过在命令提示符中输入以下内容来执行此操作:

    setx CSC_KEY_PASSWORD "my_password"
    

    JerryGoyal,你知道如何将自签名证书转换为CA根受信任证书吗? - Mr Heelis
    4
    上一个脚本中有一个错别字。应该是Export-PfxCertificate -Cert "cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath "d:\selfsigncert.pfx" -Password $CertPassword - Arvind Sedha

    22

    Roger的回答非常有帮助。

    但是,我在使用过程中遇到了一些问题,一直收到红色的“Windows无法验证此驱动程序软件的发布者”错误对话框。关键是要安装测试根证书,方法如下:

    certutil -addstore Root Demo_CA.cer
    

    这是一份对 Roger 回答内容补充的翻译。

    以下是我使用的一份批处理文件(不包含我的 .inf 文件)。 它展示了如何从头到尾完成所有操作,完全不需要使用 GUI 工具 (除了几个密码提示框)。

    REM Demo of signing a printer driver with a self-signed test certificate.
    REM Run as administrator (else devcon won't be able to try installing the driver)
    REM Use a single 'x' as the password for all certificates for simplicity.
    
    PATH %PATH%;"c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin";"c:\Program Files\Microsoft SDKs\Windows\v7.0\Bin";c:\WinDDK\7600.16385.1\bin\selfsign;c:\WinDDK\7600.16385.1\Tools\devcon\amd64
    
    makecert -r -pe -n "CN=Demo_CA" -ss CA -sr CurrentUser ^
       -a sha256 -cy authority -sky signature ^
       -sv Demo_CA.pvk Demo_CA.cer
    
    makecert -pe -n "CN=Demo_SPC" -a sha256 -cy end ^
       -sky signature ^
       -ic Demo_CA.cer -iv Demo_CA.pvk ^
       -sv Demo_SPC.pvk Demo_SPC.cer
    
    pvk2pfx -pvk Demo_SPC.pvk -spc Demo_SPC.cer ^
       -pfx Demo_SPC.pfx ^
       -po x
    
    inf2cat /drv:driver /os:XP_X86,Vista_X64,Vista_X86,7_X64,7_X86 /v
    
    signtool sign /d "description" /du "www.yoyodyne.com" ^
       /f Demo_SPC.pfx ^
       /p x ^
       /v driver\demoprinter.cat
    
    certutil -addstore Root Demo_CA.cer
    
    rem Needs administrator. If this command works, the driver is properly signed.
    devcon install driver\demoprinter.inf LPTENUM\Yoyodyne_IndustriesDemoPrinter_F84F
    
    rem Now uninstall the test driver and certificate.
    devcon remove driver\demoprinter.inf LPTENUM\Yoyodyne_IndustriesDemoPrinter_F84F
    
    certutil -delstore Root Demo_CA
    

    4
    如果你想用它来签署驱动程序,你需要将CA证书导入机器存储中。我的示例将其导入用户存储中,对于大多数软件的测试/内部目的来说这是可以的。 - Roger Lipscombe

    14

    3
    值得一提的是,即使你在Windows 7上安装了WMF更新以获取PowerShell 4.0,你也无法使用该命令。这似乎只适用于Win8或Server 2012或更高版本。 - Daniel Yankowsky

    2
    你可以在Visual Studio 2019中生成一个测试证书,在项目属性中。在驱动程序签名部分,测试证书字段有一个下拉菜单。生成测试证书是其中的一种选项。该证书通常以“cer”扩展名保存在与可执行文件或驱动程序相同的输出目录中的文件中。

    0

    这篇文章只回答“如果你有证书如何签署EXE文件”的部分:

    为了签署exe文件,我使用了MS的“signtool.exe”。为此,您需要下载庞大的MS Windows SDK,其大小高达1GB。幸运的是,您不必安装它。只需打开ISO并提取“Windows SDK Signing Tools-x86_en-us.msi”。它仅有400 KB。

    然后我编写了这个小脚本文件:

    prompt $
    echo off
    cls
    
    copy "my.exe" "my.bak.exe"
    
    "c:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe" sign /fd SHA256 /f MyCertificate.pfx /p MyPassword My.exe
    
    pause 
    

    详情

    __


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接