栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

从文件摘要创建pkcs7签名

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从文件摘要创建pkcs7签名

在他的更新中,OP几乎正确,只有两个错误:

  • 他尝试
    InputStream
    两次读取参数内容:
        CMSTypedData msg = new CMSProcessableByteArray(IOUtils.toByteArray(content));    [...]    Attribute attr = new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(md.digest(IOUtils.toByteArray(content)))));

因此,在第二次尝试之前已经从流中读取了所有数据,因此返回了empty

byte[]
。因此,消息摘要属性包含错误的哈希值。

  • 他以复杂的方式创建了最终的CMS容器:
    return new CMSSignedData(msg, s.getEnpred()).getEnpred();

将后者减少到实际需要的数量,事实证明不再需要

CMSTypedData msg
。因此,前者被隐式解决。

在将摘要计算重新安排到方法的顶部并另外切换到SHA256后(由于在许多情况下不赞成使用SHA1,我更喜欢使用其他哈希算法)并允许使用证书

chain
而不是单个证书
certificate
,该方法看起来像这个:

    // Digest generation step    MessageDigest md = MessageDigest.getInstance("SHA256", "BC");    byte[] digest = md.digest(IOUtils.toByteArray(content));    // Separate signature container creation step    List<Certificate> certList = Arrays.asList(chain);    JcaCertStore certs = new JcaCertStore(certList);    CMSSignedDataGenerator gen = new CMSSignedDataGenerator();    Attribute attr = new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digest)));    ASN1EncodableVector v = new ASN1EncodableVector();    v.add(attr);    SignerInfoGeneratorBuilder builder = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()) .setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v)));    AlgorithmIdentifier sha256withRSA = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA");    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");    InputStream in = new ByteArrayInputStream(chain[0].getEnpred());    X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);    gen.addSignerInfoGenerator(builder.build( new BcRSAContentSignerBuilder(sha256withRSA,         new DefaultDigestAlgorithmIdentifierFinder().find(sha256withRSA))      .build(PrivateKeyFactory.createKey(pk.getEnpred())), new JcaX509CertificateHolder(cert)));    gen.addCertificates(certs);    CMSSignedData s = gen.generate(new CMSAbsentContent(), false);    return s.getEnpred();

( CreateSignature方法

signWithSeparatedHashing

用在相当少的签名代码框架中

    void sign(PDdocument document, OutputStream output, SignatureInterface signatureInterface) throws IOException    {        PDSignature signature = new PDSignature();        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);        signature.setName("Example User");        signature.setLocation("Los Angeles, CA");        signature.setReason("Testing");        signature.setSignDate(Calendar.getInstance());        document.addSignature(signature);        ExternalSigningSupport externalSigning =     document.saveIncrementalForExternalSigning(output);        byte[] cmsSignature = signatureInterface.sign(externalSigning.getContent());        externalSigning.setSignature(cmsSignature);    }

( CreateSignature方法

sign

像这样

    try (   InputStream resource = getClass().getResourceAsStream("test.pdf"); OutputStream result = new FileOutputStream(new File(RESULT_FOLDER, "testSignedWithSeparatedHashing.pdf")); PDdocument pddocument = PDdocument.load(resource)   )    {        sign(pddocument, result, data -> signWithSeparatedHashing(data));    }

( CreateSignature测试方法

testSignWithSeparatedHashing

导致正确签名的PDF,至少与所讨论的证书和私钥适合当前任务一样适当。


一句话:

使用的OP

IOUtils.toByteArray(content))
(我在上面的代码中也是如此)。但是考虑到OP的开场白

如果PDF文件太大而无法上传怎么办?例如:100mb

这样做并不是一个好主意,因为它一次仅将一个大文件加载到内存中以进行哈希处理。如果确实要考虑一个应用程序的资源占用量,则应一次读取该流几个KB,然后连续使用来消化数据,

MessageDigest.update
并且仅
MessageDigest.digest
在最后使用来获得结果哈希值。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/453641.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号