CMS 版本 2.2 SHA256WithRSAEncryption

CMS version 2.2 SHA256WithRSAEncryption

我需要根据这些要求签署一份 json 文档:CMS 2.2 版,使用 SHA256WithRSAEncryption 算法。我正在尝试这段代码,但我没有发现 属性 是 cms 2.2 版。

有效的代码是在 Java 中编写的,此代码由 api 提供商开发。他们在C#中没有例子。

import java.security.KeyStore;
import java.security.PrivateKey;
import java.util.Base64;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import br.gov.frameworkdemoiselle.certificate.signer.factory.PKCS7Factory;
import br.gov.frameworkdemoiselle.certificate.signer.pkcs7.PKCS7Signer;
import br.gov.frameworkdemoiselle.certificate.signer.pkcs7.bc.policies.ADRBCMS_2_2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Path("/")
@Api(value = "assinador")
public class AssinadorLojaFranca {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Insira um JSON no formato da API Loja Franca e gere seu Base64 assinado para consumo da API.", response = String.class)
    public Response assina(@QueryParam("cnpjLoja") String cnpjLoja, String payload) {
        try {
            if (cnpjLoja == null || cnpjLoja.trim().isEmpty()) {
                return Response.status(422).entity("Favor informar o cnpjLoja por query param na URL.").build();
            }

            byte[] fileToSign = payload.getBytes();

            // quando certificado em arquivo, precisa informar a senha
            char[] senha = CertificateUtils.getSenhaCertificado(cnpjLoja);

            // Para certificado em arquivo A1
            KeyStore ks = CertificateUtils.getKeyStoreFile(cnpjLoja);
            if (ks == null) {
                return Response.status(422)
                        .entity("Não foi possível encontrar o certificado para o cnpjLoja informado.").build();
            }

            String alias = CertificateUtils.getAlias(ks);

            /* Parametrizando o objeto doSign */
            PKCS7Signer signer = PKCS7Factory.getInstance().factoryDefault();
            signer.setCertificates(ks.getCertificateChain(alias));

            signer.setPrivateKey((PrivateKey) ks.getKey(alias, senha));

            signer.setSignaturePolicy(new ADRBCMS_2_2());

            // Assinatura atachada
            signer.setAttached(true);
            byte[] signature = signer.signer(fileToSign);

            /* Valida o conteudo antes de gravar em arquivo */
            if (signature != null) {
                Boolean valid = signer.check(fileToSign, signature);

                if (valid) {
                    System.out.println("A assinatura foi validada.");
                } else {
                    System.out.println("A assinatura foi invalidada!");
                }

                return Response.ok().entity(Base64.getEncoder().encode(signature))
                        .header("Content-Type", "application/text; charset=utf-8").build();
            }

            return Response.serverError().build();
        } catch (Exception ex) {
            ex.printStackTrace();
            return Response.serverError().build();
        }
    }
}

需要用C#实现。我没有找到 属性 在 class CmsSigner.

中设置 c# signer.setSignaturePolicy(new ADRBCMS_2_2())
private string AssinaJSON(string rJSON)
{
    string wRetorno = "";

    try
    {

        byte[] data = Encoding.UTF8.GetBytes(rJSON);

        SignedCms signedCms = new SignedCms(new ContentInfo(data), true);
        CmsSigner Signer = new CmsSigner(PUCert);
        Signer.DigestAlgorithm = new Oid("1.2.840.113549.1.1.11");
        signedCms.ComputeSignature(Signer);
        byte[] wResult = signedCms.Encode();
        wRetorno = Convert.ToBase64String(wResult);


    }
    catch (Exception ex) { }


    return wRetorno;

}

有趣,

无论如何我都试过了,但它从来没有达到由可用订阅者计费的那个。我还没有找到如何在 C# 中通过 SignedCms / CmsSigner 设置 CMS 策略版本 2.2。如何使用 DEMOISELLE 组件 (https://www.frameworkdemoiselle.gov.br/),仅在 Java 中可用。我已经联系了一个SERPRO,但我还没有回来。

我在这家公司工作。遵循使用 BouncyCastle + DOC-ICP 策略版本 2.2 在 C# 中实现的功能示例:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.Esf;

