如何使用带有JarSigner的XMSS(PQC)签名方案签署.jar文件 [英] How to sign a .jar file using XMSS (PQC) Signature Scheme with JarSigner

查看:491
本文介绍了如何使用带有JarSigner的XMSS(PQC)签名方案签署.jar文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 JarSigner 使用 XMSS 签名来签署.jar文件。
使用 JCA / JCE 后量子密码术提供者来自 BouncyCastle 可以通过编程方式(示例)生成XMSS和XMSSMT KeyPairs。
为了使用JarSigner,据我所知,对于提供KeyStore以及想要使用以下代码签名的条目的别名至关重要: jarsigner -keystore myKeystore -storetype JKS -storepass密码-keypass密码myjarfile.jar keystoreEntryAlias KeyStore条目包含Public / Secret KeyPair和相关的X.509证书。

I am trying to use JarSigner to sign .jar files with XMSS Signatures. With the use of the JCA/JCE Post-Quantum Cryptography Provider from BouncyCastle it is possible to generate XMSS and XMSSMT KeyPairs programmatically (example). In order to use JarSigner it is, as far as I know, crucial to provide a KeyStore and the alias of the entry one wants to sign its code with: jarsigner -keystore myKeystore -storetype JKS -storepass password -keypass password myjarfile.jar keystoreEntryAlias The KeyStore entry contains the Public/Secret KeyPair and the assosiated X.509 Certificate.

使用JarSigner签署Jar文件的正常方式如下:

