gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 03:32:06 24 4
gpt4 key购买 nike

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

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

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

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

还有一个问题 - 如何在一个文件中存储多个 PKCS7 签名?我正在使用 bouncycaSTLe Java 库。它是否有某种方法来连接签名并从一个文件中提取它们?我不想手动将所有签名存储在一个 .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);

如您所见,生成方法的第二个参数为 false,这意味着我正在生成非封装签名==.sig 文件不包含数据。

验证代码

CMSSignedData cms = new CMSSignedData(new CMSProcessableByteArray(contents.getBytes()), signature);
Store store = cms.getCertificates();
SignerInformationStore signers = cms.getSignerInfos();
Collection c = signers.getSigners();
Iterator it = c.iterator();

while (it.hasNext()) {
SignerInformation signer = (SignerInformation) it.next();
Collection certCollection = store.getMatches(signer.getSID());
Iterator certIt = certCollection.iterator();
X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
ok = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert));
if (!ok) break; // probably should remove it
}

问题 - 我可以在 BouncyCaSTLe 中开箱即用地执行类似的操作(如下所述)吗?

将分离的签名封装起来 - 第一个签名 = hash(doc)-->appendToSigFile,第二个签名 = hash(doc+sigFile)-->appendToSigFile 等等。这种方法可以模仿 XML 的封装签名吗?

最佳答案

你实际上问了很多问题。因此,

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

如果您确定(例如由于组织原因)所有这些签名最初都正确地签署了同一文档,您可以考虑此优化。但即便如此,您也不应该随机选择签名,而应该选择那些具有更可靠算法的签名。

如果您确实进行了这样的优化,那么您绝对不应该声称​​所有签名仍然有效,但选择的一个仍然有效。如果您没有测试某些东西,则不应声称您已经测试过。

  • 但是 XML 修改无论如何都会破坏最后一个签名,为什么我必须检查其他签名?
  • 这很大程度上取决于您的用例。如果(如上所述)您确定(例如,由于组织原因)所有这些签名最初都正确地签署了各自的文档修订版,则检查最外层的签名可能就足够了。

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

    如果不是每个 XML 签名都使用至少与该签名一样严格的规范化来签署至少与各自包含的数据相同的数据(XML 签名可以非常有选择性地选择它们签名的元素以及它们允许的偏差),您绝对必须检查每一项。

  • 通常,验证过程不仅检查哈希值,还提供有关签名者的信息,这是迭代所有签名的唯一原因,对吗?
  • 显然......如果你只想检查哈希值,你只会存储哈希值(好吧,除非有政治或营销相关的原因......)。签名是为了证明特定的人在特定情况下出于特定目的看到并接受了某些特定数据。您的问题似乎只想考虑具体数据部分。

  • 如何在一个文件中存储多个 PKCS7 签名?
  • PKCS#7 签名容器可以包含任意数量的相同数据的并行签名和附加反签名。

    如果你看一下规范RFC 2315你会发现:

    The signed-data content type shall have ASN.1 type SignedData:

    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 is a collection of per-signerinformation. There may be any number of elements in thecollection, including zero.

    BouncyCaSTLe 提供了许多实用功能,也是为此,但由于您没有展示如何使用 BC,所以很难解释您应该如何更改 BC 的使用。

  • 将分离的签名封装起来 - 第一个签名 = hash(doc)-->appendToSigFile,第二个签名 = hash(doc+sigFile)-->appendToSigFile 等等。这种方法可以模仿 XML 的封装签名吗?
  • 您可以使用与您的设计等效的副署。

    或者... PKCS#7 签名容器允许您嵌入签名内容,无需分离。因此,您可以将原始内容嵌入到第一个签名容器中,然后将此签名容器嵌入到第二个签名容器中,依此类推。这将隐式地清楚每个签名所签名的内容。

    关于java - 检查一个随机选择的数字签名是否足以验证多个签名的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28794036/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com