> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/digital-signature/custom-signing.md).

# Custom Signing on Server/Desktop

Discover how to customize your document signing process with the Apryse custom signing API. Integrate PDF-specific operations, HSM tokens, cloud keystores, and more for a seamless signing experience.

{% hint style="info" %}
**Requirements**

*These packages are required to use these features in production. Trial keys have unlimited access to all features*

<a href="https://apryse.com/capabilities#DigitalSignature" class="button primary">Package: Digital Signature</a><a href="https://showcase.apryse.com/digital-signatures" class="button primary">Live demo</a>
{% endhint %}

The Apryse custom signing API is a set of APIs related to cryptographic digital signatures which allows users to customize the process of signing documents. Among other things, this includes the capability to allow for easy integration of PDF-specific signing-related operations with access to Hardware Security Module (HSM) tokens/devices, access to cloud keystores, access to system keystores, etc. The intent behind this API is to remove the old, tricky, and complicated requirement for users with specific needs to create custom SignatureHandler functor objects.

What follows is a simple code guide to the use of the custom signing API. Please note: any of the steps can be replaced with your own code that provides some custom functionality.

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
PDFDoc doc = new PDFDoc(in_docpath);

Page page1 = doc.GetPage(1);

// Create a digital signature field and associated widget.
DigitalSignatureField digsig_field = doc.CreateDigitalSignatureField(in_sig_field_name);
SignatureWidget widgetAnnot = SignatureWidget.Create(doc, new Rect(143, 287, 219, 306), digsig_field);
page1.AnnotPushBack(widgetAnnot);

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.CreateSigDictForCustomSigning("Adobe.PPKLite",
	in_PAdES_signing_mode? DigitalSignatureField.SubFilterType.e_ETSI_CAdES_detached : DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
	7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use CreateSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
Date current_date = new Date();
current_date.SetCurrentTime();
digsig_field.SetSigDictTimeOfSigning(current_date);

// Save the document incrementally to avoid invalidating any previous signatures.
doc.Save(in_outpath, SDFDoc.SaveOptions.e_incremental);

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
byte[] pdf_digest = digsig_field.CalculateDigest(DigestAlgorithm.Type.e_sha256);

X509Certificate signer_cert = new X509Certificate(in_cert_path);

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
byte[] pades_versioned_ess_signing_cert_attribute = digsig_field.GenerateESSSigningCertPAdESAttribute(
	signer_cert, DigestAlgorithm.Type.e_sha256);

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
byte[] signedAttrs = DigitalSignatureField.GenerateCMSSignedAttributes(pdf_digest, 
	pades_versioned_ess_signing_cert_attribute);

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
byte[] signedAttrs_digest = DigestAlgorithm.CalculateDigest(DigestAlgorithm.Type.e_sha256, signedAttrs);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
PDFDoc doc(in_docpath);

Page page1 = doc.GetPage(1);

// Create a digital signature field and associated widget.
DigitalSignatureField digsig_field = doc.CreateDigitalSignatureField(in_sig_field_name);
Annots::SignatureWidget widgetAnnot = Annots::SignatureWidget::Create(doc, Rect(143, 287, 219, 306), digsig_field);
page1.AnnotPushBack(widgetAnnot);

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.CreateSigDictForCustomSigning("Adobe.PPKLite",
	in_PAdES_signing_mode ? DigitalSignatureField::SubFilterType::e_ETSI_CAdES_detached : DigitalSignatureField::SubFilterType::e_adbe_pkcs7_detached,
	7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply certification signature, use CreateSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
Date current_date;
current_date.SetCurrentTime();
digsig_field.SetSigDictTimeOfSigning(current_date);

// Save the document incrementally to avoid invalidating any previous signatures.
doc.Save(in_outpath, SDFDoc::e_incremental, 0);

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
vector<UChar> pdf_digest(digsig_field.CalculateDigest(Crypto::DigestAlgorithm::e_SHA256));

Crypto::X509Certificate signer_cert(in_cert_path);

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
vector<UChar> pades_versioned_ess_signing_cert_attribute(DigitalSignatureField::GenerateESSSigningCertPAdESAttribute(
	signer_cert, Crypto::DigestAlgorithm::e_SHA256));

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
vector<UChar> signedAttrs(DigitalSignatureField::GenerateCMSSignedAttributes(pdf_digest.data(), pdf_digest.size(),
	pades_versioned_ess_signing_cert_attribute.data(), pades_versioned_ess_signing_cert_attribute.size()));

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
vector<UChar> signedAttrs_digest(Crypto::DigestAlgorithm::CalculateDigest(Crypto::DigestAlgorithm::e_SHA256, signedAttrs.data(), signedAttrs.size()));
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
doc := NewPDFDoc(in_docpath)

page1 := doc.GetPage(1)

// Create a digital signature field and associated widget.
digsig_field := doc.CreateDigitalSignatureField(in_sig_field_name)
widgetAnnot := SignatureWidgetCreate(doc, NewRect(143.0, 287.0, 219.0, 306.0), digsig_field)
page1.AnnotPushBack(widgetAnnot)

signing_mode := DigitalSignatureFieldE_adbe_pkcs7_detached
if in_PAdES_signing_mode {
signing_mode = DigitalSignatureFieldE_ETSI_CAdES_detached
}
// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.CreateSigDictForCustomSigning("Adobe.PPKLite",
	&signing_mode,
	7500) // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use CreateSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
current_date := NewDate()
current_date.SetCurrentTime()
digsig_field.SetSigDictTimeOfSigning(current_date)

// Save the document incrementally to avoid invalidating any previous signatures.
doc.Save(in_outpath, uint(SDFDocE_incremental))

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
pdf_digest := digsig_field.CalculateDigest(DigestAlgorithmE_SHA256)

signer_cert := NewX509Certificate(in_cert_path)

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
pades_versioned_ess_signing_cert_attribute := DigitalSignatureFieldGenerateESSSigningCertPAdESAttribute(signer_cert, DigestAlgorithmE_SHA256)

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS).
// The signedAttrs are certain attributes that become protected by their inclusion in the signature.
signedAttrs := DigitalSignatureFieldGenerateCMSSignedAttributes(pdf_digest, pades_versioned_ess_signing_cert_attribute)

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
signedAttrs_digest := DigestAlgorithmCalculateDigest(DigestAlgorithmE_SHA256, signedAttrs)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
PDFDoc doc = new PDFDoc(in_docpath);

