Использование JarSigner с RSASSA-PSS

#java #cryptography #pkcs#11 #jarsigner

#java #криптография #pkcs #11 #jarsigner

Вопрос:

Я пытаюсь RSA-PSS-подписать файл JAR с помощью JarSigner, используя PKCS # 11. Чтобы указать алгоритм подписи, JarSigner использует флаг sigalg . В документах JDK 14 JarSigner не указано, какие сигалы поддерживаются явно. Я проверил, что JarSigner принимает «RSASSA-PSS» в качестве допустимого алгоритма. JarSigner не принимает «SHA256withRSASSA-PSS» или аналогичные варианты RSASSA-PSS, которые часто поддерживают поставщики криптографических услуг Java, такие как поставщик криптографических услуг SunPKCS11. При попытке подписать с помощью sigalg «RSASSA-PSS» JarSigner возвращает

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

Это исключение означает, что параметры PSS не установлены. Я проследил проблему до JarSigner

  • нет никакого способа передать параметры PSS через командную строку (см. Документы JDK 14 JarSigner)
  • никогда не устанавливайте параметры PSS — JarSigner.java никогда напрямую (см. строки с 831 по 843) или косвенно (см. Signature.java и P11PSSSignature.java ) вызывает setParameter->setEngineParameter->setSigParams, который отвечает за установку требуемых параметров PSS.

Я что-то упустил? Если да, как я могу RSA-PSS-подписать файл JAR? Если нет, это ошибка? В конце концов, JarSigner явно принимает RSASSA-PSS как действительный sigalg. Или это скорее несовместимость между JarSigner и реализацией SunPKCS11? В конце концов, SunPKCS11 может просто использовать жестко заданные значения параметров PSS в таком случае.

Ответ №1:

Похоже, это пока не поддерживается. Я могу воспроизвести это поведение как с 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%, но это похоже на вашу проблему. Возможно, вы захотите посмотреть его.


Обновление: немного не по теме, но похоже, что вы можете подписаться с помощью RSASSA-PSS с помощью BouncyCastle. Однако я не уверен, является ли это альтернативой для вас. Может быть, вы просто хотите переключиться на другой тип ключа.