The 'normal' way of signing a Jar file with the JarSigner is as follows:


  1. 使用keytool生成公钥/密钥KeyPair和证书然后将它们存储在KeyStore中( keytool -genkeypair -alias keystoreEntryAlias -keyalg RSA -sigalg SHA256withRSA -dname CN = MyCompanyName -storetype JKS -keypass password -keystore mykeystore.jks -storepass password

  2. 使用JarSigner使用存储在mykeystore.jks中的SecretKey和别名keysotreEntryAlias( jarsigner -keystore mykeystore.jks -storetype jks -storepass)签署.jar passeword -keypass pa ssword myjarfile.jar keystoreEntryAlias

  1. Use keytool to generate the Public/Secret KeyPair and a Certificate then store them in a KeyStore (keytool -genkeypair -alias keystoreEntryAlias -keyalg RSA -sigalg SHA256withRSA -dname CN=MyCompanyName -storetype JKS -keypass password -keystore mykeystore.jks -storepass password)
  2. Use JarSigner to sign the .jar using the SecretKey stored in mykeystore.jks with the alias keysotreEntryAlias (jarsigner -keystore mykeystore.jks -storetype jks -storepass passeword -keypass password myjarfile.jar keystoreEntryAlias)

为了用XMSS密钥签名我的文件我理论上有两个可能性:

In order to Sign my file with an XMSS Key I have theoretically two possibilities:


  1. 使用BCPQC以编程方式创建XMSS KeyPairs,将它们存储在mykeystore中并使用 jarsigner -keystore mykeystore -alias xmss 通过CLI签署我的文件。

  2. 使用BCPQC-Provider和keytool直接通过CLI生成XMSS KeyPairs并将它们存储在mykeystore中(keytool会这里还需要2个参数: -providerclass org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider -providerpath C:\ Path \ to \\ \\BouncyCastle \ provider\bcprov-jdk15on-160.jar )然后使用JarSigner使用密钥库条目对文件进行签名

  1. Use BCPQC to create XMSS KeyPairs programmatically, store them in mykeystore and use jarsigner -keystore mykeystore -alias xmss via CLI to sign my file.
  2. Use BCPQC-Provider with the keytool in order to directly via CLI generate XMSS KeyPairs and store them in mykeystore (keytool would here need 2 more arguments: -providerclass org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider and -providerpath C:\Path\to\BouncyCastle\provider\bcprov-jdk15on-160.jar) Then sign the file with the keystore entry using JarSigner

可悲的是,我遇到了两种可能性的问题:

Sadly I run into problems with both possibilities:


  1. 因为我还没有找到一种方法在没有CLI的情况下使用JarSigner我需要把我生成的XMSS KeyPairs在KeyStore中,但是因此我需要包含Public XMSS Key的证书。 BouncyCastle确实提供了一个X.509CertificateBuilder,它可用于生成所需的证书,但是如果您查看生成的证书,特别是在签名算法和公钥(底部的源代码[CertificateBuilderExample],使用XMSSMT)

  2. 看来keytool只使用来自BCPQCProvider的init(int)重载,而XMSSKeyPairGeneratorSpi拒绝它;它希望AlgorithmParameterSpec特别是XMSSParameterSpec,或者根本不需要init - 如果我尝试后者,它会生成密钥对,但生成的密钥不能被编码,因此无法存储在KeyStore中。

我的问题现在是:

有没有人知道如何签署.jar文件使用XMSS / XMSSMT和JarSigner,可以提供一个或多或少的详细解释,说明他/她做错了什么?
或者,如果我对上面提到的任何事情有误,请提供更正并指明一种方法吗?

Does anyone know of a way to sign .jar Files using XMSS / XMSSMT with JarSigner and can provide a more or less detailed explanation on what he/her did right that I did wrong? Or if I was wrong about anything I mentioned above provide a correction and point out a way to do so ?

UPDATE 1 :我现在可以使用另一个X509CertificateGenerator(底部的源代码[X509CertificateGenerator])和从 here 这里此处成功签署jar文件 以编程方式使用BouncyCastle提供的RSA(底部签名的源代码[RSA_JarSigner])。

UPDATE 1: I am now able, with the use of another X509CertificateGenerator (Source code at bottom [X509CertificateGenerator]) and intel gathered from here, here and here, to successfully sign jar files programmatically with RSA provided from BouncyCastle (Source code for signing at bottom [RSA_JarSigner]).

如果我尝试应用相同的方案用RSA签名与XMSS或XMSSMT签名遇到 JarSignerException:签名者材料中的错误 NoSuchAlgorithmException:无法识别的算法名称:XMSS (XMSS的源代码/底部的XMSSMT [SignXMSS] [SignXMSSMT]。

If I try to apply the same scheme used to sign with RSA to sign with XMSS or XMSSMT I run into a JarSignerException: Error in signer materialscaused by NoSuchAlgorithmException: unrecognized algorithm name: XMSS (Source code for XMSS/XMSSMT at bottom [SignXMSS] [SignXMSSMT].

希望有人可以帮我找出问题所在!

Hopefully someone can help me figure out where the problem is!

UPDATE 2 :生成的XMSS(或XMSSMT)证书的问题似乎是由于签名算法的条目(是SHA256withXMSS)作为ASN1ObjectIdentifier传递,系统尚不知道。因此,我做了一些研究,看看BouncyCastle是不是偶然会在某处放置XMSS证书生成器.. Bingo,这里是一个!

UPDATE 2: It seems the problem with the generated XMSS (or XMSSMT) certificates is due to the fact that the entry for the Signature Algorithm (which is SHA256withXMSS) is passed as an ASN1ObjectIdentifier which is unknown to the system yet. Thus I did some research to see if BouncyCastle does not by accident have an XMSS Certificate Generator laying around somewhere.. Bingo, here is one!

我缩短了代码有点并提出了1个生成器和1个验证器(底部的源代码[XMSSGen] [XMSSVer]。
生成器tho给了我与其他方法相同的证书(例如[X509CertificateGenerator]) )。
验证者遗憾地提示我这个丑陋的错误:线程main中的异常java.security.spec.InvalidKeySpecException:java.lang.ClassCastException:org.bouncycastle.asn1.DLSequence不能org.bouncycastle.asn1.ASN1Integer
at org.bouncycastle.pqc.jcajce.provider.xmss.XMSSKeyFactorySpi.engineGeneratePrivate(Unknown Source)
at java.base / java.security.KeyFactory.generatePrivate(的KeyFactory .java:384)
at BCXMSSCertificateVerifyer.verifyCertificate(BCXMSSCertificateVerifyer.java:32)
at BCXMSSCertificateTester.main(BCXMSSCertificateTester.java:23)

I shortened the code a bit and came up with 1 generator and 1 verifier (Source code at bottom [XMSSGen] [XMSSVer]. The generator tho gives me the same Certificates I already got with the other methods (such as [X509CertificateGenerator]). The verifier sadly prompts me this ugly error: Exception in thread "main" java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer at org.bouncycastle.pqc.jcajce.provider.xmss.XMSSKeyFactorySpi.engineGeneratePrivate(Unknown Source) at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:384) at BCXMSSCertificateVerifyer.verifyCertificate(BCXMSSCertificateVerifyer.java:32) at BCXMSSCertificateTester.main(BCXMSSCertificateTester.java:23)

也许有人知道它来自何处/如何修复它。为了查看BC是否可以使用自己创建的XMSS证书。

Maybe someone has an idea where it comes from / how to fix it. In order to see if BC it self can work with its own created XMSS Certificates.

编辑:验证者的一个问题: PrivateKey privKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); 为什么我们需要私钥来验证证书?没有意义 - 只需删除它就行了^^(或至少应该)

One problem with the verifier: PrivateKey privKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); why would we need a private Key to verify the Certificate ? Makes no sense - just remove it and it works ^^ (or at least should)

更新3 :我终于设法使验证程序正常工作,因此我目前能够生成并验证XMSS证书。我还能够在KeyStore中存储包含PublicKey的证书的XMSS KeyPairs。虽然我仍然无法用。签名任何.jar文件。

UPDATE 3: I finally managed to get the the verifier to work properly, so I am currently able to produce and verify XMSS Certificates. I am also able to store XMSS KeyPairs with a Certificate containing the PublicKey in a KeyStore. Though I am still not able to sign any .jar file with.

现在有点奇怪:我可以用BC XMSS KeyPairs签名(当然如果我保存它们(或者至少是PrivateKey,因为他需要签署东西),然后重新加载它再次用它来签名,它就是不行的。如果我将它们存储在KeyStore中并检索它们,也不是将Key作为编码字节保存到文件并再次加载它们。 (如果您对代码感兴趣,只需发表评论,我会在此处发布)

Now comes something a bit strange: I am able to sign things with the BC XMSS KeyPairs (of course I am, thats what they got made for) tho if I save them (or at least the PrivateKey, as he is required to sign stuff) and reload it afterwards to sign stuff again with it, it does not work. Neither if I store them in a KeyStore and retrieve them nor if I save the Key as encoded Bytes to a file and load them again. (If your interested in the code, just comment and I'll post it here)

我的建议是:由于XMSS签名方案需要一个州(状态为OTS已经使用过)要保存,不能从PrivateKey中检索到这个状态,因为它再次被加载(无论是来自KeyStore还是文件无关紧要),因此不能用来签名。

My suggestion is: as the XMSS Signature Scheme requires a state (the state of the OTS already used) to be saved, that this state somehow cannot be retrieved from the PrivateKey as it is loaded again (whether from KeyStore or file doesnt matter) and thus cannot be used to sign something with.

[CertificateBuilderExample]

[CertificateBuilderExample]

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
import org.bouncycastle.pqc.jcajce.spec.XMSSMTParameterSpec;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;


public class App {

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastlePQCProvider());

        SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
        String datefrom = "12-08-2018 10:20:56";
        String dateuntil = "12-05-2020 10:20:56";
        Date from = sdf.parse(datefrom);
        Date until = sdf.parse(dateuntil);

        // Create self signed Root CA certificate
        KeyPair rootCAKeyPair = generateKeyPair();
        X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
                new X500Name("CN=rootCA"), // issuer authority
                BigInteger.valueOf(new Random().nextInt()), //serial number of certificate
                from, // start of validity
                until, //end of certificate validity
                new X500Name("CN=rootCA"), // subject name of certificate
                rootCAKeyPair.getPublic()); // public key of certificate
        // key usage restrictions
        builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign));
        builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
        X509Certificate rootCA = new JcaX509CertificateConverter().getCertificate(builder
                .build(new JcaContentSignerBuilder("SHA256withXMSSMT").setProvider("BCPQC").
                        build(rootCAKeyPair.getPrivate()))); // private key of signing authority , here it is self signed
        saveToFile(rootCA, "rootCA.cer");

    }

    private static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("XMSSMT", "BCPQC");
        kpGen.initialize(new XMSSMTParameterSpec(20, 10, XMSSMTParameterSpec.SHA256), new SecureRandom());
        KeyPair kp = kpGen.generateKeyPair();
        System.out.print("Public key:" + Arrays.toString(kp.getPublic().getEncoded()));
        return kp;
    }

    private static void saveToFile(X509Certificate certificate, String filePath) throws IOException, CertificateEncodingException {
        FileOutputStream fileOutputStream = new FileOutputStream(filePath);
        fileOutputStream.write(certificate.getEncoded());
        fileOutputStream.flush();
        fileOutputStream.close();
    }

}

