Usando o JarSigner com RSASSA-PSS
Estou tentando assinar com RSA-PSS um arquivo JAR com o JarSigner usando PKCS # 11. Para especificar o algoritmo de assinatura, o JarSigner usa o sinalizador sigalg . O JDK 14 Docs do JarSigner não especifica quais sigalgs são explicitamente suportados. Testei se o JarSigner aceita "RSASSA-PSS" como um algoritmo válido. O JarSigner não aceita "SHA256withRSASSA-PSS" ou variantes semelhantes de RSASSA-PSS que os Java Crypto Service Providers, como o SunPKCS11 Crypto Service Provider, freqüentemente suportam. Ao tentar assinar com o sigalg "RSASSA-PSS" o JarSigner retorna
jarsigner: unable to sign jar: java.security.SignatureException: Parameters required for RSASSA-PSS signature
Essa exceção significa que os parâmetros PSS não estão definidos. Rastreei o problema até o JarSigner
- não ter nenhuma maneira de passar os parâmetros PSS através da linha de comando (ver JDK 14 Docs of the JarSigner )
- nunca definindo parâmetros PSS - o JarSigner.java nunca diretamente (consulte a linha 831 a 843) ou indiretamente (consulte Signature.java e P11PSSSignature.java ) chama setParameter-> setEngineParameter-> setSigParams, que é responsável por definir os parâmetros PSS necessários.
Estou esquecendo de algo? Em caso afirmativo, como posso assinar um arquivo JAR pelo RSA-PSS? Se não, isso é um bug? Afinal, o JarSigner aceita claramente RSASSA-PSS como um sigalg válido. Ou isso é antes uma incompatibilidade entre o JarSigner e a implementação SunPKCS11? Afinal, SunPKCS11 poderia apenas usar valores de parâmetros PSS codificados permanentemente nesse caso.
Respostas
Parece que ainda não há suporte para isso. Posso reproduzir esse comportamento com a jarsignerferramenta de linha de comando e com o código Java assim:
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
Parece que o JDK-8245274 foi criado para adicionar esse recurso ao Java 16. Não tenho 100% de certeza, mas parece que é o seu problema. Você pode querer assistir.
Atualização: um pouco fora do tópico, mas parece que você pode assinar com RSASSA-PSS usando BouncyCastle. Não tenho certeza se isso é uma alternativa para você, no entanto. Talvez você apenas queira alternar para outro tipo de chave.