Sign a document with CAdES-BES using Bouncy Castle





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















Starting from an autogenerated .pfx file, i need to understand if it's possibile to sign a document with CAdES-BES algorithm and save the result to a .p7m file.

All documentation that I found is old and incompatible with current Bouncy Castle version (1.8.4).



Here an old and NO MORE WORKING sample method:



public byte SignFile(String fileName, X509Certificate2 cert, ref string resSigned)
{
try
{
SHA256Managed hashSha256 = new SHA256Managed();
byte certHash = hashSha256.ComputeHash(cert.RawData);

EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2 { essCert1 });

Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2,new DerSet(scv2));
Asn1EncodableVector v = new Asn1EncodableVector();
v.Add(CertHAttribute);
Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;

dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
cms.MyAddSigner(rsa, certCopy, keyParameter, "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);
ArrayList certList = new ArrayList();
certList.Add(certCopy);
Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP =
new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
Org.BouncyCastle.X509.Store.IX509Store st1 =
Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);
cms.AddCertificates(st1);

FileInfo File__1 = new FileInfo(fileName);
CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
CmsSignedData Firmato = cms.Generate(file__2, true);
byte Encoded = Firmato.GetEncoded();
resSigned = "";
return Encoded;
}
catch (Exception ex)
{
resSigned = ex.ToString();
return null;
}
}


Here the CmsSignedDataGenWithRsaCsp.cs



using System;
using System.Collections;
using System.IO;

using Org.BouncyCastle.Asn1;
using Asn1 = Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.X509;

using Org.BouncyCastle.Cms;
using NetCrypto = System.Security.Cryptography;

namespace example
{
public class CmsSignedDataGenWithRsaCsp : CmsSignedGenerator
{
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;

private readonly ArrayList signerInfs = new ArrayList();

private class SignerInf
{
private readonly CmsSignedGenerator outer;

private readonly AsymmetricKeyParameter key;
private readonly NetCrypto.RSACryptoServiceProvider krProv;
private readonly SignerIdentifier signerIdentifier;
private readonly string digestOID;
private readonly string encOID;
private readonly CmsAttributeTableGenerator sAttr;
private readonly CmsAttributeTableGenerator unsAttr;
private readonly Asn1.Cms.AttributeTable baseSignedTable;

internal SignerInf(
CmsSignedGenerator outer,
NetCrypto.RSACryptoServiceProvider krProv,
AsymmetricKeyParameter key,
SignerIdentifier signerIdentifier,
string digestOID,
string encOID,
CmsAttributeTableGenerator sAttr,
CmsAttributeTableGenerator unsAttr,
Asn1.Cms.AttributeTable baseSignedTable)
{
this.outer = outer;
this.key = key;
this.krProv = krProv;
this.signerIdentifier = signerIdentifier;
this.digestOID = digestOID;
this.encOID = encOID;
this.sAttr = sAttr;
this.unsAttr = unsAttr;
this.baseSignedTable = baseSignedTable;
}

internal AlgorithmIdentifier DigestAlgorithmID
{
get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
}

internal CmsAttributeTableGenerator SignedAttributes
{
get { return sAttr; }
}

internal CmsAttributeTableGenerator UnsignedAttributes
{
get { return unsAttr; }
}

internal SignerInfo ToSignerInfo(
DerObjectIdentifier contentType,
CmsProcessable content,
SecureRandom random,
bool isCounterSignature)
{
AlgorithmIdentifier digAlgId = DigestAlgorithmID;
string digestName = Helper.GetDigestAlgName(digestOID);

IDigest dig = Helper.GetDigestInstance(digestName);

string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
//ISigner sig moved there where used

// TODO Optimise the case where more than one signer with same digest
if (content != null)
{
content.Write(new DigOutputStream(dig));
}

byte hash = DigestUtilities.DoFinal(dig);
outer._digests.Add(digestOID, hash.Clone());

Asn1Set signedAttr = null;
byte tmp;
if (sAttr != null)
{
IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);

// Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);

if (isCounterSignature)
{
Hashtable tmpSigned = signed.ToHashtable();
tmpSigned.Remove(CmsAttributes.ContentType);
signed = new Asn1.Cms.AttributeTable(tmpSigned);
}

// TODO Validate proposed signed attributes

signedAttr = outer.GetAttributeSet(signed);

// sig must be composed from the DER encoding.
tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
}
else
{
// TODO Use raw signature of the hash value instead
MemoryStream bOut = new MemoryStream();
if (content != null)
{
content.Write(bOut);
}
tmp = bOut.ToArray();
}

byte sigBytes = null;
if (krProv != null)
{
//sigBytes = krProv.SignData(tmp, digestName);

IDigest digProv = Helper.GetDigestInstance(digestName);
digProv.BlockUpdate(tmp, 0, tmp.Length);
byte hashProv = new byte[digProv.GetDigestSize()];
digProv.DoFinal(hashProv, 0);

sigBytes = krProv.SignHash(hashProv, digestOID);

}
else
{
ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
sig.Init(true, new ParametersWithRandom(key, random));
sig.BlockUpdate(tmp, 0, tmp.Length);
sigBytes = sig.GenerateSignature();
}

Asn1Set unsignedAttr = null;
if (unsAttr != null)
{
IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();

// Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);

// TODO Validate proposed unsigned attributes

unsignedAttr = outer.GetAttributeSet(unsigned);
}

// TODO [RSAPSS] Need the ability to specify non-default parameters
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
new DerObjectIdentifier(encOID), sigX509Parameters);

return new SignerInfo(signerIdentifier, digAlgId,
signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
}
}

public CmsSignedDataGenWithRsaCsp()
{
}

/// <summary>Constructor allowing specific source of randomness</summary>
/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
public CmsSignedDataGenWithRsaCsp(
SecureRandom rand)
: base(rand)
{
}

/// <summary>
/// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
/// </summary>
/// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
/// <param name="cert">cert certificate containing corresponding public key</param>
/// <param name="digestOID">digestOID digest algorithm OID</param>
public void AddSigner(
NetCrypto.RSACryptoServiceProvider crProv,
X509Certificate cert,
string digestOID)
{
AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
}

/// <summary>
/// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
/// </summary>
/// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
/// <param name="cert">certificate containing corresponding public key</param>
/// <param name="encryptionOID">digest encryption algorithm OID</param>
/// <param name="digestOID">digest algorithm OID</param>
public void AddSigner(
NetCrypto.RSACryptoServiceProvider crProv,
X509Certificate cert,
string encryptionOID,
string digestOID)
{
signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
new DefaultSignedAttributeTableGenerator(), null, null));
}

/// <summary>
/// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
/// </summary>
public void AddSigner(
NetCrypto.RSACryptoServiceProvider crProv,
byte subjectKeyID,
string encryptionOID,
string digestOID,
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
}

#region AddSigner for AsymmetricKeyParameter

/**
* add a signer - no attributes other than the default ones will be
* provided here.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param digestOID digest algorithm OID
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string digestOID)
{
AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
}

/**
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
* provided here.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string encryptionOID,
string digestOID)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
new DefaultSignedAttributeTableGenerator(), null, null));
}

/**
* add a signer - no attributes other than the default ones will be
* provided here.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string digestOID)
{
AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
}

/**
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
* provided here.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string encryptionOID,
string digestOID)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
digestOID, encryptionOID,
new DefaultSignedAttributeTableGenerator(), null, null));
}

/**
* add a signer with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string digestOID,
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
signedAttr, unsignedAttr);
}

/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string encryptionOID,
string digestOID,
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
digestOID, encryptionOID,
new DefaultSignedAttributeTableGenerator(signedAttr),
new SimpleAttributeTableGenerator(unsignedAttr),
signedAttr));
}

/**
* add a signer with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param subjectKeyID subjectKeyID of corresponding public key
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string digestOID,
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
new DefaultSignedAttributeTableGenerator(signedAttr),
new SimpleAttributeTableGenerator(unsignedAttr));
}

/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param subjectKeyID subjectKeyID of corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string encryptionOID,
string digestOID,
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
digestOID, encryptionOID,
new DefaultSignedAttributeTableGenerator(signedAttr),
new SimpleAttributeTableGenerator(unsignedAttr),
signedAttr));
}

/**
* add a signer with extra signed/unsigned attributes based on generators.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string digestOID,
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
signedAttrGen, unsignedAttrGen);
}

/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
X509Certificate cert,
string encryptionOID,
string digestOID,
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
digestOID, encryptionOID,
signedAttrGen, unsignedAttrGen, null));
}

/**
* add a signer with extra signed/unsigned attributes based on generators.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string digestOID,
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
signedAttrGen, unsignedAttrGen);
}

/**
* add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
*/
public void AddSigner(
AsymmetricKeyParameter privateKey,
byte subjectKeyID,
string encryptionOID,
string digestOID,
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
}