[X509CertificateGenerator]

[X509CertificateGenerator]

public X509Certificate generateCertificate(String dn, KeyPair keyPair, int validity, String sigAlgName) throws GeneralSecurityException, IOException {
        PrivateKey privateKey = keyPair.getPrivate();

        X509CertInfo info = new X509CertInfo();

        Date from = new Date();
        Date to = new Date(from.getTime() + validity * 1000L * 24L * 60L * 60L);

        CertificateValidity interval = new CertificateValidity(from, to);
        BigInteger serialNumber = new BigInteger(64, new SecureRandom());
        X500Name owner = new X500Name(dn);
        AlgorithmId sigAlgId = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);

        info.set(X509CertInfo.VALIDITY, interval);
        info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber));
        info.set(X509CertInfo.SUBJECT, owner);
        info.set(X509CertInfo.ISSUER, owner);
        info.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic()));
        info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
        info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(sigAlgId));

        // Sign the cert to identify the algorithm that's used.
        X509CertImpl certificate = new X509CertImpl(info);
        certificate.sign(privateKey, sigAlgName);

        // Update the algorith, and resign.
        sigAlgId = (AlgorithmId) certificate.get(X509CertImpl.SIG_ALG);
        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgId);
        certificate = new X509CertImpl(info);
        certificate.sign(privateKey, sigAlgName);

        return certificate;
    }

