//// This code is part of Document Solutions for PDF .NET demos.// Copyright (c) MESCIUS inc. All rights reserved.//usingSystem;usingSystem.IO;usingSystem.Drawing;usingSystem.Security.Cryptography.X509Certificates; usingOrg.BouncyCastle.Crypto.Digests; usingAzure.Core;usingAzure.Identity;usingAzure.Security.KeyVault.Certificates;usingAzure.Security.KeyVault.Keys.Cryptography; usingGrapeCity.Documents.Pdf;usingGrapeCity.Documents.Pdf.Security; namespaceDsPdfWeb.Demos{// This sample shows how to sign an existing PDF file that contains// an empty signature field with a certificate that is stored// in an Azure Key Vault.//// The sample includes a ready to use utility class AzureSignatureGenerator// that implements the GrapeCity.Documents.Pdf.IPkcs7SignatureGenerator interface,// and can be used to sign PDFs with certificates stored in Azure Key Vault.// // Please note that when run directly off the DsPdf demo site,// this sample will NOT sign the PDF, as it passes dummy Azure credentials// to the AzureSignatureGenerator's ctor. You will need to download the sample// and provide your own credentials for the sample code to actually sign a PDF.//publicclassSignAzureKeyVault {publicintCreatePDF(Stream stream) {var doc = newGcPdfDocument();usingvar s = File.OpenRead(Path.Combine("Resources", "PDFs", "SignAzureKeyVault.pdf")); doc.Load(s); try {// This WILL NOT WORK due to dummy Azure credentials.// Supply valid credentials to actually sign the PDF.usingvar sg = newAzureSignatureGenerator("keyVaultName","tenantId","clientId","clientSecret","certificateName"); var sp = newSignatureProperties() {SignatureBuilder = newPkcs7SignatureBuilder() {SignatureGenerator = sg,CertificateChain = newX509Certificate2[] { sg.Certificate }, },SignatureField = doc.AcroForm.Fields[0] }; doc.Sign(sp, stream); }catch (Exception) {var page = doc.Pages[0];var r = doc.AcroForm.Fields[0].Widgets[0].Rect;Common.Util.AddNote("Signing failed because dummy Azure credentials were used.\n" +"Use valid Azure Key Vault credentials to sign the PDF.", page,newRectangleF(r.Left, r.Bottom + 24, page.Size.Width - r.Left * 2, 0)); doc.Save(stream); } // Done.return doc.Pages.Count; } } /// <summary>/// Implements <seecref="IPkcs7SignatureGenerator"/> /// and allows generating a digital signature using/// a certificate stored in Azure Key Vault./// </summary>publicclassAzureSignatureGenerator : IPkcs7SignatureGenerator, IDisposable {privateCertificateClient_certificateClient;privateX509Certificate2_certificate;privateCryptographyClient_cryptographyClient; /// <summary>/// Initializes a new instance of the <seecref="AzureSignatureGenerator"/> class./// </summary>/// <paramname="keyVaultName">/// The name of the Key Vault storage used to create a URL in the form/// <b>https://{keyVaultName}.vault.azure.net/</b> that will be passed to/// the <seecref="CertificateClient"/> ctor.</param>/// <paramname="tenantId">/// The Azure Active Directory tenant (directory) ID of the service principal./// This value will be used to create the <seecref="ClientSecretCredential"/>.</param>/// <paramname="clientId">/// The client (application) ID of the service principal./// This value will be used to create the <seecref="ClientSecretCredential"/>.</param>/// <paramname="clientSecret">/// The client secret that was generated for the App Registration used to authenticate the client./// This value will be used to create the <seecref="ClientSecretCredential"/>.</param>/// <paramname="certificateName">/// The name of the certificate to be used for the signature.</param>publicAzureSignatureGenerator(string keyVaultName,string tenantId,string clientId,string clientSecret,string certificateName) {var keyVaultUri = newUri($"https://{keyVaultName}.vault.azure.net/");TokenCredential credential = newClientSecretCredential(tenantId, clientId, clientSecret);_certificateClient = newCertificateClient(keyVaultUri, credential);var c = _certificateClient.GetCertificate(certificateName);_certificate = newX509Certificate2(c.Value.Cer);_cryptographyClient = newCryptographyClient(c.Value.KeyId, credential); } /// <summary>/// Gets the ID of the hash algorithm./// </summary>publicOIDHashAlgorithm => OID.HashAlgorithms.SHA256; /// <summary>/// Gets the ID of the encryption algorithm./// </summary>publicOIDDigestEncryptionAlgorithm => OID.EncryptionAlgorithms.RSA; /// <summary>/// Gets the certificate./// </summary>publicX509Certificate2Certificate => _certificate; /// <summary>/// Signs data./// </summary>/// <paramname="input">The input data to sign.</param>/// <returns>The signed data.</returns>publicbyte[] SignData(byte[] input) {var hashDigest = newSha256Digest();byte[] hash = newbyte[hashDigest.GetDigestSize()]; hashDigest.Reset(); hashDigest.BlockUpdate(input, 0, input.Length); hashDigest.DoFinal(hash, 0);byte[] result = _cryptographyClient.Sign(SignatureAlgorithm.RS256, hash).Signature;return result; } /// <summary>/// Releases resources used by this object./// </summary>publicvoidDispose() {_certificateClient = null;if (_certificate != null) {_certificate.Dispose();_certificate = null; }_cryptographyClient = null; } }}