Java 检查一个随机选择的数字签名是否足以验证多个签名文件?

Java 检查一个随机选择的数字签名是否足以验证多个签名文件?,java,certificate,x509certificate,digital-signature,bouncycastle,Java,Certificate,X509certificate,Digital Signature,Bouncycastle,想象一下,我有一些二进制文件的多个分离签名,它们存储在不同的.sig文件中当有人修改文件时,所有签名都将无效 对于xml,封装签名被广泛使用。检查更加困难-必须提取最后一个ds:Signature元素,检查签名,删除最后一个元素并检查当前的最后一个ds:Signature元素等等。但是XML修改无论如何都会破坏最后一个签名,为什么我必须检查其他签名 唯一的解释是,每个ds:Signature或PKCS7签名都包含公钥证书,其中包含有关签名者、密钥有效期和撤销检查信息的信息通常,验证过程不仅仅是检

想象一下,我有一些二进制文件的多个分离签名,它们存储在不同的.sig文件中当有人修改文件时,所有签名都将无效

对于xml,封装签名被广泛使用。检查更加困难-必须提取最后一个
ds:Signature
元素,检查签名,删除最后一个元素并检查当前的最后一个
ds:Signature
元素等等。但是XML修改无论如何都会破坏最后一个签名,为什么我必须检查其他签名

唯一的解释是,每个
ds:Signature
或PKCS7签名都包含公钥证书,其中包含有关签名者、密钥有效期和撤销检查信息的信息通常,验证过程不仅仅是检查散列,还提供关于签名者的信息,这是迭代所有签名者的唯一原因,对吗?

所以,当我想验证多个签名文件并提供签名者的信息时,我可以对所有签名进行小型优化-提取信息,但只在一个随机选择的签名中执行哈希检查吗

还有一个问题-如何在一个文件中存储多个PKCS7签名?我正在使用bouncycastleJava库。它是否有某种方法连接签名并从一个文件中提取签名?我不想手动将所有签名存储在一个.sig文件中,关心签名分隔符,bouncy castle开箱即用是否可用

更新

我的BouncyCastle签名代码

    Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(alias);

    final List<Certificate> certlist = new ArrayList<Certificate>();

    for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
        certlist.add(certchain[i]);
    }

    Store certstore = new JcaCertStore(certlist);

    Certificate cert = keystore.getCertificate(alias);

    ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").
            build((PrivateKey) (keystore.getKey(alias, getPassword().toCharArray())));

    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

    generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
            build()).build(signer, (X509Certificate) cert));

    generator.addCertificates(certstore);
    CMSTypedData cmsdata = new CMSProcessableByteArray(content);
    CMSSignedData signeddata = generator.generate(cmsdata, false);
问题-我可以在BouncyCastle开箱即用模式中执行类似操作(如下描述)吗?


将分离的签名封装起来-第一个符号=散列(doc)-->appendToSigFile,第二个符号=散列(doc+sigFile)-->appendToSigFile,依此类推。这种方法可以模仿XML的封装签名吗?

实际上,您会问很多问题。因此,

  • 当我想验证多个签名文件并提供有关签名者的信息时,我可以进行小型优化-提取所有签名的信息,但只在一个随机选择的签名中执行哈希检查吗

    如果你确信(例如,通过组织的原因)所有的签名最初都正确地签署了同一个文件,你可以考虑这个优化。但即使这样,您也不应该随机选择签名,而应该选择具有更可验证算法的签名

    如果你真的这样优化了,你肯定不应该声称所有的签名仍然有效,而应该选择一个。如果你没有测试某些东西,你就不应该声称你做了

  • 但是XML修改无论如何都会破坏最后一个签名,为什么我必须检查其他签名

    这在很大程度上取决于您的用例。如果(如上所述)您确信(例如,由于组织原因)所有这些签名最初都正确地签署了各自的文件版本,那么检查最外层的签名就足够了

    另一方面,如果文档是由一个人转发给另一个人进行签名的,并且您检查的操作可能在任何步骤中发生,则您必须检查这些签名中的每一个,以确保每个人都在没有不必要的更改的情况下签署了内容

    如果不是每个XML签名都使用至少与该签名一样严格的规范化(XML签名可以非常有选择性地对其签名的元素和允许的偏差进行选择),那么您肯定必须检查每个签名

  • 通常,验证过程不仅仅是检查散列,而是提供关于签名者的信息,这是迭代所有签名的唯一原因,对吗

    显然。。。如果您只想检查散列,那么您只需要存储散列(好的,除非有政治或营销相关的原因…)。签名是为了证明特定的人在特定的情况下为了特定的目的看到并接受了特定的数据。你的问题似乎只想考虑具体的数据部分。

  • 如何在一个文件中存储多个PKCS7签名

    PKCS#7签名容器可以包含相同数据的任意数量的并行签名和其他反签名

    如果您查看规范,您会发现:

    签名数据内容类型应具有ASN.1类型签名数据:

    SignedData ::= SEQUENCE {
     version Version,
     digestAlgorithms DigestAlgorithmIdentifiers,
     contentInfo ContentInfo,
     certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
     signerInfos SignerInfos }
    
    DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
    
    SignerInfos ::= SET OF SignerInfo
    

    signerInfos是每个签名者的签名集 信息。文件中可能有任意数量的元素 集合,包括零

    BouncyCastle也为此提供了许多实用程序功能,但由于您没有说明如何使用BC,因此很难解释如何更改BC的使用

  • 将分离的签名封装起来-第一个符号=散列(doc)-->appendToSigFile,第二个符号=散列(doc+sigFile)-->appendToSigFile,依此类推。这种方法可以模仿XML的封装签名吗

    您可以使用与您的设计等效的会签

    或者。。。PKCS#7签名容器允许您嵌入签名内容,无需分离。因此,您可以将原始内容嵌入第一个签名容器,然后将此签名容器嵌入第二个签名容器等。这将隐式地明确每个签名所签名的内容


  • 数字签名不仅仅是为了提供完整性检查。如果必要的话,他们也是一种证明该人在该文件上签字的法律手段。这就像支票上的签名。因此,您必须全部验证它们。如果一个失败了,你手上就有一个赝品。如果他们都失败了,你有一个腐败的文件或联合伪造。无论哪种情况,它都是无用的,应该被拒绝。

    您能确保所有单独的签名文件都在同一份文档上签名吗?一个签名不可能吗
    SignedData ::= SEQUENCE {
     version Version,
     digestAlgorithms DigestAlgorithmIdentifiers,
     contentInfo ContentInfo,
     certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
     signerInfos SignerInfos }
    
    DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
    
    SignerInfos ::= SET OF SignerInfo