[RSA_JarSigner]

[RSA_JarSigner]

public class JarSignerTest {

    public static void main(String[] args) throws Exception{
        JarSignerTest jst = new JarSignerTest();
        jst.SignRSA();
    }

    public void SignRSA() throws Exception{
        Security.addProvider(new BouncyCastleProvider());
        File inputFile = new File("C:\\Path\\to\\jar\\toSign\\jarfile.jar"),
                outputfile = new File("C:\\Path\\to\\signedJar\\jarfile.jar");
        X509CertificateGen x509certgen = new X509CertificateGen();
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
        kpGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = kpGen.generateKeyPair();
        Certificate[] chain = {x509certgen.generateCertificate("cn=Unknown", keyPair, 356, "SHA256withRSA")};
        List<? extends Certificate> foo = Arrays.asList(chain);
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        CertPath certPath = certificateFactory.generateCertPath(foo);
        JarSigner signer = new JarSigner.Builder(keyPair.getPrivate(), certPath)
                .digestAlgorithm("SHA-256")
                .signatureAlgorithm("SHA256withRSA")
                .build();
        try (ZipFile in = new ZipFile(inputFile);
             FileOutputStream out = new FileOutputStream(outputfile)){
            signer.sign(in, out);
        }
    }
}

[SignXMSS]

