Signing Windows application on Linux-based distros

前端 未结 3 1267
萌比男神i
萌比男神i 2020-11-30 21:57

I have prepared an application and website where the customer can set several options for this application before he downloads it. Settings are stored in binary format on th

相关标签:
3条回答
  • 2020-11-30 22:10

    You can try osslsigncode

    To sign an EXE or MSI file you can now do:

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

    or if you are using a PEM or PVK key file with a password together with a PEM certificate:

    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
    

    or if you want to add a timestamp as well:

    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
    

    You can use a certificate and key stored in a PKCS#12 container:

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

    To sign a CAB file containing java class files:

    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
    
    0 讨论(0)
  • 2020-11-30 22:21

    It's actually quite straight forward to do using Mono's signtool; the tricky part (described in more detail in the linked Mozilla article) is copying the certificate in the correct format from Windows to Linux.

    Converting the Windows PFX certificate file to PVK and SPC files, only needs to be done once when copying the certificate from Windows to 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
    

    Actually signing the exe is straight forward;

    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
    
    0 讨论(0)
  • 2020-11-30 22:24

    If you want to do that programmatically in runtime you can usee Jsign tool. Especially it could be quite helpful when you generate self-executable archive on the backend by request signing it after. And you do that using Java/Kotlin obviously (name of the tool is suggesting). Here is API provided from the official site:

    Simply add this dependency to the project:

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

    and then use the AuthenticodeSigner class like this:

     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); 
    

    See the Javadoc for more details about the API.

    Besides signing via Java KeyStore AuthenticodeSigner has (Certificate, PrivateKey) constructor and you can freely use it like I did in my "Spring on Kotlin" backend:

        @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");
    
    

    after, you can just @Autowire the signer bean and call its method sign() with the required file

    0 讨论(0)
提交回复
热议问题