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