[SignXMSS]

public void SignXMSS() throws Exception{
    Security.addProvider(new BouncyCastlePQCProvider());
    File inputFile = new File("C:\\Path\\to\\jar\\toSign\\jarfile.jar"),
            outputfile = new File("C:\\Path\\to\\signedJar\\jarfile.jar");
    X509CertificateGen x509certgen = new X509CertificateGen();
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("XMSS", "BCPQC");
    kpGen.initialize(new XMSSParameterSpec(10, XMSSParameterSpec.SHA256), new SecureRandom());
    KeyPair keyPair = kpGen.generateKeyPair();
    Certificate[] chain = {x509certgen.generateCertificate("cn=Unknown", keyPair, 356, "SHA256withXMSS")};
    List<? extends Certificate> foo = Arrays.asList(chain);
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    CertPath certPath = certificateFactory.generateCertPath(foo);
    JarSigner signer = new JarSigner.Builder(keyPair.getPrivate(), certPath)
            .digestAlgorithm("SHA-256")
            .signatureAlgorithm("SHA256withXMSS", new BouncyCastlePQCProvider())
            .build();
    try (ZipFile in = new ZipFile(inputFile);
         FileOutputStream out = new FileOutputStream(outputfile)){
        signer.sign(in, out);
    }
}

[SignXMSSMT]

[SignXMSSMT]

public void SignXMSSMT() throws Exception{
    Security.addProvider(new BouncyCastlePQCProvider());
    File inputFile = new File("C:\\Path\\to\\jar\\toSign\\jarfile.jar"),
            outputfile = new File("C:\\Path\\to\\signedJar\\jarfile.jar");
    X509CertificateGen x509certgen = new X509CertificateGen();
    KeyPairGenerator kpGen = KeyPairGenerator.getInstance("XMSSMT", "BCPQC");
    kpGen.initialize(new XMSSMTParameterSpec(20, 10, XMSSMTParameterSpec.SHA256), new SecureRandom());
    KeyPair keyPair = kpGen.generateKeyPair();
    Certificate[] chain = {x509certgen.generateCertificate("cn=Unknown", keyPair, 356, "SHA256withXMSSMT")};
    List<? extends Certificate> foo = Arrays.asList(chain);
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    CertPath certPath = certificateFactory.generateCertPath(foo);
    JarSigner signer = new JarSigner.Builder(keyPair.getPrivate(), certPath)
            .digestAlgorithm("SHA-256")
            .signatureAlgorithm("SHA256withXMSSMT")
            .build();
    try (ZipFile in = new ZipFile(inputFile);
         FileOutputStream out = new FileOutputStream(outputfile)){
        signer.sign(in, out);
    }
}

[XMSSGen]

[XMSSGen]

public class BCXMSSCertificateGenerator {

    public static X509Certificate generateCertificate(PrivateKey privKey, PublicKey pubKey, int duration, boolean isSelfSigned) throws Exception {
        Provider BC = new BouncyCastleProvider();

        //
        // distinguished name table.
        //
        X500NameBuilder builder = createStdBuilder();

        //
        // create the certificate - version 3
        //
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withXMSS").setProvider("BCPQC").build(privKey);
        X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(new X500Name("cn=Java"), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date((long)(System.currentTimeMillis() + duration*8.65*Math.pow(10,7))), builder.build(), pubKey);

        X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen));

        cert.checkValidity(new Date());
        if (isSelfSigned) {
            //
            // check verifies in general
            //
            cert.verify(pubKey);

            //
            // check verifies with contained key
            //
            cert.verify(cert.getPublicKey());
        }


        ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded());
        CertificateFactory fact = CertificateFactory.getInstance("X.509", BC);

        return (X509Certificate) fact.generateCertificate(bIn);
    }

    private static X500NameBuilder createStdBuilder() {
        X500NameBuilder builder = new X500NameBuilder(RFC4519Style.INSTANCE);

        builder.addRDN(RFC4519Style.c, "AU");
        builder.addRDN(RFC4519Style.o, "The Legion of the Bouncy Castle");
        builder.addRDN(RFC4519Style.l, "Melbourne");
        builder.addRDN(RFC4519Style.st, "Victoria");
        builder.addRDN(PKCSObjectIdentifiers.pkcs_9_at_emailAddress, "feedback-crypto@bouncycastle.org");

        return builder;
    }
}

