/// <summary> /// Generates PKCS#7 signature of specified data /// </summary> /// <param name="data">Data to be signed</param> /// <param name="detached">Flag indicating whether detached signature should be produced</param> /// <param name="signingCertificate">Signing certificate</param> /// <param name="certPath">Certification path for signing certificate</param> /// <returns>DER encoded PKCS#7 signature of specified data</returns> public byte[] GenerateSignature(byte[] data, bool detached, BCX509.X509Certificate signingCertificate, ICollection<BCX509.X509Certificate> certPath) { if (this._disposed) throw new ObjectDisposedException(this.GetType().FullName); string hashOid = GetHashOid(_hashAlgorihtm); IDigest hashGenerator = GetHashGenerator(_hashAlgorihtm); // Compute hash of input data byte[] dataHash = ComputeDigest(hashGenerator, data); // Construct SignerInfo.signedAttrs Asn1EncodableVector signedAttributesVector = new Asn1EncodableVector(); // Add PKCS#9 contentType signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(OID.PKCS9AtContentType), new DerSet(new DerObjectIdentifier(OID.PKCS7IdData)))); // Add PKCS#9 messageDigest signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(OID.PKCS9AtMessageDigest), new DerSet(new DerOctetString(dataHash)))); // Add PKCS#9 signingTime signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(OID.PKCS9AtSigningTime), new DerSet(new Org.BouncyCastle.Asn1.Cms.Time(new DerUtcTime(DateTime.UtcNow))))); DerSet signedAttributes = new DerSet(signedAttributesVector); // Sign SignerInfo.signedAttrs with PKCS#1 v1.5 RSA signature using private key stored on PKCS#11 compatible device byte[] pkcs1Digest = ComputeDigest(hashGenerator, signedAttributes.GetDerEncoded()); byte[] pkcs1DigestInfo = CreateDigestInfo(pkcs1Digest, hashOid); byte[] pkcs1Signature = null; using (Session session = _slot.OpenSession(true)) using (Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS)) pkcs1Signature = session.Sign(mechanism, _privateKeyHandle, pkcs1DigestInfo); // Construct SignerInfo SignerInfo signerInfo = new SignerInfo( new SignerIdentifier(new IssuerAndSerialNumber(signingCertificate.IssuerDN, signingCertificate.SerialNumber)), new AlgorithmIdentifier(new DerObjectIdentifier(hashOid), null), signedAttributes, new AlgorithmIdentifier(new DerObjectIdentifier(OID.PKCS1RsaEncryption), null), new DerOctetString(pkcs1Signature), null); // Construct SignedData.digestAlgorithms Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector(); digestAlgorithmsVector.Add(new AlgorithmIdentifier(new DerObjectIdentifier(hashOid), null)); // Construct SignedData.encapContentInfo ContentInfo encapContentInfo = new ContentInfo( new DerObjectIdentifier(OID.PKCS7IdData), (detached) ? null : new DerOctetString(data)); // Construct SignedData.certificates Asn1EncodableVector certificatesVector = new Asn1EncodableVector(); foreach (BCX509.X509Certificate cert in certPath) certificatesVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded()))); // Construct SignedData.signerInfos Asn1EncodableVector signerInfosVector = new Asn1EncodableVector(); signerInfosVector.Add(signerInfo.ToAsn1Object()); // Construct SignedData SignedData signedData = new SignedData( new DerSet(digestAlgorithmsVector), encapContentInfo, new BerSet(certificatesVector), null, new DerSet(signerInfosVector)); // Construct top level ContentInfo ContentInfo contentInfo = new ContentInfo( new DerObjectIdentifier(OID.PKCS7IdSignedData), signedData); return contentInfo.GetDerEncoded(); }
//var bcCert = CertificateUtilities.BuildBouncyCastleCollection(signingCertificates); //ICollection<Org.BouncyCastle.X509.X509Certificate> private SignedData CreateSignature( Session session, byte[] content, X509Certificate2Collection signingCertificates) { var digestOid = ToDigestAlgorithmOid(DigestAlgorithm).Value; var hashGenerator = GetHashGenerator(DigestAlgorithm); var dataHash = ComputeDigest(hashGenerator, content); // Construct SignerInfo.signedAttrs var signedAttributesVector = new Asn1EncodableVector(); // Add PKCS#9 contentType signed attribute as Data signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(PkcsObjectIdentifiers.Pkcs9AtContentType.Id), new DerSet(new DerObjectIdentifier(PkcsObjectIdentifiers.Data.Id)))); // Add PKCS#9 messageDigest signed attribute with hash der string encoded signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(PkcsObjectIdentifiers.Pkcs9AtMessageDigest.Id), new DerSet(new DerOctetString(dataHash)))); // Add PKCS#9 signingTime signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(PkcsObjectIdentifiers.Pkcs9AtSigningTime.Id), new DerSet(new Time(new DerUtcTime(DateTime.UtcNow))))); var signedAttributes = new DerSet(signedAttributesVector); // Sign SignerInfo.signedAttrs with PKCS#1 v1.5 RSA signature using private key stored on PKCS#11 compatible device byte[] pkcs1Digest = ComputeDigest(hashGenerator, signedAttributes.GetDerEncoded()); byte[] pkcs1DigestInfo = CreateDigestInfo(pkcs1Digest, digestOid); // Construct SignedData.digestAlgorithms var digestAlgorithmsVector = new Asn1EncodableVector(); // Construct SignedData.certificates var certificatesVector = new Asn1EncodableVector(); // Construct SignedData.signerInfos var signerInfosVector = new Asn1EncodableVector(); // Construct SignedData.encapContentInfo var encapContentInfo = new Org.BouncyCastle.Asn1.Cms.ContentInfo( new DerObjectIdentifier(PkcsObjectIdentifiers.Data.Id), null); //Always a detached signature. foreach (var signingCertificate in signingCertificates) { var bcSigningCertificate = CertificateUtilities.ToBouncyCastleObject(signingCertificate.RawData); // Get public key from certificate var pubKeyParams = bcSigningCertificate.GetPublicKey(); //AsymmetricKeyParameter if (!(pubKeyParams is RsaKeyParameters)) { throw new NotSupportedException("Unsupported keys. Currently supporting RSA keys only."); } var rsaPubKeyParams = (RsaKeyParameters)pubKeyParams; byte[] pkcs1Signature; if (signingCertificate.HasPrivateKey) { pkcs1Signature = GeneratePkcs1Signature(signingCertificate, pkcs1DigestInfo); } else { pkcs1Signature = GeneratePkcs1Signature(session, rsaPubKeyParams, bcSigningCertificate, pkcs1DigestInfo); } // Construct SignerInfo var signerInfo = new Org.BouncyCastle.Asn1.Cms.SignerInfo( new SignerIdentifier(new IssuerAndSerialNumber(bcSigningCertificate.IssuerDN, bcSigningCertificate.SerialNumber)), new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier(new DerObjectIdentifier(digestOid), null), signedAttributes, new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier(new DerObjectIdentifier(PkcsObjectIdentifiers.RsaEncryption.Id), null), new DerOctetString(pkcs1Signature), null); digestAlgorithmsVector.Add(new Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier(new DerObjectIdentifier(digestOid), null)); certificatesVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(bcSigningCertificate.GetEncoded()))); signerInfosVector.Add(signerInfo.ToAsn1Object()); } // Construct SignedData var signedData = new SignedData( new DerSet(digestAlgorithmsVector), encapContentInfo, new BerSet(certificatesVector), null, new DerSet(signerInfosVector)); return(signedData); }