#endregion

protected string GetEncOid(
NetCrypto.RSACryptoServiceProvider crProv,
string digestOID)
{
string encOID = null;

if (crProv is NetCrypto.RSACryptoServiceProvider)
{
if ((crProv).PublicOnly)
throw new ArgumentException("Expected RSA private key");

encOID = EncryptionRsa;
}
/*else if (key is DsaPrivateKeyParameters)
{
if (!digestOID.Equals(DigestSha1))
throw new ArgumentException("can't mix DSA with anything but SHA1");

encOID = EncryptionDsa;
}
else if (key is ECPrivateKeyParameters)
{
ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
string algName = ecPrivKey.AlgorithmName;

if (algName == "ECGOST3410")
{
encOID = EncryptionECGost3410;
}
else
{
// TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
encOID = (string)ecAlgorithms[digestOID];

if (encOID == null)
throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
}
}
else if (key is Gost3410PrivateKeyParameters)
{
encOID = EncryptionGost3410;
}
else
{
throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
}*/

return encOID;
}


/**
* generate a signed object that for a CMS Signed Data object
*/
public CmsSignedData Generate(
CmsProcessable content)
{
return Generate(content, false);
}

/**
* generate a signed object that for a CMS Signed Data
* object - if encapsulate is true a copy
* of the message will be included in the signature. The content type
* is set according to the OID represented by the string signedContentType.
*/
public CmsSignedData Generate(
string signedContentType,
CmsProcessable content,
bool encapsulate)
{
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
Asn1EncodableVector signerInfos = new Asn1EncodableVector();

_digests.Clear(); // clear the current preserved digest state

//
// add the precalculated SignerInfo objects.
//
foreach (SignerInformation signer in _signers)
{
digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
signerInfos.Add(signer.ToSignerInfo());
}

//
// add the SignerInfo objects
//
bool isCounterSignature = (signedContentType == null);

DerObjectIdentifier contentTypeOID = isCounterSignature
? CmsObjectIdentifiers.Data
: new DerObjectIdentifier(signedContentType);

foreach (SignerInf signer in signerInfs)
{
try
{
digestAlgs.Add(signer.DigestAlgorithmID);
signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
}
catch (IOException e)
{
throw new CmsException("encoding error.", e);
}
catch (InvalidKeyException e)
{
throw new CmsException("key inappropriate for signature.", e);
}
catch (SignatureException e)
{
throw new CmsException("error creating signature.", e);
}
catch (CertificateEncodingException e)
{
throw new CmsException("error creating sid.", e);
}
}

Asn1Set certificates = null;

if (_certs.Count != 0)
{
certificates = CmsUtilities.CreateBerSetFromList(_certs);
}

Asn1Set certrevlist = null;

if (_crls.Count != 0)
{
certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
}

Asn1OctetString octs = null;
if (encapsulate)
{
MemoryStream bOut = new MemoryStream();
if (content != null)
{
try
{
content.Write(bOut);
}
catch (IOException e)
{
throw new CmsException("encapsulation error.", e);
}
}
octs = new BerOctetString(bOut.ToArray());
}

ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);

SignedData sd = new SignedData(
new DerSet(digestAlgs),
encInfo,
certificates,
certrevlist,
new DerSet(signerInfos));

ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

return new CmsSignedData(content, contentInfo);
}

/**
* generate a signed object that for a CMS Signed Data
* object - if encapsulate is true a copy
* of the message will be included in the signature with the
* default content type "data".
*/
public CmsSignedData Generate(
CmsProcessable content,
bool encapsulate)
{
return this.Generate(Data, content, encapsulate);
}
public SignerInformationStore GenerateCounterSigners(
SignerInformation signer)
{
return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
}

public static bool arrAreEquals(byte a, byte b)
{
bool res = true;

if (a.Length != b.Length) return false;

for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
{
return false;
}
}

return res;
}

}
}


This approach is correct for what i need to do, or I need to reimplement all?










