javacryptographypkcs#11jarsigner

Using the JarSigner with RSASSA-PSS


Im trying to RSA-PSS-sign a JAR file with the JarSigner using PKCS#11. To specify the signature algorithm the JarSigner uses the sigalg flag. The JDK 14 Docs of the JarSigner does not specify which sigalgs are explicitly supported. I have tested that the JarSigner accepts "RSASSA-PSS" as a valid algorithm. The JarSigner does not accept "SHA256withRSASSA-PSS" or similar RSASSA-PSS variants that Java Crypto Service Providers, such as the SunPKCS11 Crypto Service Provider, often support. When trying to sign with the sigalg "RSASSA-PSS" the JarSigner returns

jarsigner: unable to sign jar: java.security.SignatureException: Parameters required for RSASSA-PSS signature

This exception means that the PSS parameters are not set. I have traced the problem down to the JarSigner

Am I missing something? If yes, how can I RSA-PSS-sign a JAR file? If no, is this a bug? After all, the JarSigner clearly accepts RSASSA-PSS as a valid sigalg. Or is this rather an incompatibility between the JarSigner and the SunPKCS11 implementation? After all, SunPKCS11 could just be using hardcoded PSS param values in such a case.


Solution

  • It looks like this is not supported yet. I can reproduce this behaviour both with the jarsigner command line tool and with Java code like this:

    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
    

    It looks like JDK-8245274 is meant to add this feature to Java 16. I am not 100% sure, but it looks like your issue. You may want to watch it.


    Update: Slightly off-topic, but it looks like you can sign with RSASSA-PSS using BouncyCastle. I am not sure if that is an alternative for you, though. Maybe you just want to switch to another key type.