将 JarSigner 与 RSASSA-PSS 结合使用
Using the JarSigner with RSASSA-PSS
我正在尝试使用 PKCS#11 使用 JarSigner 对 JAR 文件进行 RSA-PSS 签名。为了指定签名算法,JarSigner 使用 sigalg 标志。 JDK 14 Docs of the JarSigner 没有指定明确支持哪些信号。我已经测试过 JarSigner 接受“RSASSA-PSS”作为有效算法。 JarSigner 不接受 Java 加密服务提供商(例如 SunPKCS11 加密服务提供商)经常支持的“SHA256withRSASSA-PSS”或类似的 RSASSA-PSS 变体。
当尝试使用 sigalg“RSASSA-PSS”签名时,JarSigner returns
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 never directly (see line 831 to 843) or indirectly (see Signature.java and 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% 确定,但它看起来像你的问题。你可能想看看。
更新: 稍微 off-topic,但看起来你可以使用 BouncyCastle 与 RSASSA-PSS 签约。不过,我不确定这是否适合您。也许您只是想切换到另一种密钥类型。
我正在尝试使用 PKCS#11 使用 JarSigner 对 JAR 文件进行 RSA-PSS 签名。为了指定签名算法,JarSigner 使用 sigalg 标志。 JDK 14 Docs of the JarSigner 没有指定明确支持哪些信号。我已经测试过 JarSigner 接受“RSASSA-PSS”作为有效算法。 JarSigner 不接受 Java 加密服务提供商(例如 SunPKCS11 加密服务提供商)经常支持的“SHA256withRSASSA-PSS”或类似的 RSASSA-PSS 变体。 当尝试使用 sigalg“RSASSA-PSS”签名时,JarSigner returns
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 never directly (see line 831 to 843) or indirectly (see Signature.java and 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% 确定,但它看起来像你的问题。你可能想看看。
更新: 稍微 off-topic,但看起来你可以使用 BouncyCastle 与 RSASSA-PSS 签约。不过,我不确定这是否适合您。也许您只是想切换到另一种密钥类型。