当前位置: 首页 > 知识库问答 >
问题:

PKCS7和“nonewithrsa”签名

贺佑运
2023-03-14

我需要计算一些数据签名,使用未封装的pkcs7与sha256和RSA。对于原始内容没有问题,使用:

public byte[] signRawContent(final byte[] content)
    throws CMSException, IOException, OperatorCreationException, CertificateEncodingException {

    // Create generator of pkcs7-signature message
    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").setProvider("BC").build(privateKey);
    generator.addSignerInfoGenerator(
        new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(signer, certificate));
    generator.addCertificate(new X509CertificateHolder(certificate.getEncoded()));

    CMSTypedData cmsTypedData = new CMSProcessableByteArray(content);
    CMSSignedData cmsSignedData = generator.generate(cmsTypedData, false);
    return cmsSignedData.getEncoded();
}

但是我有另一个用户案例,我没有原始内容,只有它的哈希(sha256)Bouncycastle不支持pkcs7签名的“nonewithRSA”或“RSA”,所以我尝试使用自定义ContentSigner,而没有获得与原始内容版本相同的签名。

public byte[] signHash(final byte[] sha256) throws IOException,
    OperatorCreationException, CertificateEncodingException, CMSException {

    // Create generator of pkcs7-signature message
    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
    // custom content signer to bypass hash
    ContentSigner signer = new ContentSigner() {
        @Override public AlgorithmIdentifier getAlgorithmIdentifier() {
            return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSA");
        }

        @Override public OutputStream getOutputStream() {
            return new ByteArrayOutputStream();
        }

        @Override public byte[] getSignature() {
            try {
                Signature signer = Signature.getInstance("NONEwithRSA");
                signer.initSign(privateKey);
                signer.update(sha256);
                return signer.sign();
            } catch (Exception e){
            throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e);
            }
        }
    };

    generator.addSignerInfoGenerator(
        new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(signer, certificate));
    generator.addCertificate(new X509CertificateHolder(certificate.getEncoded()));

    CMSTypedData cmsTypedData = new CMSProcessableByteArray(sha256);
    CMSSignedData cmsSignedData = generator.generate(cmsTypedData, false);
    return cmsSignedData.getEncoded();
}
 // build digest
 MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
 messageDigest.update(sha256);
 byte[] outputDigest = messageDigest.digest();
 AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);
 DigestInfo di = new DigestInfo(sha256Aid, outputDigest);

 //sign SHA256 with RSA
 Signature rsaSignature = Signature.getInstance("RSA");
 rsaSignature.initSign(privateKey);
 byte[] encodedDigestInfo = di.toASN1Primitive().getEncoded();
 rsaSignature.update(encodedDigestInfo);
 return rsaSignature.sign();

共有1个答案

乐正秦斩
2023-03-14

找到了一个工作解决方案:

private static final String SIGNATURE_ALGO = "SHA256WithRSA";

/**
 * Get the pkcs7-signature from a document hash (sha256Hex)
 *
 * @param contentSha256Hex
 *     the original document content hash (sha256Hex) to be signed
 * @return the pkcs7 signature
 *
 * note: see TestSha1WithRsaAndAttributeTable() in bouncycastle/test/src/cms/test/SignedDataTest.cs
 * */
public byte[] signSha256Hex(final String contentSha256Hex)
    throws CertificateEncodingException, IOException, OperatorCreationException, CMSException, DecoderException {

    byte[] hash = Hex.decodeHex(contentSha256Hex);

    /*
     * The trick is to manually set digest attribute with hash value,
     * then generate signature without content.
     */

    // CMS attributes
    ASN1EncodableVector v = new ASN1EncodableVector();
    v.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(hash)))); // set digest (sha256)

    return signCms_Sha256WithRsa(
        new CMSAbsentContent(),
        new DefaultSignedAttributeTableGenerator(new AttributeTable(v)));

}

private byte[] signCms_Sha256WithRsa(CMSTypedData content, CMSAttributeTableGenerator signedAttributes)
    throws CMSException, IOException, CertificateEncodingException, OperatorCreationException {

    CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

    // content signer
    ContentSigner signer = new JcaContentSignerBuilder(SIGNATURE_ALGO).setProvider("BC").build(privateKey);
    generator.addSignerInfoGenerator(
        new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
            .setSignedAttributeGenerator(signedAttributes)
            .build(signer, certificate));

    // add certificate
    generator.addCertificate(new X509CertificateHolder(certificate.getEncoded()));

    // sign
    CMSSignedData cmsSignedData = generator.generate(content, false);
    return cmsSignedData.getEncoded();
}
 类似资料:
  • 我想做多个签名的pdf文件,像在一个工作流。我正在使用下面的代码签署我写的pdf文件,这工作很好。 签署文件 而且上面的代码工作得很好。我的新要求是添加多个签名。是否有任何方法可以重用此代码段。我经历了这,这,这,但没有运气。 除此之外,我尝试的是,创建了空白多个空白签名,并尝试附加签名。但它导致创建损坏的文件。我还尝试使用本链接中提到的方法创建文件。还对PDF文档进行了很好的文档数字签名 nul

  • 问题内容: 目前,我有一个客户端-服务器应用程序,给定一个PDF文件,使用服务器证书对其进行签名,将签名与原始文件一起附加,然后将输出返回给客户端(所有这些操作均通过PDFBox实现)。 我有一个签名处理程序,这是我的外部签名支持(其中内容为PDF文件) 它工作正常,但我在想-如果PDF文件太大而无法上传怎么办?例如:100mb …这将永远!鉴于此,我想弄清楚,如果不对PDF文件签名,是否可以仅对

  • 情况是我必须检查一个数字签名: 字符串1“A1005056807CE11EE2B4CE0025305725CFRCN=KED,OU=I0020266601,OU=SAPWebAS,O=SAPTrustCommunity,C=DE20130611102236”通过PKCS#7签名并通过HTTP-URL发送给我。 我在BASE64中获得签名的内容(在代码字符串sc中查找)。 现在我必须检查,如果Str

  • 目前,我有一个客户机-服务器应用程序,给定一个PDF文件,它对其进行签名(使用服务器证书),将签名附加到原始文件,并将输出返回给客户机(所有这些都是通过PDFBox实现的)。 我有一个签名处理程序,它是我的外部签名支持(其中的内容是PDF文件) 它工作得很好,但我在想--如果PDF文件太大无法上传怎么办?例如:100MB...这会花上很长时间的!鉴于此,我试图弄清楚,如果不签署PDF文件,是否可能

  • 我正在编写一个接收PKCS7数据(从签名的PDF文档中提取)的服务,并需要对其进行验证。 我使用iText7 PdfPKCS7进行验证,但签名验证总是失败。我可以从PKCS7读取所有其他信息(证书、时间戳等,我也用OpenSSL验证了这一点)。只有签名显示为无效。 下面是测试案例: 输出总是: 我想我在进口方面做错了什么,但就是找不到什么... 顺便说一句,验证其他pdf工具(Adobe DC、P

  • 我想使用PKCS7容器在PDF文件中创建分离签名。数据(哈希)是预先在另一个设备上用私钥签名的。我想创建一个PKCS7,其中包含签名的数据以及带有公钥的证书。如果不提供私钥并让库签名数据,我似乎无法创建带有bouncy castle的PKCS7。这似乎不起作用: