我已经准备好一个应用程序和网站,顾客可以在下载前为这个应用程序设置几个选项。设置以二进制格式存储在文件末尾(追加),然后编辑过的文件被发送到终端用户。问题是文件内容的更改会破坏文件签名 - 是否有任何命令行工具可以重新签名这个更改后的文件?我尝试使用微软的SignTool,但在Linux上它不能正常工作。
我已经准备好一个应用程序和网站,顾客可以在下载前为这个应用程序设置几个选项。设置以二进制格式存储在文件末尾(追加),然后编辑过的文件被发送到终端用户。问题是文件内容的更改会破坏文件签名 - 是否有任何命令行工具可以重新签名这个更改后的文件?我尝试使用微软的SignTool,但在Linux上它不能正常工作。
osslsigncode sign -certs <cert-file> -key <der-key-file> \
-n "Your Application" -i http://www.yourwebsite.com/ \
-in yourapp.exe -out yourapp-signed.exe
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
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
使用Mono
的signtool对可执行文件进行签名实际上是相当简单的;复制证书以正确格式从Windows复制到Linux是有点棘手的(在链接的Mozilla文章中有更详细的描述)。
将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
signcode \
-spc authenticode.spc \
-v authenticode.pvk \
-a sha1 -$ commercial \
-n My\ Application \
-i http://www.example.com/ \
-t http://timestamp.digicert.com/scripts/timstamp.dll \
-tr 10 \
MyApp.exe
openssl:Error: 'cr12pkcs7' is an invalid command.
请确保注意第三个字符是小写字母'L'而不是数字'1'。 - user391035crl2pkcs7
,其中 L 不是数字 1。 - Tenders McChiken除了使用JavaSimply 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.
KeyStore
进行签名外,AuthenticodeSigner
还有一个 (Certificate, PrivateKey)
构造函数,您可以像我在我的后端 "Spring on Kotlin" 中所做的那样自由地使用它。 @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
签名者bean并调用其方法sign()
即可使用所需文件。