[XMSSVer]

[XMSSVer]

public class BCXMSSCertificateVerifyer {
    public static boolean verifyCertificate(byte[] certBytes, String sigAlgorithm, byte[] keyBytes) throws Exception{
        ByteArrayInputStream bIn;

        bIn = new ByteArrayInputStream(certBytes);

        CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC");

        Certificate cert = fact.generateCertificate(bIn);

        PublicKey k = cert.getPublicKey();

        X509CertificateHolder certHldr = new X509CertificateHolder(certBytes);

        certHldr.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BCPQC").build(k));
        System.out.println(cert);

        KeyFactory keyFactory = KeyFactory.getInstance(k.getAlgorithm(), "BCPQC");

        PrivateKey privKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));   // ERROR at this line
        /*_______________________________________________________________________________________________________________*\

        Exception in thread "main" java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer
            at org.bouncycastle.pqc.jcajce.provider.xmss.XMSSKeyFactorySpi.engineGeneratePrivate(Unknown Source)
            at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:384)
            at BCXMSSCertificateVerifyer.verifyCertificate(BCXMSSCertificateVerifyer.java:32)
            at BCXMSSCertificateTester.main(BCXMSSCertificateTester.java:23)
        _________________________________________________________________________________________________________________
      /*                                                                                                                 */

        Signature signer = Signature.getInstance(sigAlgorithm, "BCPQC");

        signer.initSign(privKey);

        signer.update(certBytes);

        byte[] sig = signer.sign();

        signer.initVerify(cert);

        signer.update(certBytes);

        signer.verify(sig);
        return true;
    }
}


推荐答案

TL; DR:签署.jar文件使用PQC签名方案,例如BC使用内置 JarSigner提供的XMSS是不可能的。然而,人们可以怀疑它的一个JarSigner,然后就可以了。

TL;DR: Signing .jar Files with PQC Signature schemes such as XMSS provided by BC using the built in JarSigner is not possible. However one can wright its one JarSigner which then can.

尽管Oracle为加密提供商(如BC)提供了JCA / JCE的开箱即用集成,但这些注册提供商并非如此用于JarSigner既不用于签名也不用于验证。
考虑JarSigner:支持的算法是硬编码的,因此无法扩展。

Although Oracle provides with JCA/JCE an out of the box integration for Crypto Provider such as BC those registered providers are not used from JarSigner neither for signing nor for verifying. Considering the JarSigner: the supported algorithms are hard-coded and can thus not be extended.

将JarSigner与BC Provider一起使用的唯一方法是重建它完全是。但是不建议这样做。

The only way to use JarSigner with the BC Provider is to rebuild it entirely. However this is not recommended.

对于那些不怕劫持jdk源代码的人,你的项目必须从jdk覆盖以下类:

