问题描述
我正在尝试使用PKCS#11用JarSigner进行RSA-PSS-签名JAR文件。为了指定签名算法,JarSigner使用 sigalg 标志。 JDK 14 Docs of the JarSigner没有指定明确支持哪些标记。我已经测试过JarSigner接受“ RSASSA-PSS”作为有效算法。 JarSigner不接受Java加密服务提供程序(例如SunPKCS11加密服务提供程序)经常支持的“ SHA256withRSASSA-PSS”或类似的RSASSA-PSS变体。 尝试使用 sigalg “ RSASSA-PSS”签名时,JarSigner返回
jarsigner: unable to sign jar: java.security.SignatureException: Parameters required for RSASSA-PSS signature
此异常表示未设置PSS参数。我已将问题归结为JarSigner
- 无法通过命令行传递PSS参数(请参见JDK 14 Docs of the JarSigner)
- 从不设置PSS参数-JarSigner.java从不直接(参见第831至843行)或间接(参见Signature.java和P11PSSSignature.java)调用setParameter-> setEngineParameter-> setSigParams,即负责设置所需的PSS参数。
我错过了什么吗?如果是,我如何通过RSA-PSS签名JAR文件?如果否,这是一个错误吗?毕竟,JarSigner显然接受RSASSA-PSS作为有效的标志。还是在JarSigner和SunPKCS11实现之间不兼容?毕竟,在这种情况下,SunPKCS11可能只是使用硬编码的PSS参数值。
解决方法
似乎尚不支持此功能。我可以使用jarsigner
命令行工具和Java代码来重现这种行为:
import jdk.security.jarsigner.JarSigner;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertPath;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.zip.ZipFile;
class JarSignerDemo {
public static void main(String[] args) throws IOException,CertificateException,NoSuchAlgorithmException,KeyStoreException,UnrecoverableKeyException {
char[] password = "changeit".toCharArray();
KeyStore keyStore = KeyStore.getInstance(new File("keystore.jks"),password);
PrivateKey privateKey = (PrivateKey) keyStore.getKey("mykey",password);
CertPath certPath = CertificateFactory.getInstance("X.509").generateCertPath(Arrays.asList(keyStore.getCertificateChain("mykey")));
JarSigner jarSigner = new JarSigner.Builder(privateKey,certPath)
.digestAlgorithm("SHA-256")
.signatureAlgorithm("RSASSA-PSS")
.build();
try (
ZipFile jarFile = new ZipFile("my.jar");
FileOutputStream signedJarFile = new FileOutputStream("my-signed.jar")
)
{
jarSigner.sign(jarFile,signedJarFile);
}
}
}
Exception in thread "main" jdk.security.jarsigner.JarSignerException: Error creating signature
at jdk.jartool/jdk.security.jarsigner.JarSigner.sign(JarSigner.java:573)
at JarSignerDemo.main(scratch_3.java:28)
Caused by: java.security.SignatureException: Parameters required for RSASSA-PSS signatures
at java.base/sun.security.rsa.RSAPSSSignature.ensureInit(RSAPSSSignature.java:295)
at java.base/sun.security.rsa.RSAPSSSignature.engineUpdate(RSAPSSSignature.java:346)
at java.base/java.security.Signature$Delegate.engineUpdate(Signature.java:1393)
at java.base/java.security.Signature.update(Signature.java:902)
at java.base/java.security.Signature.update(Signature.java:871)
at jdk.jartool/jdk.security.jarsigner.JarSigner.sign0(JarSigner.java:841)
at jdk.jartool/jdk.security.jarsigner.JarSigner.sign(JarSigner.java:562)
... 1 more
看来JDK-8245274是要向Java 16添加此功能。我不确定100%,但是看起来像是您的问题。您可能要看它。
更新:有点偏离主题,但看起来您可以使用BouncyCastle使用RSASSA-PSS进行签名。不过,我不确定这是否可以替代您。也许您只想切换到其他键类型。