namespace assinador
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] entradaArray = File.ReadAllBytes(@"certificado/arquivoTeste.txt");

            AsymmetricKeyParameter chavePrivada;

            X509Certificate certificadoX509 = getCertificadoX509(@"certificado/certificado.p12", "123!@#", out chavePrivada);

            SHA512Managed hashSHA512 = new SHA512Managed();
            SHA256Managed hashSHA256 = new SHA256Managed();
            byte[] certificadoX509Hash = hashSHA256.ComputeHash(certificadoX509.GetEncoded());
            byte[] EntradaHash = hashSHA512.ComputeHash(entradaArray);

            CmsSignedDataGenerator geradorCms = new CmsSignedDataGenerator();

            //
            //atributos
            //
            Asn1EncodableVector atributosAssinados = new Asn1EncodableVector();

            //1.2.840.113549.1.9.3 -> ContentType
            //1.2.840.113549.1.7.1 -> RSA Security Data Inc
            atributosAssinados.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(CmsAttributes.ContentType, new DerSet(new DerObjectIdentifier("1.2.840.113549.1.7.1"))));

            //1.2.840.113549.1.9.5 -> Signing Time
            atributosAssinados.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(CmsAttributes.SigningTime, new DerSet(new DerUtcTime(DateTime.Now))));

            //1.2.840.113549.1.9.4 -> messageDigest
            atributosAssinados.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(CmsAttributes.MessageDigest, new DerSet(new DerOctetString(EntradaHash))));

            //2.16.840.1.101.3.4.2.3 -> SHA-512
            //2.16.840.1.101.3.4.2.1 -> SHA-256
            //1.2.840.113549.1.9.16.5.1 -> sigPolicyQualifier-spuri
            DerObjectIdentifier identificadorPolicyID = new DerObjectIdentifier("1.2.840.113549.1.9.16.2.15");
            byte[] policyHASH = System.Text.Encoding.ASCII.GetBytes("0F6FA2C6281981716C95C79899039844523B1C61C2C962289CDAC7811FEEE29E");
            List<SigPolicyQualifierInfo> sigPolicyQualifierInfos = new List<SigPolicyQualifierInfo>();
            Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier algoritmoIdentificador = new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.3");
            SigPolicyQualifierInfo bcSigPolicyQualifierInfo = new SigPolicyQualifierInfo(new DerObjectIdentifier("1.2.840.113549.1.9.16.5.1"), new DerIA5String("http://politicas.icpbrasil.gov.br/PA_AD_RB_v2_2.der"));
            sigPolicyQualifierInfos.Add(bcSigPolicyQualifierInfo);
            SignaturePolicyId signaturePolicyId = new SignaturePolicyId(DerObjectIdentifier.GetInstance(new DerObjectIdentifier("2.16.76.1.7.1.6.2.2")), new OtherHashAlgAndValue(algoritmoIdentificador, new DerOctetString(policyHASH)), sigPolicyQualifierInfos);
            atributosAssinados.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(identificadorPolicyID, new DerSet(signaturePolicyId)));

            //1.2.840.113549.1.9.16.2.47 -> id-aa-signingCertificateV2
            Org.BouncyCastle.Asn1.Ess.EssCertIDv2 essCertIDv2;
            essCertIDv2 = new Org.BouncyCastle.Asn1.Ess.EssCertIDv2(certificadoX509Hash);
            atributosAssinados.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(new DerObjectIdentifier("1.2.840.113549.1.9.16.2.47"), new DerSet(essCertIDv2)));

            AttributeTable atributosAssinadosTabela = new AttributeTable(atributosAssinados);

            //geradorCms.AddSigner(chavePrivada, certificadoX509, CmsSignedDataGenerator.DigestSha256, new DefaultSignedAttributeTableGenerator(atributosAssinadosTabela), null);
            geradorCms.AddSigner(chavePrivada, certificadoX509, CmsSignedDataGenerator.DigestSha512, new DefaultSignedAttributeTableGenerator(atributosAssinadosTabela), null);

            List<X509Certificate> certificadoX509Lista = new List<X509Certificate>();
            certificadoX509Lista.Add(certificadoX509);
            //storeCerts.AddRange(chain);

            X509CollectionStoreParameters parametrosArmazem = new X509CollectionStoreParameters(certificadoX509Lista);
            IX509Store armazemCertificado = X509StoreFactory.Create("CERTIFICATE/COLLECTION", parametrosArmazem);
            geradorCms.AddCertificates(armazemCertificado);

            var dadosAssinado = geradorCms.Generate(new CmsProcessableByteArray(entradaArray), true); // encapsulate = false for detached signature

            Console.WriteLine("Codificado => " + Convert.ToBase64String(dadosAssinado.GetEncoded()));
        }

        public static X509Certificate getCertificadoX509(string arquivoCertificado, string senha, out AsymmetricKeyParameter chavePrivada)
        {
            chavePrivada = null;
            using (FileStream certificadoStream = new FileStream(arquivoCertificado, FileMode.Open, FileAccess.Read))
            {
                Pkcs12Store armazemPkcs12 = new Pkcs12Store();
                armazemPkcs12.Load(certificadoStream, senha.ToCharArray());

                string certificadoCN = armazemPkcs12.Aliases.Cast<string>().FirstOrDefault(n => armazemPkcs12.IsKeyEntry(n));

                //Console.WriteLine("keyAlias => " + certificadoCN);

                chavePrivada = armazemPkcs12.GetKey(certificadoCN).Key;

                return (X509Certificate)armazemPkcs12.GetCertificate(certificadoCN).Certificate;
            }
        }
    }
}