For those which are not afraid of hijacking jdk source code, your project has to "override" the following classes from the jdk:


  • AlgorithmId

  • 属性

  • ContentInfo

  • EndEntityChecker

  • HttpTimestamper

  • InvalidJarIndexError

  • Jarentry

  • JarException

  • JarFile

  • JarIndex

  • JarInputStream

  • JarOutputStream

  • JarSigner

  • JarVerifier

  • JavaUtilJarAccess

  • JavaUtilJarAccessImpl

  • JavaUtilZipFileAccess

  • Main(jdk.jartool.sun.security.tools.jarsigner)

  • Manifest

  • ManifestEntryVerifier

  • Pack200

  • PKCS7

  • PKIXValidator

  • 资源

  • Resources_ja

  • Resources_zh_CN

  • SharedSecrets

  • SignatureFi leVerifier

  • SignerInfo

  • SimpleValidator

  • TimestampedSigner

  • Timestamper

  • TimestampToken

  • TSResponse

  • Validator

  • VersionedStream

  • AlgorithmId
  • Attributes
  • ContentInfo
  • EndEntityChecker
  • HttpTimestamper
  • InvalidJarIndexError
  • Jarentry
  • JarException
  • JarFile
  • JarIndex
  • JarInputStream
  • JarOutputStream
  • JarSigner
  • JarVerifier
  • JavaUtilJarAccess
  • JavaUtilJarAccessImpl
  • JavaUtilZipFileAccess
  • Main (jdk.jartool.sun.security.tools.jarsigner)
  • Manifest
  • ManifestEntryVerifier
  • Pack200
  • PKCS7
  • PKIXValidator
  • Resources
  • Resources_ja
  • Resources_zh_CN
  • SharedSecrets
  • SignatureFileVerifier
  • SignerInfo
  • SimpleValidator
  • TimestampedSigner
  • Timestamper
  • TimestampToken
  • TSResponse
  • Validator
  • VersionedStream

因此,将原始代码复制粘贴到您的项目中并删除您劫持的所有类的导入,这样您的自定义类将被取代而不是官方的。

Therefor copy paste the original code into your project and remove the import of all classes which you hijack so your "custom" classes will be taken instead of the official ones.

注意:上面提到的大多数类都可以在java.base模块中找到,尽管有些类在jdk.jartool模块中(例如JarSigner本身)。

Note: Most of the classes mentioned above can be found in the java.base module, although some are in the jdk.jartool module (such as the JarSigner itself).

克隆jdk的必要部分以使JarSigner工作后,您最终可以继续实施BC提供程序并支持PQC签名方案,尤其是XMSSMT和SPHINCS,作为 ke XMSS存在一些主要问题

After cloning the necessary part of the jdk to get the JarSigner to work you can finally move on implementing your BC provider and the support of the PQC Signature Schemes, especially XMSSMT and SPHINCS, as for the moment it seems like XMSS has some major problems.

请注意已签名jar文件的验证 JarVerifier获取签名块文件的文件扩展名,并检查其.RSA,.DCA或.EC。因此,您必须添加.XMSS .XMSSMT .SPHINCS256等。您还必须告诉parseSignedData方法中的PKCS7类使用BC证书生成器。
还有一些其他的东西要改变(例如AlgorithmID),我不记得了,但是一旦你完成了所有必要的步骤,你的JarSigner就能够使用BC签署并验证.jar文件了使用正常RSA DCA和EC签名和验证。

Note that for the verification of a signed jar file the JarVerifier takes the file extension of the signature block file and checks rather if its .RSA, .DCA or .EC. So you will have to add .XMSS .XMSSMT .SPHINCS256 etc. You will also have to tell the PKCS7 class in the parseSignedData method to use a BC certificate generator. There are a few other things to change as well (e.g. AlgorithmID) which I don't remember, but once you have done all the necessary steps, your JarSigner is able to sign and verify .jar files using BC in addition to using the "normal" RSA DCA and EC signing and verifying.

遗憾的是,我无法与您分享最终的源代码,尽管我会尝试回答你的大部分问题都可以。

Sadly I will not be able to share the final Source Code with you, although I will try answer as much of your questions as possible.

这篇关于如何使用带有JarSigner的XMSS(PQC)签名方案签署.jar文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