public void CreateSign() { byte[] data = File.ReadAllBytes(Path.Combine(_settings.PackagePath, _manifestFilename)); X509Certificate2 certificate = new X509Certificate2(_settings.CertificatePath, _settings.CertificatePassword, X509KeyStorageFlags.Exportable); X509Certificate2 intermCertificate = new X509Certificate2(_settings.IntermCertificatePath); var privKey = SecurityUtils.GetRsaKeyPair(certificate.GetRSAPrivateKey()).Private; var cert = SecurityUtils.FromX509Certificate(certificate); var interm = SecurityUtils.FromX509Certificate(intermCertificate); CmsProcessableByteArray content = new CmsProcessableByteArray(data); CmsSignedDataGenerator generator = new CmsSignedDataGenerator(); generator.AddSigner(privKey, cert, CmsSignedGenerator.EncryptionRsa, CmsSignedGenerator.DigestSha256); CmsSignedData signedContent = generator.Generate(content, false); var si = signedContent.GetSignerInfos(); var signer = si.GetSigners().Cast <SignerInformation>().First(); SignerInfo signerInfo = signer.ToSignerInfo(); Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector(); digestAlgorithmsVector.Add(new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(_oidSHA256), parameters: DerNull.Instance)); // Construct SignedData.encapContentInfo ContentInfo encapContentInfo = new ContentInfo( contentType: new DerObjectIdentifier(_oidPKCS7IdData), content: null); Asn1EncodableVector certificatesVector = new Asn1EncodableVector(); certificatesVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded()))); certificatesVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(interm.GetEncoded()))); // Construct SignedData.signerInfos Asn1EncodableVector signerInfosVector = new Asn1EncodableVector(); signerInfosVector.Add(signerInfo.ToAsn1Object()); // Construct SignedData SignedData signedData = new SignedData( digestAlgorithms: new DerSet(digestAlgorithmsVector), contentInfo: encapContentInfo, certificates: new BerSet(certificatesVector), crls: null, signerInfos: new DerSet(signerInfosVector)); ContentInfo contentInfo = new ContentInfo( contentType: new DerObjectIdentifier(_oidPKCS7IdSignedData), content: signedData); File.WriteAllBytes(Path.Combine(_settings.PackagePath, _signatureFilename), contentInfo.GetDerEncoded()); }
/// <summary> /// Get a signature block that java will load a JAR with /// </summary> /// <param name="sfFileData">The data to sign</param> /// <returns>The signature block (including certificate) for the data passed in</returns> private byte[] SignIt(byte[] sfFileData) { AsymmetricKeyParameter privateKey = null; var cert = LoadCert(_pemData, out privateKey); //create things needed to make the CmsSignedDataGenerator work var certStore = X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(new List <X509Certificate>() { cert })); CmsSignedDataGenerator dataGen = new CmsSignedDataGenerator(); dataGen.AddCertificates(certStore); dataGen.AddSigner(privateKey, cert, CmsSignedDataGenerator.EncryptionRsa, CmsSignedDataGenerator.DigestSha256); //content is detached- i.e. not included in the signature block itself CmsProcessableByteArray detachedContent = new CmsProcessableByteArray(sfFileData); var signedContent = dataGen.Generate(detachedContent, false); //do lots of stuff to get things in the proper ASN.1 structure for java to parse it properly. much trial and error. var signerInfos = signedContent.GetSignerInfos(); var signer = signerInfos.GetSigners().Cast <SignerInformation>().First(); SignerInfo signerInfo = signer.ToSignerInfo(); Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector(); digestAlgorithmsVector.Add(new AlgorithmIdentifier(new DerObjectIdentifier("2.16.840.1.101.3.4.2.1"), DerNull.Instance)); ContentInfo encapContentInfo = new ContentInfo(new DerObjectIdentifier("1.2.840.113549.1.7.1"), null); Asn1EncodableVector asnVector = new Asn1EncodableVector(); asnVector.Add(X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded()))); Asn1EncodableVector signersVector = new Asn1EncodableVector(); signersVector.Add(signerInfo.ToAsn1Object()); SignedData signedData = new SignedData(new DerSet(digestAlgorithmsVector), encapContentInfo, new BerSet(asnVector), null, new DerSet(signersVector)); ContentInfo contentInfo = new ContentInfo(new DerObjectIdentifier("1.2.840.113549.1.7.2"), signedData); return(contentInfo.GetDerEncoded()); }
static void PKCS7() { GostCryptoConfig.ProviderType = ProviderTypes.VipNet; Config.InitCommon(); BCX509.X509Certificate bcCert = null; using (var g = GostCryptoConfig.CreateGost3410AsymmetricAlgorithm()) { bool detached = false; byte[] data = File.ReadAllBytes("test.xml"); var certBytes = g.ContainerCertificateRaw; BCX509.X509CertificateParser _x509CertificateParser = new BCX509.X509CertificateParser(); bcCert = _x509CertificateParser.ReadCertificate(certBytes); ICollection <BCX509.X509Certificate> certPath = new List <BCX509.X509Certificate>(); certPath.Add(bcCert); IDigest digest = new Gost3411Digest(); string hashOid = GostCryptoConfig.DefaultHashOid; byte[] dataHash = ComputeDigest(digest, data); // Construct SignerInfo.signedAttrs Asn1EncodableVector signedAttributesVector = new Asn1EncodableVector(); // Add PKCS#9 contentType signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier("1.2.840.113549.1.9.3"), new DerSet(new DerObjectIdentifier("1.2.840.113549.1.7.1")))); // Add PKCS#9 messageDigest signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier("1.2.840.113549.1.9.4"), new DerSet(new DerOctetString(dataHash)))); // Add PKCS#9 signingTime signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier("1.2.840.113549.1.9.5"), new DerSet(new Org.BouncyCastle.Asn1.Cms.Time(new DerUtcTime(DateTime.UtcNow))))); DerSet signedAttributes = new DerSet(signedAttributesVector); byte[] pkcs1Digest = ComputeDigest(digest, signedAttributes.GetDerEncoded()); byte[] pkcs1DigestInfo = CreateDigestInfo(pkcs1Digest, hashOid); // hash //var signature = g.CreateSignature(hash); var formatter = new GostSignatureFormatter(g); var signature = formatter.CreateSignature(pkcs1Digest); // Construct SignerInfo SignerInfo signerInfo = new SignerInfo( new SignerIdentifier(new IssuerAndSerialNumber(bcCert.IssuerDN, bcCert.SerialNumber)), new AlgorithmIdentifier(new DerObjectIdentifier(hashOid), null), signedAttributes, new AlgorithmIdentifier(new DerObjectIdentifier(GostCryptoConfig.DefaultSignOid), null), new DerOctetString(signature), 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("1.2.840.113549.1.7.1"), (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("1.2.840.113549.1.7.2"), signedData); var res = contentInfo.GetDerEncoded(); File.WriteAllBytes("test.p7", res); CmsSignedData cms = new CmsSignedData(res); var certStore = cms.GetCertificates("Collection"); SignerInformationStore signers = cms.GetSignerInfos(); var it = signers.GetSigners().GetEnumerator(); it.MoveNext(); var signer = it.Current as SignerInformation; var b = signer.Verify(bcCert); } }
/// <summary> /// Формирование сигнатуры для серверной подписи /// </summary> /// <param name="alg"></param> /// <param name="data"></param> /// <param name="detached"></param> /// <returns></returns> public static byte[] ComputeSignature(Gost3410 alg, byte[] data, bool detached = true) { var certBytes = alg.ContainerCertificateRaw; var _x509CertificateParser = new BCX509.X509CertificateParser(); var bcCert = _x509CertificateParser.ReadCertificate(certBytes); ICollection <BCX509.X509Certificate> certPath = new List <BCX509.X509Certificate>(); certPath.Add(bcCert); IDigest digest; string hashOid; string signOid; if (GostCryptoConfig.ProviderType == ProviderTypes.CryptoPro256) { digest = new GOST3411_2012_256Digest(); signOid = Constants.OID_GR3410_12_256; hashOid = Constants.OID_GR3411_12_256; } else if (GostCryptoConfig.ProviderType == ProviderTypes.CryptoPro512) { digest = new GOST3411_2012_512Digest(); signOid = Constants.OID_GR3410_12_512; hashOid = Constants.OID_GR3411_12_512; } else { digest = new Gost3411Digest(); signOid = Constants.OID_GR3410_2001; hashOid = Constants.OID_GR3411_2001; } byte[] dataHash = ComputeDigest(digest, data); // Construct SignerInfo.signedAttrs Asn1EncodableVector signedAttributesVector = new Asn1EncodableVector(); // Add PKCS#9 contentType signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(Constants.szOID_RSA_contentType), new DerSet(new DerObjectIdentifier(Constants.szOID_RSA_data)))); // Add PKCS#9 messageDigest signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(Constants.szOID_RSA_messageDigest), new DerSet(new DerOctetString(dataHash)))); // Add PKCS#9 signingTime signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( new DerObjectIdentifier(Constants.szOID_RSA_signingTime), new DerSet(new Org.BouncyCastle.Asn1.Cms.Time(new DerUtcTime(DateTime.UtcNow))))); DerSet signedAttributes = new DerSet(signedAttributesVector); byte[] pkcs1Digest = ComputeDigest(digest, signedAttributes.GetDerEncoded()); //byte[] pkcs1DigestInfo = CreateDigestInfo(pkcs1Digest, hashOid); var formatter = new GostSignatureFormatter(alg); var signature = formatter.CreateSignature(pkcs1Digest); // Construct SignerInfo SignerInfo signerInfo = new SignerInfo( new SignerIdentifier(new IssuerAndSerialNumber(bcCert.IssuerDN, bcCert.SerialNumber)), new AlgorithmIdentifier(new DerObjectIdentifier(hashOid), null), signedAttributes, new AlgorithmIdentifier(new DerObjectIdentifier(signOid), null), new DerOctetString(signature), 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(Constants.szOID_RSA_data), (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(Constants.szOID_RSA_signedData), signedData); return(contentInfo.GetDerEncoded()); }
public byte[] GenerateP7s(byte[] data, X509Certificate signingCertificate, IEnumerable <X509Certificate> certPath) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (signingCertificate == null) { throw new ArgumentNullException(nameof(signingCertificate)); } if (certPath == null) { throw new ArgumentNullException(nameof(certPath)); } byte[] dataHashSha256 = this.ComputeHash(data); Asn1EncodableVector signedAttributesVector = this.CreateSignatureAttribute(dataHashSha256, signingCertificate); DerSet signedAttributes = new DerSet(signedAttributesVector); byte[] signedAttributesDigest = this.ComputeHash(signedAttributes.GetDerEncoded()); byte[] signature = this.cadesExternalSignature.SignSha256(signedAttributesDigest); DerOctetString digestSignature = new DerOctetString(signature); AlgorithmIdentifier digestSignatureAlgorithm = this.CreateSignatureInfo(); SignerInfo signerInfo = new SignerInfo( sid: new SignerIdentifier(new IssuerAndSerialNumber(signingCertificate.IssuerDN, signingCertificate.SerialNumber)), digAlgorithm: new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(Oid.SHA256), parameters: DerNull.Instance ), authenticatedAttributes: signedAttributes, digEncryptionAlgorithm: digestSignatureAlgorithm, encryptedDigest: digestSignature, unauthenticatedAttributes: null ); // Construct SignedData.digestAlgorithms Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector(); digestAlgorithmsVector.Add( new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(Oid.SHA256), parameters: DerNull.Instance)); // Construct SignedData.encapContentInfo ContentInfo encapContentInfo = new ContentInfo( contentType: new DerObjectIdentifier(Oid.PKCS7IdData), content: null); // Construct SignedData.certificates Asn1EncodableVector certificatesVector = new Asn1EncodableVector(); foreach (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( digestAlgorithms: new DerSet(digestAlgorithmsVector), contentInfo: encapContentInfo, certificates: new BerSet(certificatesVector), crls: null, signerInfos: new DerSet(signerInfosVector)); // Construct top level ContentInfo ContentInfo contentInfo = new ContentInfo( contentType: new DerObjectIdentifier(Oid.PKCS7IdSignedData), content: signedData); return(contentInfo.GetDerEncoded()); }
/// <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 = HashAlgorithmUtils.GetHashOid(_hashAlgorihtm); IDigest hashGenerator = HashAlgorithmUtils.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( attrType: new DerObjectIdentifier(OID.PKCS9AtContentType), attrValues: new DerSet(new DerObjectIdentifier(OID.PKCS7IdData)))); // Add PKCS#9 messageDigest signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( attrType: new DerObjectIdentifier(OID.PKCS9AtMessageDigest), attrValues: new DerSet(new DerOctetString(dataHash)))); // Add PKCS#9 signingTime signed attribute signedAttributesVector.Add( new Org.BouncyCastle.Asn1.Cms.Attribute( attrType: new DerObjectIdentifier(OID.PKCS9AtSigningTime), attrValues: new DerSet(new Org.BouncyCastle.Asn1.Cms.Time(new DerUtcTime(DateTime.UtcNow))))); // Compute digest of SignerInfo.signedAttrs DerSet signedAttributes = new DerSet(signedAttributesVector); byte[] signedAttributesDigest = ComputeDigest(hashGenerator, signedAttributes.GetDerEncoded()); // Sign digest of SignerInfo.signedAttrs with private key stored on PKCS#11 compatible device Asn1OctetString digestSignature = null; AlgorithmIdentifier digestSignatureAlgorithm = null; if (_signatureScheme == SignatureScheme.RSASSA_PKCS1_v1_5) { // Construct DigestInfo byte[] digestInfo = CreateDigestInfo(signedAttributesDigest, hashOid); // Sign DigestInfo with CKM_RSA_PKCS mechanism byte[] signature = null; using (Session session = _slot.OpenSession(SessionType.ReadOnly)) using (Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS)) signature = session.Sign(mechanism, _privateKeyHandle, digestInfo); // Construct SignerInfo.signature digestSignature = new DerOctetString(signature); // Construct SignerInfo.signatureAlgorithm digestSignatureAlgorithm = new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(OID.PKCS1RsaEncryption), parameters: DerNull.Instance ); } else if (_signatureScheme == SignatureScheme.RSASSA_PSS) { // Construct parameters for CKM_RSA_PKCS_PSS mechanism CkRsaPkcsPssParams pssMechanismParams = CreateCkRsaPkcsPssParams(_hashAlgorihtm); // Sign digest with CKM_RSA_PKCS_PSS mechanism byte[] signature = null; using (Session session = _slot.OpenSession(SessionType.ReadOnly)) using (Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_PSS, pssMechanismParams)) signature = session.Sign(mechanism, _privateKeyHandle, signedAttributesDigest); // Construct SignerInfo.signature digestSignature = new DerOctetString(signature); // Construct SignerInfo.signatureAlgorithm digestSignatureAlgorithm = new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(OID.PKCS1RsassaPss), parameters: new Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters( hashAlgorithm: new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(hashOid), parameters: DerNull.Instance ), maskGenAlgorithm: new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(OID.PKCS1Mgf1), parameters: new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(hashOid), parameters: DerNull.Instance ) ), saltLength: new DerInteger(hashGenerator.GetDigestSize()), trailerField: new DerInteger(1) ) ); } else { throw new NotSupportedException("Unsupported signature scheme"); } // Construct SignerInfo SignerInfo signerInfo = new SignerInfo( sid: new SignerIdentifier(new IssuerAndSerialNumber(signingCertificate.IssuerDN, signingCertificate.SerialNumber)), digAlgorithm: new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(hashOid), parameters: DerNull.Instance ), authenticatedAttributes: signedAttributes, digEncryptionAlgorithm: digestSignatureAlgorithm, encryptedDigest: digestSignature, unauthenticatedAttributes: null ); // Construct SignedData.digestAlgorithms Asn1EncodableVector digestAlgorithmsVector = new Asn1EncodableVector(); digestAlgorithmsVector.Add( new AlgorithmIdentifier( algorithm: new DerObjectIdentifier(hashOid), parameters: DerNull.Instance)); // Construct SignedData.encapContentInfo ContentInfo encapContentInfo = new ContentInfo( contentType: new DerObjectIdentifier(OID.PKCS7IdData), content: (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( digestAlgorithms: new DerSet(digestAlgorithmsVector), contentInfo: encapContentInfo, certificates: new BerSet(certificatesVector), crls: null, signerInfos: new DerSet(signerInfosVector)); // Construct top level ContentInfo ContentInfo contentInfo = new ContentInfo( contentType: new DerObjectIdentifier(OID.PKCS7IdSignedData), content: signedData); return(contentInfo.GetDerEncoded()); }
/// <summary> /// Signs the signature file's content using the given certificate, and returns the RSA signature. /// </summary> /// <param name="signatureFileData">Content of the signature file to be signed</param> /// <param name="pemCertData">PEM data of the certificate and private key for signing</param> /// <returns>The RSA signature</returns> private byte[] GetSignature(byte[] signatureFileData, string pemCertData) { var(cert, privateKey) = LoadCertificate(pemCertData); var certStore = X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(new List <X509Certificate> { cert })); CmsSignedDataGenerator dataGen = new(); dataGen.AddCertificates(certStore); dataGen.AddSigner(privateKey, cert, CmsSignedGenerator.EncryptionRsa, CmsSignedGenerator.DigestSha256); // Content is detached - i.e. not included in the signature block itself CmsProcessableByteArray detachedContent = new(signatureFileData); var signedContent = dataGen.Generate(detachedContent, false); // Get the signature in the proper ASN.1 structure for java to parse it properly. Lots of trial and error var signerInfos = signedContent.GetSignerInfos(); var signer = signerInfos.GetSigners().Cast <SignerInformation>().First(); SignerInfo signerInfo = signer.ToSignerInfo(); Asn1EncodableVector digestAlgorithmsVector = new(); digestAlgorithmsVector.Add(new AlgorithmIdentifier(new DerObjectIdentifier("2.16.840.1.101.3.4.2.1"), DerNull.Instance)); ContentInfo encapContentInfo = new(new DerObjectIdentifier("1.2.840.113549.1.7.1"), null); Asn1EncodableVector asnVector = new() { X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded())) }; Asn1EncodableVector signersVector = new() { signerInfo.ToAsn1Object() }; SignedData signedData = new(new DerSet(digestAlgorithmsVector), encapContentInfo, new BerSet(asnVector), null, new DerSet(signersVector)); ContentInfo contentInfo = new(new DerObjectIdentifier("1.2.840.113549.1.7.2"), signedData); return(contentInfo.GetDerEncoded()); } /// <summary> /// Loads the certificate and private key from the given PEM data /// </summary> /// <param name="pemData"></param> /// <returns>The loaded certificate and private key</returns> /// <exception cref="System.Security.SecurityException">If the certificate or private key failed to load</exception> private (X509Certificate certificate, AsymmetricKeyParameter privateKey) LoadCertificate(string pemData) { X509Certificate? cert = null; AsymmetricKeyParameter?privateKey = null; using (var reader = new StringReader(pemData)) { // Iterate through the PEM objects until we find the public or private key var pemReader = new PemReader(reader); object pemObject; while ((pemObject = pemReader.ReadObject()) != null) { cert ??= pemObject as X509Certificate; privateKey ??= (pemObject as AsymmetricCipherKeyPair)?.Private; } } if (cert == null) { throw new System.Security.SecurityException("Certificate could not be loaded from PEM data."); } if (privateKey == null) { throw new System.Security.SecurityException("Private Key could not be loaded from PEM data."); } return(cert, privateKey); }