在基于Linux的发行版上签署Windows应用程序

时间:2013-08-17 10:52:52

标签: linux windows certificate exe sign

我准备了一个应用程序和网站,客户可以在下载之前为此应用程序设置多个选项。设置以二进制格式存储在文件末尾(附加),然后编辑的文件将发送给最终用户。问题是文件“内容”的更改将破坏文件签名 - 是否有机会使用任何命令行工具重新签名此更改的文件?我曾尝试使用微软的SignTool,但它在Linux上无法正常运行。

3 个答案:

答案 0 :(得分:25)

您可以尝试osslsigncode

要签署EXE或MSI文件,您现在可以执行以下操作:

osslsigncode sign -certs <cert-file> -key <der-key-file> \
        -n "Your Application" -i http://www.yourwebsite.com/ \
        -in yourapp.exe -out yourapp-signed.exe

或者如果您正在使用带密码的PEM或PVK密钥文件 有PEM证书:

osslsigncode sign -certs <cert-file> \
        -key <key-file> -pass <key-password> \
        -n "Your Application" -i http://www.yourwebsite.com/ \
        -in yourapp.exe -out yourapp-signed.exe

或者如果您还要添加时间戳:

osslsigncode sign -certs <cert-file> -key <key-file> \
        -n "Your Application" -i http://www.yourwebsite.com/ \
        -t http://timestamp.verisign.com/scripts/timstamp.dll \
        -in yourapp.exe -out yourapp-signed.exe

您可以使用存储在PKCS#12容器中的证书和密钥:

osslsigncode sign -pkcs12 <pkcs12-file> -pass <pkcs12-password> \
        -n "Your Application" -i http://www.yourwebsite.com/ \
        -in yourapp.exe -out yourapp-signed.exe

签署包含java类文件的CAB文件:

osslsigncode sign -certs <cert-file> -key <key-file> \
        -n "Your Application" -i http://www.yourwebsite.com/ \
        -jp low \
        -in yourapp.cab -out yourapp-signed.cab

答案 1 :(得分:20)

使用Mono的signtool实际上quite straight forward;棘手的部分(在链接的Mozilla文章中有更详细的描述)是将证书以正确的格式从Windows复制到Linux。

将Windows PFX证书文件转换为PVK和SPC文件,只需在将证书从Windows复制到Linux时就完成一次;

openssl pkcs12 -in authenticode.pfx -nocerts -nodes -out key.pem
openssl rsa -in key.pem -outform PVK -pvk-strong -out authenticode.pvk
openssl pkcs12 -in authenticode.pfx -nokeys -nodes -out cert.pem
openssl crl2pkcs7 -nocrl -certfile cert.pem -outform DER -out authenticode.spc

实际上签署exe是直截了当的;

signcode \
 -spc authenticode.spc \
 -v authenticode.pvk \
 -a sha1 -$ commercial \
 -n My\ Application \
 -i http://www.example.com/ \
 -t http://timestamp.verisign.com/scripts/timstamp.dll \
 -tr 10 \
 MyApp.exe

答案 2 :(得分:0)

如果要在运行时以编程方式执行此操作,可以使用Jsign工具。尤其是当您在后端请求签名后生成后端可执行文件时,这可能会很有帮助。而且您显然使用Java / Kotlin进行了此操作(该工具的名称暗示)。这是官方网站提供的API:

只需将此依赖项添加到项目中即可:

    <dependency>
      <groupId>net.jsign</groupId>
      <artifactId>jsign-core</artifactId>
      <version>3.1</version>
    </dependency> 

,然后像这样使用AuthenticodeSigner类:

 KeyStore keystore = KeyStoreUtils.load(newFile("keystore.p12"), "PKCS12", "password", null);

 AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "secret");  signer.withProgramName("My Application")
       .withProgramURL("http://www.example.com")
       .withTimestamping(true)
       .withTimestampingAuthority("http://timestamp.comodoca.com/authenticode");

 Signable file = Signable.of(new File("application.exe")); 
 signer.sign(file); 

有关API的更多详细信息,请参见Javadoc

除了通过Java KeyStore AuthenticodeSigner进行签名之外,还具有(Certificate, PrivateKey)构造函数,您可以像在“ Kotlin上的春天” 后端那样自由使用它:< / p>

    @Bean
    fun certsChain(): Array<Certificate> {
        val fact: CertificateFactory = CertificateFactory.getInstance("X.509")
        val `is` = ResourceUtil.getResourceFileAsInputStream("cert/certificate.pem")
        val cer: X509Certificate = fact.generateCertificate(`is`) as X509Certificate
        return arrayOf(cer)
    }

    @Bean
    fun privateKey(): PrivateKey {
        var key = ResourceUtil.getResourceFileAsString("cert/privateKey.pem")
        key = key.replace("-----BEGIN PRIVATE KEY-----", "")
        key = key.replace("\n", "")
        key = key.replace("-----END PRIVATE KEY-----", "")
        val encoded = Base64.getDecoder().decode(key)
        val kf = KeyFactory.getInstance("RSA")
        val keySpec = PKCS8EncodedKeySpec(encoded)
        return kf.generatePrivate(keySpec) as RSAPrivateKey
    }

    @Bean
    fun signer(
            certs: Array<Certificate>,
            privateKey: PrivateKey
    ): AuthenticodeSigner =
            AuthenticodeSigner(certs, privateKey)
                    .withProgramName("Your Company Name")
                    .withProgramURL("https://something.com")
                    .withTimestamping(true)
                    .withTimestampingAuthority("http://timestamp.comodoca.com/authenticode");

之后,您只需@Autowire signer bean并使用所需文件调用其方法sign()