share|improve this question































    1















    Starting from an autogenerated .pfx file, i need to understand if it's possibile to sign a document with CAdES-BES algorithm and save the result to a .p7m file.

    All documentation that I found is old and incompatible with current Bouncy Castle version (1.8.4).



    Here an old and NO MORE WORKING sample method:



    public byte SignFile(String fileName, X509Certificate2 cert, ref string resSigned)
    {
    try
    {
    SHA256Managed hashSha256 = new SHA256Managed();
    byte certHash = hashSha256.ComputeHash(cert.RawData);

    EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
    SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2 { essCert1 });

    Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2,new DerSet(scv2));
    Asn1EncodableVector v = new Asn1EncodableVector();
    v.Add(CertHAttribute);
    Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
    CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

    Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;

    dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
    Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
    cms.MyAddSigner(rsa, certCopy, keyParameter, "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);
    ArrayList certList = new ArrayList();
    certList.Add(certCopy);
    Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP =
    new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
    Org.BouncyCastle.X509.Store.IX509Store st1 =
    Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);
    cms.AddCertificates(st1);

    FileInfo File__1 = new FileInfo(fileName);
    CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
    CmsSignedData Firmato = cms.Generate(file__2, true);
    byte Encoded = Firmato.GetEncoded();
    resSigned = "";
    return Encoded;
    }
    catch (Exception ex)
    {
    resSigned = ex.ToString();
    return null;
    }
    }


    Here the CmsSignedDataGenWithRsaCsp.cs



    using System;
    using System.Collections;
    using System.IO;

    using Org.BouncyCastle.Asn1;
    using Asn1 = Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.Cms;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Security.Certificates;
    using Org.BouncyCastle.X509;

    using Org.BouncyCastle.Cms;
    using NetCrypto = System.Security.Cryptography;

    namespace example
    {
    public class CmsSignedDataGenWithRsaCsp : CmsSignedGenerator
    {
    private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;

    private readonly ArrayList signerInfs = new ArrayList();

    private class SignerInf
    {
    private readonly CmsSignedGenerator outer;

    private readonly AsymmetricKeyParameter key;
    private readonly NetCrypto.RSACryptoServiceProvider krProv;
    private readonly SignerIdentifier signerIdentifier;
    private readonly string digestOID;
    private readonly string encOID;
    private readonly CmsAttributeTableGenerator sAttr;
    private readonly CmsAttributeTableGenerator unsAttr;
    private readonly Asn1.Cms.AttributeTable baseSignedTable;

    internal SignerInf(
    CmsSignedGenerator outer,
    NetCrypto.RSACryptoServiceProvider krProv,
    AsymmetricKeyParameter key,
    SignerIdentifier signerIdentifier,
    string digestOID,
    string encOID,
    CmsAttributeTableGenerator sAttr,
    CmsAttributeTableGenerator unsAttr,
    Asn1.Cms.AttributeTable baseSignedTable)
    {
    this.outer = outer;
    this.key = key;
    this.krProv = krProv;
    this.signerIdentifier = signerIdentifier;
    this.digestOID = digestOID;
    this.encOID = encOID;
    this.sAttr = sAttr;
    this.unsAttr = unsAttr;
    this.baseSignedTable = baseSignedTable;
    }

    internal AlgorithmIdentifier DigestAlgorithmID
    {
    get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
    }

    internal CmsAttributeTableGenerator SignedAttributes
    {
    get { return sAttr; }
    }

    internal CmsAttributeTableGenerator UnsignedAttributes
    {
    get { return unsAttr; }
    }

    internal SignerInfo ToSignerInfo(
    DerObjectIdentifier contentType,
    CmsProcessable content,
    SecureRandom random,
    bool isCounterSignature)
    {
    AlgorithmIdentifier digAlgId = DigestAlgorithmID;
    string digestName = Helper.GetDigestAlgName(digestOID);

    IDigest dig = Helper.GetDigestInstance(digestName);

    string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
    //ISigner sig moved there where used

    // TODO Optimise the case where more than one signer with same digest
    if (content != null)
    {
    content.Write(new DigOutputStream(dig));
    }

    byte hash = DigestUtilities.DoFinal(dig);
    outer._digests.Add(digestOID, hash.Clone());

    Asn1Set signedAttr = null;
    byte tmp;
    if (sAttr != null)
    {
    IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);

    // Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
    Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);

    if (isCounterSignature)
    {
    Hashtable tmpSigned = signed.ToHashtable();
    tmpSigned.Remove(CmsAttributes.ContentType);
    signed = new Asn1.Cms.AttributeTable(tmpSigned);
    }

    // TODO Validate proposed signed attributes

    signedAttr = outer.GetAttributeSet(signed);

    // sig must be composed from the DER encoding.
    tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
    }
    else
    {
    // TODO Use raw signature of the hash value instead
    MemoryStream bOut = new MemoryStream();
    if (content != null)
    {
    content.Write(bOut);
    }
    tmp = bOut.ToArray();
    }

    byte sigBytes = null;
    if (krProv != null)
    {
    //sigBytes = krProv.SignData(tmp, digestName);

    IDigest digProv = Helper.GetDigestInstance(digestName);
    digProv.BlockUpdate(tmp, 0, tmp.Length);
    byte hashProv = new byte[digProv.GetDigestSize()];
    digProv.DoFinal(hashProv, 0);

    sigBytes = krProv.SignHash(hashProv, digestOID);

    }
    else
    {
    ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
    sig.Init(true, new ParametersWithRandom(key, random));
    sig.BlockUpdate(tmp, 0, tmp.Length);
    sigBytes = sig.GenerateSignature();
    }

    Asn1Set unsignedAttr = null;
    if (unsAttr != null)
    {
    IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
    baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();

    // Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
    Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);

    // TODO Validate proposed unsigned attributes

    unsignedAttr = outer.GetAttributeSet(unsigned);
    }

    // TODO [RSAPSS] Need the ability to specify non-default parameters
    Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
    AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
    new DerObjectIdentifier(encOID), sigX509Parameters);

    return new SignerInfo(signerIdentifier, digAlgId,
    signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
    }
    }

    public CmsSignedDataGenWithRsaCsp()
    {
    }

    /// <summary>Constructor allowing specific source of randomness</summary>
    /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
    public CmsSignedDataGenWithRsaCsp(
    SecureRandom rand)
    : base(rand)
    {
    }

    /// <summary>
    /// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
    /// </summary>
    /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
    /// <param name="cert">cert certificate containing corresponding public key</param>
    /// <param name="digestOID">digestOID digest algorithm OID</param>
    public void AddSigner(
    NetCrypto.RSACryptoServiceProvider crProv,
    X509Certificate cert,
    string digestOID)
    {
    AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
    }

    /// <summary>
    /// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
    /// </summary>
    /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
    /// <param name="cert">certificate containing corresponding public key</param>
    /// <param name="encryptionOID">digest encryption algorithm OID</param>
    /// <param name="digestOID">digest algorithm OID</param>
    public void AddSigner(
    NetCrypto.RSACryptoServiceProvider crProv,
    X509Certificate cert,
    string encryptionOID,
    string digestOID)
    {
    signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
    new DefaultSignedAttributeTableGenerator(), null, null));
    }

    /// <summary>
    /// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
    /// </summary>
    public void AddSigner(
    NetCrypto.RSACryptoServiceProvider crProv,
    byte subjectKeyID,
    string encryptionOID,
    string digestOID,
    CmsAttributeTableGenerator signedAttrGen,
    CmsAttributeTableGenerator unsignedAttrGen)
    {
    signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
    digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
    }

    #region AddSigner for AsymmetricKeyParameter

    /**
    * add a signer - no attributes other than the default ones will be
    * provided here.
    *
    * @param key signing key to use
    * @param cert certificate containing corresponding public key
    * @param digestOID digest algorithm OID
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string digestOID)
    {
    AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
    }

    /**
    * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
    * provided here.
    *
    * @param key signing key to use
    * @param cert certificate containing corresponding public key
    * @param encryptionOID digest encryption algorithm OID
    * @param digestOID digest algorithm OID
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string encryptionOID,
    string digestOID)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
    new DefaultSignedAttributeTableGenerator(), null, null));
    }

    /**
    * add a signer - no attributes other than the default ones will be
    * provided here.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string digestOID)
    {
    AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
    }

    /**
    * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
    * provided here.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string encryptionOID,
    string digestOID)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
    digestOID, encryptionOID,
    new DefaultSignedAttributeTableGenerator(), null, null));
    }

    /**
    * add a signer with extra signed/unsigned attributes.
    *
    * @param key signing key to use
    * @param cert certificate containing corresponding public key
    * @param digestOID digest algorithm OID
    * @param signedAttr table of attributes to be included in signature
    * @param unsignedAttr table of attributes to be included as unsigned
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string digestOID,
    Asn1.Cms.AttributeTable signedAttr,
    Asn1.Cms.AttributeTable unsignedAttr)
    {
    AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
    signedAttr, unsignedAttr);
    }

    /**
    * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
    *
    * @param key signing key to use
    * @param cert certificate containing corresponding public key
    * @param encryptionOID digest encryption algorithm OID
    * @param digestOID digest algorithm OID
    * @param signedAttr table of attributes to be included in signature
    * @param unsignedAttr table of attributes to be included as unsigned
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string encryptionOID,
    string digestOID,
    Asn1.Cms.AttributeTable signedAttr,
    Asn1.Cms.AttributeTable unsignedAttr)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
    digestOID, encryptionOID,
    new DefaultSignedAttributeTableGenerator(signedAttr),
    new SimpleAttributeTableGenerator(unsignedAttr),
    signedAttr));
    }

    /**
    * add a signer with extra signed/unsigned attributes.
    *
    * @param key signing key to use
    * @param subjectKeyID subjectKeyID of corresponding public key
    * @param digestOID digest algorithm OID
    * @param signedAttr table of attributes to be included in signature
    * @param unsignedAttr table of attributes to be included as unsigned
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string digestOID,
    Asn1.Cms.AttributeTable signedAttr,
    Asn1.Cms.AttributeTable unsignedAttr)
    {
    AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
    new DefaultSignedAttributeTableGenerator(signedAttr),
    new SimpleAttributeTableGenerator(unsignedAttr));
    }

    /**
    * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
    *
    * @param key signing key to use
    * @param subjectKeyID subjectKeyID of corresponding public key
    * @param encryptionOID digest encryption algorithm OID
    * @param digestOID digest algorithm OID
    * @param signedAttr table of attributes to be included in signature
    * @param unsignedAttr table of attributes to be included as unsigned
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string encryptionOID,
    string digestOID,
    Asn1.Cms.AttributeTable signedAttr,
    Asn1.Cms.AttributeTable unsignedAttr)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
    digestOID, encryptionOID,
    new DefaultSignedAttributeTableGenerator(signedAttr),
    new SimpleAttributeTableGenerator(unsignedAttr),
    signedAttr));
    }

    /**
    * add a signer with extra signed/unsigned attributes based on generators.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string digestOID,
    CmsAttributeTableGenerator signedAttrGen,
    CmsAttributeTableGenerator unsignedAttrGen)
    {
    AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
    signedAttrGen, unsignedAttrGen);
    }

    /**
    * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    X509Certificate cert,
    string encryptionOID,
    string digestOID,
    CmsAttributeTableGenerator signedAttrGen,
    CmsAttributeTableGenerator unsignedAttrGen)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
    digestOID, encryptionOID,
    signedAttrGen, unsignedAttrGen, null));
    }

    /**
    * add a signer with extra signed/unsigned attributes based on generators.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string digestOID,
    CmsAttributeTableGenerator signedAttrGen,
    CmsAttributeTableGenerator unsignedAttrGen)
    {
    AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
    signedAttrGen, unsignedAttrGen);
    }

    /**
    * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
    */
    public void AddSigner(
    AsymmetricKeyParameter privateKey,
    byte subjectKeyID,
    string encryptionOID,
    string digestOID,
    CmsAttributeTableGenerator signedAttrGen,
    CmsAttributeTableGenerator unsignedAttrGen)
    {
    signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
    digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
    }

    #endregion

    protected string GetEncOid(
    NetCrypto.RSACryptoServiceProvider crProv,
    string digestOID)
    {
    string encOID = null;

    if (crProv is NetCrypto.RSACryptoServiceProvider)
    {
    if ((crProv).PublicOnly)
    throw new ArgumentException("Expected RSA private key");

    encOID = EncryptionRsa;
    }
    /*else if (key is DsaPrivateKeyParameters)
    {
    if (!digestOID.Equals(DigestSha1))
    throw new ArgumentException("can't mix DSA with anything but SHA1");

    encOID = EncryptionDsa;
    }
    else if (key is ECPrivateKeyParameters)
    {
    ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
    string algName = ecPrivKey.AlgorithmName;

    if (algName == "ECGOST3410")
    {
    encOID = EncryptionECGost3410;
    }
    else
    {
    // TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
    encOID = (string)ecAlgorithms[digestOID];

    if (encOID == null)
    throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
    }
    }
    else if (key is Gost3410PrivateKeyParameters)
    {
    encOID = EncryptionGost3410;
    }
    else
    {
    throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
    }*/

    return encOID;
    }


    /**
    * generate a signed object that for a CMS Signed Data object
    */
    public CmsSignedData Generate(
    CmsProcessable content)
    {
    return Generate(content, false);
    }

    /**
    * generate a signed object that for a CMS Signed Data
    * object - if encapsulate is true a copy
    * of the message will be included in the signature. The content type
    * is set according to the OID represented by the string signedContentType.
    */
    public CmsSignedData Generate(
    string signedContentType,
    CmsProcessable content,
    bool encapsulate)
    {
    Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
    Asn1EncodableVector signerInfos = new Asn1EncodableVector();

    _digests.Clear(); // clear the current preserved digest state

    //
    // add the precalculated SignerInfo objects.
    //
    foreach (SignerInformation signer in _signers)
    {
    digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
    signerInfos.Add(signer.ToSignerInfo());
    }

    //
    // add the SignerInfo objects
    //
    bool isCounterSignature = (signedContentType == null);

    DerObjectIdentifier contentTypeOID = isCounterSignature
    ? CmsObjectIdentifiers.Data
    : new DerObjectIdentifier(signedContentType);

    foreach (SignerInf signer in signerInfs)
    {
    try
    {
    digestAlgs.Add(signer.DigestAlgorithmID);
    signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
    }
    catch (IOException e)
    {
    throw new CmsException("encoding error.", e);
    }
    catch (InvalidKeyException e)
    {
    throw new CmsException("key inappropriate for signature.", e);
    }
    catch (SignatureException e)
    {
    throw new CmsException("error creating signature.", e);
    }
    catch (CertificateEncodingException e)
    {
    throw new CmsException("error creating sid.", e);
    }
    }

    Asn1Set certificates = null;

    if (_certs.Count != 0)
    {
    certificates = CmsUtilities.CreateBerSetFromList(_certs);
    }

    Asn1Set certrevlist = null;

    if (_crls.Count != 0)
    {
    certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
    }

    Asn1OctetString octs = null;
    if (encapsulate)
    {
    MemoryStream bOut = new MemoryStream();
    if (content != null)
    {
    try
    {
    content.Write(bOut);
    }
    catch (IOException e)
    {
    throw new CmsException("encapsulation error.", e);
    }
    }
    octs = new BerOctetString(bOut.ToArray());
    }

    ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);

    SignedData sd = new SignedData(
    new DerSet(digestAlgs),
    encInfo,
    certificates,
    certrevlist,
    new DerSet(signerInfos));

    ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

    return new CmsSignedData(content, contentInfo);
    }

    /**
    * generate a signed object that for a CMS Signed Data
    * object - if encapsulate is true a copy
    * of the message will be included in the signature with the
    * default content type "data".
    */
    public CmsSignedData Generate(
    CmsProcessable content,
    bool encapsulate)
    {
    return this.Generate(Data, content, encapsulate);
    }
    public SignerInformationStore GenerateCounterSigners(
    SignerInformation signer)
    {
    return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
    }

    public static bool arrAreEquals(byte a, byte b)
    {
    bool res = true;

    if (a.Length != b.Length) return false;

    for (int i = 0; i < a.Length; i++)
    {
    if (a[i] != b[i])
    {
    return false;
    }
    }

    return res;
    }

    }
    }


    This approach is correct for what i need to do, or I need to reimplement all?










    share|improve this question



























      1












      1








      1








      Starting from an autogenerated .pfx file, i need to understand if it's possibile to sign a document with CAdES-BES algorithm and save the result to a .p7m file.

      All documentation that I found is old and incompatible with current Bouncy Castle version (1.8.4).



      Here an old and NO MORE WORKING sample method:



      public byte SignFile(String fileName, X509Certificate2 cert, ref string resSigned)
      {
      try
      {
      SHA256Managed hashSha256 = new SHA256Managed();
      byte certHash = hashSha256.ComputeHash(cert.RawData);

      EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
      SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2 { essCert1 });

      Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2,new DerSet(scv2));
      Asn1EncodableVector v = new Asn1EncodableVector();
      v.Add(CertHAttribute);
      Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
      CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

      Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;

      dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
      Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
      cms.MyAddSigner(rsa, certCopy, keyParameter, "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);
      ArrayList certList = new ArrayList();
      certList.Add(certCopy);
      Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP =
      new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
      Org.BouncyCastle.X509.Store.IX509Store st1 =
      Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);
      cms.AddCertificates(st1);

      FileInfo File__1 = new FileInfo(fileName);
      CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
      CmsSignedData Firmato = cms.Generate(file__2, true);
      byte Encoded = Firmato.GetEncoded();
      resSigned = "";
      return Encoded;
      }
      catch (Exception ex)
      {
      resSigned = ex.ToString();
      return null;
      }
      }


      Here the CmsSignedDataGenWithRsaCsp.cs



      using System;
      using System.Collections;
      using System.IO;

      using Org.BouncyCastle.Asn1;
      using Asn1 = Org.BouncyCastle.Asn1;
      using Org.BouncyCastle.Asn1.Cms;
      using Org.BouncyCastle.Asn1.X509;
      using Org.BouncyCastle.Crypto;
      using Org.BouncyCastle.Crypto.Parameters;
      using Org.BouncyCastle.Security;
      using Org.BouncyCastle.Security.Certificates;
      using Org.BouncyCastle.X509;

      using Org.BouncyCastle.Cms;
      using NetCrypto = System.Security.Cryptography;

      namespace example
      {
      public class CmsSignedDataGenWithRsaCsp : CmsSignedGenerator
      {
      private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;

      private readonly ArrayList signerInfs = new ArrayList();

      private class SignerInf
      {
      private readonly CmsSignedGenerator outer;

      private readonly AsymmetricKeyParameter key;
      private readonly NetCrypto.RSACryptoServiceProvider krProv;
      private readonly SignerIdentifier signerIdentifier;
      private readonly string digestOID;
      private readonly string encOID;
      private readonly CmsAttributeTableGenerator sAttr;
      private readonly CmsAttributeTableGenerator unsAttr;
      private readonly Asn1.Cms.AttributeTable baseSignedTable;

      internal SignerInf(
      CmsSignedGenerator outer,
      NetCrypto.RSACryptoServiceProvider krProv,
      AsymmetricKeyParameter key,
      SignerIdentifier signerIdentifier,
      string digestOID,
      string encOID,
      CmsAttributeTableGenerator sAttr,
      CmsAttributeTableGenerator unsAttr,
      Asn1.Cms.AttributeTable baseSignedTable)
      {
      this.outer = outer;
      this.key = key;
      this.krProv = krProv;
      this.signerIdentifier = signerIdentifier;
      this.digestOID = digestOID;
      this.encOID = encOID;
      this.sAttr = sAttr;
      this.unsAttr = unsAttr;
      this.baseSignedTable = baseSignedTable;
      }

      internal AlgorithmIdentifier DigestAlgorithmID
      {
      get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
      }

      internal CmsAttributeTableGenerator SignedAttributes
      {
      get { return sAttr; }
      }

      internal CmsAttributeTableGenerator UnsignedAttributes
      {
      get { return unsAttr; }
      }

      internal SignerInfo ToSignerInfo(
      DerObjectIdentifier contentType,
      CmsProcessable content,
      SecureRandom random,
      bool isCounterSignature)
      {
      AlgorithmIdentifier digAlgId = DigestAlgorithmID;
      string digestName = Helper.GetDigestAlgName(digestOID);

      IDigest dig = Helper.GetDigestInstance(digestName);

      string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
      //ISigner sig moved there where used

      // TODO Optimise the case where more than one signer with same digest
      if (content != null)
      {
      content.Write(new DigOutputStream(dig));
      }

      byte hash = DigestUtilities.DoFinal(dig);
      outer._digests.Add(digestOID, hash.Clone());

      Asn1Set signedAttr = null;
      byte tmp;
      if (sAttr != null)
      {
      IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);

      // Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
      Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);

      if (isCounterSignature)
      {
      Hashtable tmpSigned = signed.ToHashtable();
      tmpSigned.Remove(CmsAttributes.ContentType);
      signed = new Asn1.Cms.AttributeTable(tmpSigned);
      }

      // TODO Validate proposed signed attributes

      signedAttr = outer.GetAttributeSet(signed);

      // sig must be composed from the DER encoding.
      tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
      }
      else
      {
      // TODO Use raw signature of the hash value instead
      MemoryStream bOut = new MemoryStream();
      if (content != null)
      {
      content.Write(bOut);
      }
      tmp = bOut.ToArray();
      }

      byte sigBytes = null;
      if (krProv != null)
      {
      //sigBytes = krProv.SignData(tmp, digestName);

      IDigest digProv = Helper.GetDigestInstance(digestName);
      digProv.BlockUpdate(tmp, 0, tmp.Length);
      byte hashProv = new byte[digProv.GetDigestSize()];
      digProv.DoFinal(hashProv, 0);

      sigBytes = krProv.SignHash(hashProv, digestOID);

      }
      else
      {
      ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
      sig.Init(true, new ParametersWithRandom(key, random));
      sig.BlockUpdate(tmp, 0, tmp.Length);
      sigBytes = sig.GenerateSignature();
      }

      Asn1Set unsignedAttr = null;
      if (unsAttr != null)
      {
      IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
      baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();

      // Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
      Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);

      // TODO Validate proposed unsigned attributes

      unsignedAttr = outer.GetAttributeSet(unsigned);
      }

      // TODO [RSAPSS] Need the ability to specify non-default parameters
      Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
      AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
      new DerObjectIdentifier(encOID), sigX509Parameters);

      return new SignerInfo(signerIdentifier, digAlgId,
      signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
      }
      }

      public CmsSignedDataGenWithRsaCsp()
      {
      }

      /// <summary>Constructor allowing specific source of randomness</summary>
      /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
      public CmsSignedDataGenWithRsaCsp(
      SecureRandom rand)
      : base(rand)
      {
      }

      /// <summary>
      /// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
      /// </summary>
      /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
      /// <param name="cert">cert certificate containing corresponding public key</param>
      /// <param name="digestOID">digestOID digest algorithm OID</param>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      X509Certificate cert,
      string digestOID)
      {
      AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
      }

      /// <summary>
      /// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
      /// </summary>
      /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
      /// <param name="cert">certificate containing corresponding public key</param>
      /// <param name="encryptionOID">digest encryption algorithm OID</param>
      /// <param name="digestOID">digest algorithm OID</param>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      X509Certificate cert,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /// <summary>
      /// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
      /// </summary>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
      }

      #region AddSigner for AsymmetricKeyParameter

      /**
      * add a signer - no attributes other than the default ones will be
      * provided here.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param digestOID digest algorithm OID
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
      }

      /**
      * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
      * provided here.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /**
      * add a signer - no attributes other than the default ones will be
      * provided here.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID)
      {
      AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
      }

      /**
      * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
      * provided here.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /**
      * add a signer with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
      signedAttr, unsignedAttr);
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr),
      signedAttr));
      }

      /**
      * add a signer with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param subjectKeyID subjectKeyID of corresponding public key
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr));
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param subjectKeyID subjectKeyID of corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr),
      signedAttr));
      }

      /**
      * add a signer with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
      signedAttrGen, unsignedAttrGen);
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
      digestOID, encryptionOID,
      signedAttrGen, unsignedAttrGen, null));
      }

      /**
      * add a signer with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
      signedAttrGen, unsignedAttrGen);
      }

      /**
      * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
      }

      #endregion

      protected string GetEncOid(
      NetCrypto.RSACryptoServiceProvider crProv,
      string digestOID)
      {
      string encOID = null;

      if (crProv is NetCrypto.RSACryptoServiceProvider)
      {
      if ((crProv).PublicOnly)
      throw new ArgumentException("Expected RSA private key");

      encOID = EncryptionRsa;
      }
      /*else if (key is DsaPrivateKeyParameters)
      {
      if (!digestOID.Equals(DigestSha1))
      throw new ArgumentException("can't mix DSA with anything but SHA1");

      encOID = EncryptionDsa;
      }
      else if (key is ECPrivateKeyParameters)
      {
      ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
      string algName = ecPrivKey.AlgorithmName;

      if (algName == "ECGOST3410")
      {
      encOID = EncryptionECGost3410;
      }
      else
      {
      // TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
      encOID = (string)ecAlgorithms[digestOID];

      if (encOID == null)
      throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
      }
      }
      else if (key is Gost3410PrivateKeyParameters)
      {
      encOID = EncryptionGost3410;
      }
      else
      {
      throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
      }*/

      return encOID;
      }


      /**
      * generate a signed object that for a CMS Signed Data object
      */
      public CmsSignedData Generate(
      CmsProcessable content)
      {
      return Generate(content, false);
      }

      /**
      * generate a signed object that for a CMS Signed Data
      * object - if encapsulate is true a copy
      * of the message will be included in the signature. The content type
      * is set according to the OID represented by the string signedContentType.
      */
      public CmsSignedData Generate(
      string signedContentType,
      CmsProcessable content,
      bool encapsulate)
      {
      Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
      Asn1EncodableVector signerInfos = new Asn1EncodableVector();

      _digests.Clear(); // clear the current preserved digest state

      //
      // add the precalculated SignerInfo objects.
      //
      foreach (SignerInformation signer in _signers)
      {
      digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
      signerInfos.Add(signer.ToSignerInfo());
      }

      //
      // add the SignerInfo objects
      //
      bool isCounterSignature = (signedContentType == null);

      DerObjectIdentifier contentTypeOID = isCounterSignature
      ? CmsObjectIdentifiers.Data
      : new DerObjectIdentifier(signedContentType);

      foreach (SignerInf signer in signerInfs)
      {
      try
      {
      digestAlgs.Add(signer.DigestAlgorithmID);
      signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
      }
      catch (IOException e)
      {
      throw new CmsException("encoding error.", e);
      }
      catch (InvalidKeyException e)
      {
      throw new CmsException("key inappropriate for signature.", e);
      }
      catch (SignatureException e)
      {
      throw new CmsException("error creating signature.", e);
      }
      catch (CertificateEncodingException e)
      {
      throw new CmsException("error creating sid.", e);
      }
      }

      Asn1Set certificates = null;

      if (_certs.Count != 0)
      {
      certificates = CmsUtilities.CreateBerSetFromList(_certs);
      }

      Asn1Set certrevlist = null;

      if (_crls.Count != 0)
      {
      certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
      }

      Asn1OctetString octs = null;
      if (encapsulate)
      {
      MemoryStream bOut = new MemoryStream();
      if (content != null)
      {
      try
      {
      content.Write(bOut);
      }
      catch (IOException e)
      {
      throw new CmsException("encapsulation error.", e);
      }
      }
      octs = new BerOctetString(bOut.ToArray());
      }

      ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);

      SignedData sd = new SignedData(
      new DerSet(digestAlgs),
      encInfo,
      certificates,
      certrevlist,
      new DerSet(signerInfos));

      ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

      return new CmsSignedData(content, contentInfo);
      }

      /**
      * generate a signed object that for a CMS Signed Data
      * object - if encapsulate is true a copy
      * of the message will be included in the signature with the
      * default content type "data".
      */
      public CmsSignedData Generate(
      CmsProcessable content,
      bool encapsulate)
      {
      return this.Generate(Data, content, encapsulate);
      }
      public SignerInformationStore GenerateCounterSigners(
      SignerInformation signer)
      {
      return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
      }

      public static bool arrAreEquals(byte a, byte b)
      {
      bool res = true;

      if (a.Length != b.Length) return false;

      for (int i = 0; i < a.Length; i++)
      {
      if (a[i] != b[i])
      {
      return false;
      }
      }

      return res;
      }

      }
      }


      This approach is correct for what i need to do, or I need to reimplement all?










      share|improve this question
















      Starting from an autogenerated .pfx file, i need to understand if it's possibile to sign a document with CAdES-BES algorithm and save the result to a .p7m file.

      All documentation that I found is old and incompatible with current Bouncy Castle version (1.8.4).



      Here an old and NO MORE WORKING sample method:



      public byte SignFile(String fileName, X509Certificate2 cert, ref string resSigned)
      {
      try
      {
      SHA256Managed hashSha256 = new SHA256Managed();
      byte certHash = hashSha256.ComputeHash(cert.RawData);

      EssCertIDv2 essCert1 = new EssCertIDv2(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"), certHash);
      SigningCertificateV2 scv2 = new SigningCertificateV2(new EssCertIDv2 { essCert1 });

      Org.BouncyCastle.Asn1.Cms.Attribute CertHAttribute = new Org.BouncyCastle.Asn1.Cms.Attribute(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdAASigningCertificateV2,new DerSet(scv2));
      Asn1EncodableVector v = new Asn1EncodableVector();
      v.Add(CertHAttribute);
      Org.BouncyCastle.Asn1.Cms.AttributeTable AT = new Org.BouncyCastle.Asn1.Cms.AttributeTable(v);
      CmsSignedDataGenWithRsaCsp cms = new CmsSignedDataGenWithRsaCsp();

      Org.BouncyCastle.Crypto.AsymmetricKeyParameter keyParameter = null;

      dynamic rsa = (RSACryptoServiceProvider)cert.PrivateKey;
      Org.BouncyCastle.X509.X509Certificate certCopy = DotNetUtilities.FromX509Certificate(cert);
      cms.MyAddSigner(rsa, certCopy, keyParameter, "1.2.840.113549.1.1.1", "2.16.840.1.101.3.4.2.1", AT, null);
      ArrayList certList = new ArrayList();
      certList.Add(certCopy);
      Org.BouncyCastle.X509.Store.X509CollectionStoreParameters PP =
      new Org.BouncyCastle.X509.Store.X509CollectionStoreParameters(certList);
      Org.BouncyCastle.X509.Store.IX509Store st1 =
      Org.BouncyCastle.X509.Store.X509StoreFactory.Create("CERTIFICATE/COLLECTION", PP);
      cms.AddCertificates(st1);

      FileInfo File__1 = new FileInfo(fileName);
      CmsProcessableFile file__2 = new CmsProcessableFile(File__1);
      CmsSignedData Firmato = cms.Generate(file__2, true);
      byte Encoded = Firmato.GetEncoded();
      resSigned = "";
      return Encoded;
      }
      catch (Exception ex)
      {
      resSigned = ex.ToString();
      return null;
      }
      }


      Here the CmsSignedDataGenWithRsaCsp.cs



      using System;
      using System.Collections;
      using System.IO;

      using Org.BouncyCastle.Asn1;
      using Asn1 = Org.BouncyCastle.Asn1;
      using Org.BouncyCastle.Asn1.Cms;
      using Org.BouncyCastle.Asn1.X509;
      using Org.BouncyCastle.Crypto;
      using Org.BouncyCastle.Crypto.Parameters;
      using Org.BouncyCastle.Security;
      using Org.BouncyCastle.Security.Certificates;
      using Org.BouncyCastle.X509;

      using Org.BouncyCastle.Cms;
      using NetCrypto = System.Security.Cryptography;

      namespace example
      {
      public class CmsSignedDataGenWithRsaCsp : CmsSignedGenerator
      {
      private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;

      private readonly ArrayList signerInfs = new ArrayList();

      private class SignerInf
      {
      private readonly CmsSignedGenerator outer;

      private readonly AsymmetricKeyParameter key;
      private readonly NetCrypto.RSACryptoServiceProvider krProv;
      private readonly SignerIdentifier signerIdentifier;
      private readonly string digestOID;
      private readonly string encOID;
      private readonly CmsAttributeTableGenerator sAttr;
      private readonly CmsAttributeTableGenerator unsAttr;
      private readonly Asn1.Cms.AttributeTable baseSignedTable;

      internal SignerInf(
      CmsSignedGenerator outer,
      NetCrypto.RSACryptoServiceProvider krProv,
      AsymmetricKeyParameter key,
      SignerIdentifier signerIdentifier,
      string digestOID,
      string encOID,
      CmsAttributeTableGenerator sAttr,
      CmsAttributeTableGenerator unsAttr,
      Asn1.Cms.AttributeTable baseSignedTable)
      {
      this.outer = outer;
      this.key = key;
      this.krProv = krProv;
      this.signerIdentifier = signerIdentifier;
      this.digestOID = digestOID;
      this.encOID = encOID;
      this.sAttr = sAttr;
      this.unsAttr = unsAttr;
      this.baseSignedTable = baseSignedTable;
      }

      internal AlgorithmIdentifier DigestAlgorithmID
      {
      get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
      }

      internal CmsAttributeTableGenerator SignedAttributes
      {
      get { return sAttr; }
      }

      internal CmsAttributeTableGenerator UnsignedAttributes
      {
      get { return unsAttr; }
      }

      internal SignerInfo ToSignerInfo(
      DerObjectIdentifier contentType,
      CmsProcessable content,
      SecureRandom random,
      bool isCounterSignature)
      {
      AlgorithmIdentifier digAlgId = DigestAlgorithmID;
      string digestName = Helper.GetDigestAlgName(digestOID);

      IDigest dig = Helper.GetDigestInstance(digestName);

      string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
      //ISigner sig moved there where used

      // TODO Optimise the case where more than one signer with same digest
      if (content != null)
      {
      content.Write(new DigOutputStream(dig));
      }

      byte hash = DigestUtilities.DoFinal(dig);
      outer._digests.Add(digestOID, hash.Clone());

      Asn1Set signedAttr = null;
      byte tmp;
      if (sAttr != null)
      {
      IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);

      // Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
      Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);

      if (isCounterSignature)
      {
      Hashtable tmpSigned = signed.ToHashtable();
      tmpSigned.Remove(CmsAttributes.ContentType);
      signed = new Asn1.Cms.AttributeTable(tmpSigned);
      }

      // TODO Validate proposed signed attributes

      signedAttr = outer.GetAttributeSet(signed);

      // sig must be composed from the DER encoding.
      tmp = signedAttr.GetEncoded(Asn1Encodable.Der);
      }
      else
      {
      // TODO Use raw signature of the hash value instead
      MemoryStream bOut = new MemoryStream();
      if (content != null)
      {
      content.Write(bOut);
      }
      tmp = bOut.ToArray();
      }

      byte sigBytes = null;
      if (krProv != null)
      {
      //sigBytes = krProv.SignData(tmp, digestName);

      IDigest digProv = Helper.GetDigestInstance(digestName);
      digProv.BlockUpdate(tmp, 0, tmp.Length);
      byte hashProv = new byte[digProv.GetDigestSize()];
      digProv.DoFinal(hashProv, 0);

      sigBytes = krProv.SignHash(hashProv, digestOID);

      }
      else
      {
      ISigner sig = Helper.GetSignatureInstance(signatureName);//was moved
      sig.Init(true, new ParametersWithRandom(key, random));
      sig.BlockUpdate(tmp, 0, tmp.Length);
      sigBytes = sig.GenerateSignature();
      }

      Asn1Set unsignedAttr = null;
      if (unsAttr != null)
      {
      IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
      baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();

      // Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
      Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);

      // TODO Validate proposed unsigned attributes

      unsignedAttr = outer.GetAttributeSet(unsigned);
      }

      // TODO [RSAPSS] Need the ability to specify non-default parameters
      Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
      AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
      new DerObjectIdentifier(encOID), sigX509Parameters);

      return new SignerInfo(signerIdentifier, digAlgId,
      signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
      }
      }

      public CmsSignedDataGenWithRsaCsp()
      {
      }

      /// <summary>Constructor allowing specific source of randomness</summary>
      /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
      public CmsSignedDataGenWithRsaCsp(
      SecureRandom rand)
      : base(rand)
      {
      }

      /// <summary>
      /// add a signer - no attributes other than the default ones will be provided here для RSACryptoServiceProvider
      /// </summary>
      /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
      /// <param name="cert">cert certificate containing corresponding public key</param>
      /// <param name="digestOID">digestOID digest algorithm OID</param>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      X509Certificate cert,
      string digestOID)
      {
      AddSigner(crProv, cert, GetEncOid(crProv, digestOID), digestOID);
      }

      /// <summary>
      /// add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be provided here.
      /// </summary>
      /// <param name="crProv">RSACryptoServiceProvider використовується для підписування</param>
      /// <param name="cert">certificate containing corresponding public key</param>
      /// <param name="encryptionOID">digest encryption algorithm OID</param>
      /// <param name="digestOID">digest algorithm OID</param>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      X509Certificate cert,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(cert), digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /// <summary>
      /// add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators
      /// </summary>
      public void AddSigner(
      NetCrypto.RSACryptoServiceProvider crProv,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, crProv, null, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
      }

      #region AddSigner for AsymmetricKeyParameter

      /**
      * add a signer - no attributes other than the default ones will be
      * provided here.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param digestOID digest algorithm OID
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
      }

      /**
      * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
      * provided here.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert), digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /**
      * add a signer - no attributes other than the default ones will be
      * provided here.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID)
      {
      AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
      }

      /**
      * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
      * provided here.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(), null, null));
      }

      /**
      * add a signer with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
      signedAttr, unsignedAttr);
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param cert certificate containing corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr),
      signedAttr));
      }

      /**
      * add a signer with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param subjectKeyID subjectKeyID of corresponding public key
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr));
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
      *
      * @param key signing key to use
      * @param subjectKeyID subjectKeyID of corresponding public key
      * @param encryptionOID digest encryption algorithm OID
      * @param digestOID digest algorithm OID
      * @param signedAttr table of attributes to be included in signature
      * @param unsignedAttr table of attributes to be included as unsigned
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      Asn1.Cms.AttributeTable signedAttr,
      Asn1.Cms.AttributeTable unsignedAttr)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID,
      new DefaultSignedAttributeTableGenerator(signedAttr),
      new SimpleAttributeTableGenerator(unsignedAttr),
      signedAttr));
      }

      /**
      * add a signer with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
      signedAttrGen, unsignedAttrGen);
      }

      /**
      * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      X509Certificate cert,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(cert),
      digestOID, encryptionOID,
      signedAttrGen, unsignedAttrGen, null));
      }

      /**
      * add a signer with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      AddSigner(privateKey, subjectKeyID, digestOID, GetEncOid(privateKey, digestOID),
      signedAttrGen, unsignedAttrGen);
      }

      /**
      * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
      */
      public void AddSigner(
      AsymmetricKeyParameter privateKey,
      byte subjectKeyID,
      string encryptionOID,
      string digestOID,
      CmsAttributeTableGenerator signedAttrGen,
      CmsAttributeTableGenerator unsignedAttrGen)
      {
      signerInfs.Add(new SignerInf(this, null, privateKey, GetSignerIdentifier(subjectKeyID),
      digestOID, encryptionOID, signedAttrGen, unsignedAttrGen, null));
      }

      #endregion

      protected string GetEncOid(
      NetCrypto.RSACryptoServiceProvider crProv,
      string digestOID)
      {
      string encOID = null;

      if (crProv is NetCrypto.RSACryptoServiceProvider)
      {
      if ((crProv).PublicOnly)
      throw new ArgumentException("Expected RSA private key");

      encOID = EncryptionRsa;
      }
      /*else if (key is DsaPrivateKeyParameters)
      {
      if (!digestOID.Equals(DigestSha1))
      throw new ArgumentException("can't mix DSA with anything but SHA1");

      encOID = EncryptionDsa;
      }
      else if (key is ECPrivateKeyParameters)
      {
      ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
      string algName = ecPrivKey.AlgorithmName;

      if (algName == "ECGOST3410")
      {
      encOID = EncryptionECGost3410;
      }
      else
      {
      // TO DO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
      encOID = (string)ecAlgorithms[digestOID];

      if (encOID == null)
      throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
      }
      }
      else if (key is Gost3410PrivateKeyParameters)
      {
      encOID = EncryptionGost3410;
      }
      else
      {
      throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
      }*/

      return encOID;
      }


      /**
      * generate a signed object that for a CMS Signed Data object
      */
      public CmsSignedData Generate(
      CmsProcessable content)
      {
      return Generate(content, false);
      }

      /**
      * generate a signed object that for a CMS Signed Data
      * object - if encapsulate is true a copy
      * of the message will be included in the signature. The content type
      * is set according to the OID represented by the string signedContentType.
      */
      public CmsSignedData Generate(
      string signedContentType,
      CmsProcessable content,
      bool encapsulate)
      {
      Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
      Asn1EncodableVector signerInfos = new Asn1EncodableVector();

      _digests.Clear(); // clear the current preserved digest state

      //
      // add the precalculated SignerInfo objects.
      //
      foreach (SignerInformation signer in _signers)
      {
      digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
      signerInfos.Add(signer.ToSignerInfo());
      }

      //
      // add the SignerInfo objects
      //
      bool isCounterSignature = (signedContentType == null);

      DerObjectIdentifier contentTypeOID = isCounterSignature
      ? CmsObjectIdentifiers.Data
      : new DerObjectIdentifier(signedContentType);

      foreach (SignerInf signer in signerInfs)
      {
      try
      {
      digestAlgs.Add(signer.DigestAlgorithmID);
      signerInfos.Add(signer.ToSignerInfo(contentTypeOID, content, rand, isCounterSignature));
      }
      catch (IOException e)
      {
      throw new CmsException("encoding error.", e);
      }
      catch (InvalidKeyException e)
      {
      throw new CmsException("key inappropriate for signature.", e);
      }
      catch (SignatureException e)
      {
      throw new CmsException("error creating signature.", e);
      }
      catch (CertificateEncodingException e)
      {
      throw new CmsException("error creating sid.", e);
      }
      }

      Asn1Set certificates = null;

      if (_certs.Count != 0)
      {
      certificates = CmsUtilities.CreateBerSetFromList(_certs);
      }

      Asn1Set certrevlist = null;

      if (_crls.Count != 0)
      {
      certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
      }

      Asn1OctetString octs = null;
      if (encapsulate)
      {
      MemoryStream bOut = new MemoryStream();
      if (content != null)
      {
      try
      {
      content.Write(bOut);
      }
      catch (IOException e)
      {
      throw new CmsException("encapsulation error.", e);
      }
      }
      octs = new BerOctetString(bOut.ToArray());
      }

      ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);

      SignedData sd = new SignedData(
      new DerSet(digestAlgs),
      encInfo,
      certificates,
      certrevlist,
      new DerSet(signerInfos));

      ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

      return new CmsSignedData(content, contentInfo);
      }

      /**
      * generate a signed object that for a CMS Signed Data
      * object - if encapsulate is true a copy
      * of the message will be included in the signature with the
      * default content type "data".
      */
      public CmsSignedData Generate(
      CmsProcessable content,
      bool encapsulate)
      {
      return this.Generate(Data, content, encapsulate);
      }
      public SignerInformationStore GenerateCounterSigners(
      SignerInformation signer)
      {
      return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
      }

      public static bool arrAreEquals(byte a, byte b)
      {
      bool res = true;

      if (a.Length != b.Length) return false;

      for (int i = 0; i < a.Length; i++)
      {
      if (a[i] != b[i])
      {
      return false;
      }
      }

      return res;
      }

      }
      }


      This approach is correct for what i need to do, or I need to reimplement all?







      c# bouncycastle sign pfx






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 14:35







      Marco Ferrari

















      asked Nov 23 '18 at 14:02









      Marco FerrariMarco Ferrari

      234




      234
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Here a possibile solution:



          public static void SignFile(string filePath,X509Certificate2 cert, string p7mFilePath)
          {
          if (!p7mFilePath.ToLowerInvariant().EndsWith(".p7m"))
          p7mFilePath += ".p7m";

          try
          {
          ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1", "PKCS 7 Data"), File.ReadAllBytes(filePath));
          SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
          CmsSigner signer = new CmsSigner(cert);
          signer.IncludeOption = X509IncludeOption.EndCertOnly;
          signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1", "SHA256");
          signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
          try
          {
          //PKCS7 format
          signedCms.ComputeSignature(signer, false);
          }
          catch (CryptographicException cex)
          {
          //To evaluate https://stackoverflow.com/a/52897100
          /*
          // Try re-importing the private key into a better CSP:
          using (RSA tmpRsa = RSA.Create())
          {
          tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
          using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
          using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
          {
          signer.Certificate = tmpCert;
          signedCms.ComputeSignature(signer, false);
          }
          }*/

          throw cex;
          }
          byte signature = signedCms.Encode();
          File.WriteAllBytes(p7mFilePath, signature);
          }
          catch (Exception)
          {
          throw;
          }
          finally
          {
          if (File.Exists(tempFile))
          File.Delete(tempFile);
          }
          }





          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448113%2fsign-a-document-with-cades-bes-using-bouncy-castle%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            Here a possibile solution:



            public static void SignFile(string filePath,X509Certificate2 cert, string p7mFilePath)
            {
            if (!p7mFilePath.ToLowerInvariant().EndsWith(".p7m"))
            p7mFilePath += ".p7m";

            try
            {
            ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1", "PKCS 7 Data"), File.ReadAllBytes(filePath));
            SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
            CmsSigner signer = new CmsSigner(cert);
            signer.IncludeOption = X509IncludeOption.EndCertOnly;
            signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1", "SHA256");
            signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
            try
            {
            //PKCS7 format
            signedCms.ComputeSignature(signer, false);
            }
            catch (CryptographicException cex)
            {
            //To evaluate https://stackoverflow.com/a/52897100
            /*
            // Try re-importing the private key into a better CSP:
            using (RSA tmpRsa = RSA.Create())
            {
            tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
            using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
            using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
            {
            signer.Certificate = tmpCert;
            signedCms.ComputeSignature(signer, false);
            }
            }*/

            throw cex;
            }
            byte signature = signedCms.Encode();
            File.WriteAllBytes(p7mFilePath, signature);
            }
            catch (Exception)
            {
            throw;
            }
            finally
            {
            if (File.Exists(tempFile))
            File.Delete(tempFile);
            }
            }





            share|improve this answer




























              1














              Here a possibile solution:



              public static void SignFile(string filePath,X509Certificate2 cert, string p7mFilePath)
              {
              if (!p7mFilePath.ToLowerInvariant().EndsWith(".p7m"))
              p7mFilePath += ".p7m";

              try
              {
              ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1", "PKCS 7 Data"), File.ReadAllBytes(filePath));
              SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
              CmsSigner signer = new CmsSigner(cert);
              signer.IncludeOption = X509IncludeOption.EndCertOnly;
              signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1", "SHA256");
              signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
              try
              {
              //PKCS7 format
              signedCms.ComputeSignature(signer, false);
              }
              catch (CryptographicException cex)
              {
              //To evaluate https://stackoverflow.com/a/52897100
              /*
              // Try re-importing the private key into a better CSP:
              using (RSA tmpRsa = RSA.Create())
              {
              tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
              using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
              using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
              {
              signer.Certificate = tmpCert;
              signedCms.ComputeSignature(signer, false);
              }
              }*/

              throw cex;
              }
              byte signature = signedCms.Encode();
              File.WriteAllBytes(p7mFilePath, signature);
              }
              catch (Exception)
              {
              throw;
              }
              finally
              {
              if (File.Exists(tempFile))
              File.Delete(tempFile);
              }
              }





              share|improve this answer


























                1












                1








                1







                Here a possibile solution:



                public static void SignFile(string filePath,X509Certificate2 cert, string p7mFilePath)
                {
                if (!p7mFilePath.ToLowerInvariant().EndsWith(".p7m"))
                p7mFilePath += ".p7m";

                try
                {
                ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1", "PKCS 7 Data"), File.ReadAllBytes(filePath));
                SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
                CmsSigner signer = new CmsSigner(cert);
                signer.IncludeOption = X509IncludeOption.EndCertOnly;
                signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1", "SHA256");
                signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
                try
                {
                //PKCS7 format
                signedCms.ComputeSignature(signer, false);
                }
                catch (CryptographicException cex)
                {
                //To evaluate https://stackoverflow.com/a/52897100
                /*
                // Try re-importing the private key into a better CSP:
                using (RSA tmpRsa = RSA.Create())
                {
                tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
                using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
                using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
                {
                signer.Certificate = tmpCert;
                signedCms.ComputeSignature(signer, false);
                }
                }*/

                throw cex;
                }
                byte signature = signedCms.Encode();
                File.WriteAllBytes(p7mFilePath, signature);
                }
                catch (Exception)
                {
                throw;
                }
                finally
                {
                if (File.Exists(tempFile))
                File.Delete(tempFile);
                }
                }





                share|improve this answer













                Here a possibile solution:



                public static void SignFile(string filePath,X509Certificate2 cert, string p7mFilePath)
                {
                if (!p7mFilePath.ToLowerInvariant().EndsWith(".p7m"))
                p7mFilePath += ".p7m";

                try
                {
                ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1", "PKCS 7 Data"), File.ReadAllBytes(filePath));
                SignedCms signedCms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber, content, false);
                CmsSigner signer = new CmsSigner(cert);
                signer.IncludeOption = X509IncludeOption.EndCertOnly;
                signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1", "SHA256");
                signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
                try
                {
                //PKCS7 format
                signedCms.ComputeSignature(signer, false);
                }
                catch (CryptographicException cex)
                {
                //To evaluate https://stackoverflow.com/a/52897100
                /*
                // Try re-importing the private key into a better CSP:
                using (RSA tmpRsa = RSA.Create())
                {
                tmpRsa.ImportParameters(cert.GetRSAPrivateKey().ExportParameters(true));
                using (X509Certificate2 tmpCertNoKey = new X509Certificate2(cert.RawData))
                using (X509Certificate2 tmpCert = tmpCertNoKey.CopyWithPrivateKey(tmpRsa))
                {
                signer.Certificate = tmpCert;
                signedCms.ComputeSignature(signer, false);
                }
                }*/

                throw cex;
                }
                byte signature = signedCms.Encode();
                File.WriteAllBytes(p7mFilePath, signature);
                }
                catch (Exception)
                {
                throw;
                }
                finally
                {
                if (File.Exists(tempFile))
                File.Delete(tempFile);
                }
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 5 '18 at 15:54









                MarcoMarco

                389624




                389624
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448113%2fsign-a-document-with-cades-bes-using-bouncy-castle%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Academy of Television Arts & Sciences

                    L'Équipe

                    1995 France bombings