Page page1 = doc.getPage(1);

// Create a digital signature field and associated widget.
DigitalSignatureField digsig_field = doc.createDigitalSignatureField(in_sig_field_name);
SignatureWidget widgetAnnot = SignatureWidget.create(doc, new Rect(143, 287, 219, 306), digsig_field);
page1.annotPushBack(widgetAnnot);

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.createSigDictForCustomSigning("Adobe.PPKLite",
	in_PAdES_signing_mode? DigitalSignatureField.SubFilterType.e_ETSI_CAdES_detached : DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
	7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use createSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
Date current_date = new Date();
current_date.setCurrentTime();
digsig_field.setSigDictTimeOfSigning(current_date);

// Save the document incrementally to avoid invalidating any previous signatures.
doc.save(in_outpath, SDFDoc.SaveMode.INCREMENTAL, null);

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
byte[] pdf_digest = digsig_field.calculateDigest(DigestAlgorithm.e_sha256);

X509Certificate signer_cert = new X509Certificate(in_cert_path);

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
byte[] pades_versioned_ess_signing_cert_attribute = digsig_field.generateESSSigningCertPAdESAttribute(
	signer_cert, DigestAlgorithm.e_sha256);

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
byte[] signedAttrs = DigitalSignatureField.generateCMSSignedAttributes(pdf_digest, 
	pades_versioned_ess_signing_cert_attribute);

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
byte[] signedAttrs_digest = DigestAlgorithm.calculateDigest(DigestAlgorithm.e_sha256, signedAttrs);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
const doc = await PDFNet.PDFDoc.createFromFilePath(in_docpath);

const page1 = await doc.getPage(1);

// Create a digital signature field and associated widget.
const digsig_field = await doc.createDigitalSignatureField(in_sig_field_name);
const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(143, 287, 219, 306), digsig_field);
await page1.annotPushBack(widgetAnnot);

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
await digsig_field.createSigDictForCustomSigning("Adobe.PPKLite",
	in_PAdES_signing_mode?  PDFNet.DigitalSignatureField.SubFilterType.e_ETSI_CAdES_detached :  PDFNet.DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
	7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use createSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
const current_date = new PDFNet.Date();
await current_date.setCurrentTime();
await digsig_field.setSigDictTimeOfSigning(current_date);

await doc.save(in_outpath, PDFNet.SDFDoc.SaveOptions.e_incremental);

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
const pdf_digest = await digsig_field.calculateDigest(PDFNet.DigestAlgorithm.Type.e_SHA256);

const signer_cert = await PDFNet.X509Certificate.createFromFile(in_cert_path);

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
const pades_versioned_ess_signing_cert_attribute = await PDFNet.DigitalSignatureField.generateESSSigningCertPAdESAttribute(signer_cert, PDFNet.DigestAlgorithm.Type.e_SHA256);

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
const signedAttrs = await PDFNet.DigitalSignatureField.generateCMSSignedAttributes(pdf_digest,
	pades_versioned_ess_signing_cert_attribute);

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
const signedAttrs_digest = await PDFNet.DigestAlgorithm.calculateDigest(PDFNet.DigestAlgorithm.Type.e_SHA256, signedAttrs);
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
PTPDFDoc* doc = [[PTPDFDoc alloc] initWithFilepath: in_docpath];

PTPage* page1 = [doc GetPage: 1];

// Create a digital signature field and associated widget.
PTDigitalSignatureField* digsig_field = [doc CreateDigitalSignatureField: in_sig_field_name];
PTSignatureWidget* widgetAnnot = [PTSignatureWidget CreateWithDigitalSignatureField: doc pos: [[PTPDFRect alloc] initWithX1: 143 y1: 287 x2: 219 y2: 306] field: digsig_field];
[page1 AnnotPushBack: widgetAnnot];

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
// For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use createSigDictForCustomCertification instead.
[digsig_field CreateSigDictForCustomSigning: @"Adobe.PPKLite" in_subfilter_type: e_ptadbe_pkcs7_detached in_contents_size_to_reserve: 7500];

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
PTDate* current_date = [[PTDate alloc] init];
[current_date SetCurrentTime];
[digsig_field SetSigDictTimeOfSigning: current_date];

// Save the document incrementally to avoid invalidating any previous signatures.
[doc SaveToFile: in_outpath flags: e_ptincremental];

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
NSData* pdf_digest = [digsig_field CalculateDigest: e_ptsha256];

PTX509Certificate* signer_cert = [[PTX509Certificate alloc] initWithIn_certificate_path: in_cert_path];

// Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
// The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm.
NSData* pades_versioned_ess_signing_cert_attribute = [PTDigitalSignatureField GenerateESSSigningCertPAdESAttribute: signer_cert in_digest_algorithm_type: e_ptsha256];

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
NSData* signedAttrs = [PTDigitalSignatureField GenerateCMSSignedAttributes: pdf_digest in_custom_signedattributes_buf: pades_versioned_ess_signing_cert_attribute];

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
NSData* signedAttrs_digest = [PTDigestAlgorithm CalculateDigest: e_ptsha256 in_message_buf: signedAttrs];
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$doc = new PDFDoc($in_docpath);
$page1 = $doc->GetPage(1);

// Create a digital signature field and associated widget.
$digsig_field = $doc->CreateDigitalSignatureField($in_sig_field_name);
$widgetAnnot = SignatureWidget::Create($doc, new Rect(143.0, 287.0, 219.0, 306.0), $digsig_field);
$page1->AnnotPushBack($widgetAnnot);

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
$digsig_field->CreateSigDictForCustomSigning("Adobe.PPKLite",
	$in_PAdES_signing_mode? DigitalSignatureField::e_ETSI_CAdES_detached : DigitalSignatureField::e_adbe_pkcs7_detached,
	7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
// ... or, if you want to apply a certification signature, use CreateSigDictForCustomCertification instead.

// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
$current_date = new Date();
$current_date->SetCurrentTime();
$digsig_field->SetSigDictTimeOfSigning($current_date);

// Save the document incrementally to avoid invalidating any previous signatures.
$doc->Save($in_outpath, SDFDoc::e_incremental);

// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
$pdf_digest = $digsig_field->CalculateDigest(DigestAlgorithm::e_SHA256);

$signer_cert = new X509Certificate($in_cert_path);

/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
$pades_versioned_ess_signing_cert_attribute = DigitalSignatureField::GenerateESSSigningCertPAdESAttribute(
	$signer_cert, DigestAlgorithm::e_SHA256);

// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
$signedAttrs = DigitalSignatureField::GenerateCMSSignedAttributes($pdf_digest, 
	$pades_versioned_ess_signing_cert_attribute);

// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
$signedAttrs_digest = DigestAlgorithm::CalculateDigest(DigestAlgorithm::e_SHA256, $signedAttrs);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
doc = PDFDoc(in_docpath)

page1 = doc.GetPage(1)

# Create a digital signature field and associated widget.
digsig_field = doc.CreateDigitalSignatureField(in_sig_field_name)
widgetAnnot = SignatureWidget.Create(doc, Rect(143, 287, 219, 306), digsig_field)
page1.AnnotPushBack(widgetAnnot)

# Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.CreateSigDictForCustomSigning('Adobe.PPKLite',
	DigitalSignatureField.e_ETSI_CAdES_detached if in_PAdES_signing_mode else DigitalSignatureField.e_adbe_pkcs7_detached,
	7500) # For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
# ... or, if you want to apply a certification signature, use createSigDictForCustomCertification instead.

# (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
current_date = Date()
current_date.SetCurrentTime()
digsig_field.SetSigDictTimeOfSigning(current_date)

# Save the document incrementally to avoid invalidating any previous signatures.
doc.Save(in_outpath, SDFDoc.e_incremental)

# Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
pdf_digest = digsig_field.CalculateDigest(DigestAlgorithm.e_SHA256)

signer_cert = X509Certificate(in_cert_path)

# Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
# The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm.
pades_versioned_ess_signing_cert_attribute = DigitalSignatureField.GenerateESSSigningCertPAdESAttribute(signer_cert, DigestAlgorithm.e_SHA256)

# Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
signedAttrs = DigitalSignatureField.GenerateCMSSignedAttributes(pdf_digest, pades_versioned_ess_signing_cert_attribute)

# Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
signedAttrs_digest = DigestAlgorithm.CalculateDigest(DigestAlgorithm.e_SHA256, signedAttrs)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
doc = PDFDoc.new(in_docpath);

page1 = doc.GetPage(1);

# Create a digital signature field and associated widget.
digsig_field = doc.CreateDigitalSignatureField(in_sig_field_name);
widgetAnnot = SignatureWidget.Create(doc, Rect.new(143, 287, 219, 306), digsig_field);
page1.AnnotPushBack(widgetAnnot);

# Create a digital signature dictionary inside the digital signature field, in preparation for signing.
digsig_field.CreateSigDictForCustomSigning("Adobe.PPKLite",
	in_PAdES_signing_mode ? DigitalSignatureField::E_ETSI_CAdES_detached : DigitalSignatureField::E_adbe_pkcs7_detached,
	7500); # For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
			# ... or, if you want to apply a certification signature, use CreateSigDictForCustomCertification instead.

# (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
current_date = Date.new();
current_date.SetCurrentTime();
digsig_field.SetSigDictTimeOfSigning(current_date);

# Save the document incrementally to avoid invalidating any previous signatures.
doc.Save(in_outpath, SDFDoc::E_incremental);

# Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
pdf_digest = digsig_field.CalculateDigest(DigestAlgorithm::E_SHA256);

signer_cert = X509Certificate.new(in_cert_path);

# Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
# The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm.
pades_versioned_ess_signing_cert_attribute = DigitalSignatureField.GenerateESSSigningCertPAdESAttribute(signer_cert, DigestAlgorithm::E_SHA256);

# Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
signedAttrs = DigitalSignatureField.GenerateCMSSignedAttributes(pdf_digest, pades_versioned_ess_signing_cert_attribute);

# Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
signedAttrs_digest = DigestAlgorithm.CalculateDigest(DigestAlgorithm::E_SHA256, signedAttrs);
```

{% endcode %}
{% endtab %}
{% endtabs %}

At this point, use your signing provider (e.g. HSM device, cloud keystore) to sign the digest of signedAttrs. Your input should be the variable signedAttrs\_digest. In the following code, we assume the output is in a variable named signature\_value.

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
// Then, load all your chain certificates into a container of X509Certificate.
X509Certificate[] chain_certs = {};

// Then, create ObjectIdentifiers for the algorithms you have used.
ObjectIdentifier digest_algorithm_oid = new ObjectIdentifier(DigestAlgorithm.Type.e_sha256);
ObjectIdentifier signature_algorithm_oid = new ObjectIdentifier(ObjectIdentifier.Predefined.e_RSA_encryption_PKCS1);

// Then, put the CMS signature components together.
byte[] cms_signature = DigitalSignatureField.GenerateCMSSignature(
	signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid,
	signature_value, signedAttrs);

// Write the signature to the document.
doc.SaveCustomSignature(cms_signature, digsig_field, in_outpath);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
// Then, load all your chain certificates into a container of X509Certificate.
vector<Crypto::X509Certificate> chain_certs;

// Then, create ObjectIdentifiers for the algorithms you have used.
Crypto::ObjectIdentifier digest_algorithm_oid(Crypto::DigestAlgorithm::e_SHA256);
Crypto::ObjectIdentifier signature_algorithm_oid(Crypto::ObjectIdentifier::e_RSA_encryption_PKCS1);

// Then, put the CMS signature components together.
vector<UChar> cms_signature(DigitalSignatureField::GenerateCMSSignature(
	signer_cert, chain_certs.data(), chain_certs.size(), digest_algorithm_oid, signature_algorithm_oid,
	signature_value.data(), signature_value.size(), signedAttrs.data(), signedAttrs.size()));

// Write the signature to the document.
doc.SaveCustomSignature(cms_signature.data(), cms_signature.size(), digsig_field, in_outpath);
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
// Then, load all your chain certificates into a container of X509Certificate.
chain_certs := NewVectorX509Certificate()

// Then, create ObjectIdentifiers for the algorithms you have used.
digest_algorithm_oid := NewObjectIdentifier(DigestAlgorithmE_SHA256)
signature_algorithm_oid := NewObjectIdentifier(ObjectIdentifierE_RSA_encryption_PKCS1)

// Then, put the CMS signature components together.
cms_signature := DigitalSignatureFieldGenerateCMSSignature(
	signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid,
	signature_value, signedAttrs)

// Write the signature to the document.
doc.SaveCustomSignature(cms_signature, digsig_field, in_outpath)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
// Then, load all your chain certificates into a container of X509Certificate.
X509Certificate[] chain_certs = {};

// Then, create ObjectIdentifiers for the algorithms you have used.
ObjectIdentifier digest_algorithm_oid = new ObjectIdentifier(ObjectIdentifier.Predefined.e_SHA256);
ObjectIdentifier signature_algorithm_oid = new ObjectIdentifier(ObjectIdentifier.Predefined.e_RSA_encryption_PKCS1);

// Then, put the CMS signature components together.
byte[] cms_signature = DigitalSignatureField.generateCMSSignature(
	signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid,
	signature_value, signedAttrs);

// Write the signature to the document.
doc.saveCustomSignature(cms_signature, digsig_field, in_outpath);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
// Then, load all your chain certificates into a container of X509Certificate.
var chain_certs = [];

// Then, create ObjectIdentifiers for the algorithms you have used.
const digest_algorithm_oid = await PDFNet.ObjectIdentifier.createFromDigestAlgorithm(PDFNet.DigestAlgorithm.Type.e_SHA256);
const signature_algorithm_oid = await PDFNet.ObjectIdentifier.createFromPredefined(PDFNet.ObjectIdentifier.Predefined.e_RSA_encryption_PKCS1);

// Then, put the CMS signature components together.
const cms_signature = await PDFNet.DigitalSignatureField.generateCMSSignature(
		signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid, signature_value,
		signedAttrs);

// Write the signature to the document.
await doc.saveCustomSignature(cms_signature, digsig_field, in_outpath);
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
// Then, load all your chain certificates into a container of X509Certificate.
NSArray<PTX509Certificate *> *chain_certs;

// Then, create ObjectIdentifiers for the algorithms you have used.
PTObjectIdentifier* digest_algorithm_oid = [[PTObjectIdentifier alloc] initWithIn_digest_algorithm_type: e_ptsha256];
PTObjectIdentifier* signature_algorithm_oid = [[PTObjectIdentifier alloc] initWithIn_oid_enum: e_ptRSA_encryption_PKCS1];

// Then, put the CMS signature components together.
NSData* cms_signature = [PTDigitalSignatureField GenerateCMSSignature: signer_cert in_chain_certs_list: chain_certs in_digest_algorithm_oid: digest_algorithm_oid in_signature_algorithm_oid: signature_algorithm_oid  in_signature_value_buf: signature_value in_signedattributes_buf: signedAttrs];

// Write the signature to the document.
[doc SaveCustomSignatureToFile: cms_signature in_field: digsig_field in_path: output_path];
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
// Then, load all your chain certificates into a container of X509Certificate.
$chain_certs = new VectorX509Certificate();

// Then, create ObjectIdentifiers for the algorithms you have used.
$digest_algorithm_oid = new ObjectIdentifier(ObjectIdentifier::e_SHA256);
$signature_algorithm_oid = new ObjectIdentifier(ObjectIdentifier::e_RSA_encryption_PKCS1);

// Then, put the CMS signature components together.
$cms_signature = DigitalSignatureField::GenerateCMSSignature(
	$signer_cert, $chain_certs, $digest_algorithm_oid, $signature_algorithm_oid,
	$signature_value, $signedAttrs);

// Write the signature to the document.
$doc->SaveCustomSignature($cms_signature, $digsig_field, $in_outpath);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
# Then, load all your chain certificates into a container of X509Certificate.
chain_certs = []

# Then, create ObjectIdentifiers for the algorithms you have used.
digest_algorithm_oid = ObjectIdentifier(ObjectIdentifier.e_SHA256)
signature_algorithm_oid = ObjectIdentifier(ObjectIdentifier.e_RSA_encryption_PKCS1)

# Then, put the CMS signature components together.
cms_signature = DigitalSignatureField.GenerateCMSSignature(signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid, signature_value, signedAttrs)

# Write the signature to the document.
doc.SaveCustomSignature(cms_signature, digsig_field, in_outpath)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
# Then, load all your chain certificates into a container of X509Certificate.
chain_certs = VectorX509Certificate.new();

# Then, create ObjectIdentifiers for the algorithms you have used.
digest_algorithm_oid = ObjectIdentifier.new(ObjectIdentifier::E_SHA256);
signature_algorithm_oid = ObjectIdentifier.new(ObjectIdentifier::E_RSA_encryption_PKCS1);

# Then, put the CMS signature components together.
cms_signature = DigitalSignatureField.GenerateCMSSignature(
	signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid,
	signature_value, signedAttrs);

# Write the signature to the document.
doc.SaveCustomSignature(cms_signature, digsig_field, in_outpath);
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/digital-signature/custom-signing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
