---
title: "AWS CloudHSM digital signature integration"
canonical_url: "https://www.nutrient.io/guides/document-engine/signatures/integrations/aws-hsm/"
md_url: "https://www.nutrient.io/guides/document-engine/signatures/integrations/aws-hsm.md"
last_updated: "2026-05-23T00:08:18.047Z"
description: "Learn how to integrate AWS CloudHSM for secure digital signatures in your applications."
---

This guide explains how to configure Nutrient Document Engine’s signing service to use [AWS CloudHSM](https://aws.amazon.com/cloudhsm/) for hardware-backed digital signatures.

**Simplify eSignatures**

Unless you need HSM-level security, Nutrient offers a powerful signing API.

[Read more](https://www.nutrient.io/api/signing-api/)

**View example**

Prefer to jump straight into code? View the example repo on GitHub.

[Read more](https://github.com/PSPDFKit/pspdfkit-web-signing-service-example)

## Overview

[AWS CloudHSM](https://aws.amazon.com/cloudhsm/) is a cloud-based hardware security module (HSM) that provides cryptographic key storage and operations. HSMs are specialized devices designed to safeguard sensitive data and cryptographic keys. By integrating Document Engine’s signing service with AWS CloudHSM, private keys never leave the secure hardware, significantly enhancing the security of your digital signature operations.

## Architecture

Document Engine’s signing service acts as an intermediary between Document Engine and AWS CloudHSM:

1. **Document Engine** — Prepares the document and requests a signature

2. **Signing service** — Communicates with CloudHSM using PKCS#11 to perform cryptographic operations

3. **AWS CloudHSM** — Stores private keys and performs signing operations in hardware

The signing service uses the [PKCS#11](https://en.wikipedia.org/wiki/PKCS_11) standard interface to communicate with CloudHSM, ensuring private keys remain secure within the HSM at all times.

## Prerequisites

Before starting the integration, you’ll need:

1. A Document Engine instance with digital signature support

2. An AWS CloudHSM cluster configured and initialized

3. A crypto user (CU) account created in the HSM

4. The CloudHSM PKCS#11 client library installed on your signing service host

5. Your signing certificate’s private key imported or generated in the HSM

> Follow the [official CloudHSM getting started](https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html) guide to set up your HSM cluster and install the client library.

## Configuration

Follow the steps below.

### Environment variables

Configure your signing service with the following environment variables:

```bash

# Path to the CloudHSM PKCS#11 library.

export HSM_MODULE=/opt/cloudhsm/lib/libcloudhsm_pkcs11.so

# HSM Crypto User credentials (format: "username:password")

export HSM_PIN=crypto_user:your_password

# Signing service port.

export SIGNING_SERVICE_PORT=6000

```

### Document Engine configuration

Point Document Engine to your signing service by setting the `SIGNING_SERVICE_URL` environment variable:

```bash

export SIGNING_SERVICE_URL=http://signing-service:6000/sign

```

For more information on Document Engine configuration, refer to the [configuration](https://www.nutrient.io/guides/document-engine/configuration/options.md#digital-signature-options) guide.

### Docker deployment

When deploying with Docker, use `docker-compose` to set up both services:

```yaml

services:
  signing_service:
    build:.
    environment:
      SIGNING_SERVICE_PORT: 6000
      HSM_MODULE: /opt/cloudhsm/lib/libcloudhsm_pkcs11.so
      HSM_PIN: ${HSM_PIN}
    volumes:
      - /opt/cloudhsm:/opt/cloudhsm # Mount CloudHSM client libraries

    ports:
      - 6000:6000

  document_engine:
    image: nutrient/document-engine:latest
    environment:
      SIGNING_SERVICE_URL: http://signing_service:6000/sign
      ACTIVATION_KEY: ${ACTIVATION_KEY}
    ports:
      - 5000:5000

```

## Signing methods

Document Engine supports two signature container formats when using AWS CloudHSM.

### RAW signing (recommended for CAdES)

Use RAW signing when your HSM returns a raw PKCS#1 signature. This is the recommended approach for CAdES signatures:

```bash

curl -X 'POST' 'http://localhost:5000/api/documents/my-document-id/sign' \
  -H 'Authorization: Token token="secret"' \
  -H 'Content-Type: application/json' \
  -d '{
    "signatureContainer": "raw",
    "signatureType": "cades",
    "cadesLevel": "b-lt",
    "signingToken": "{\"signMethod\": \"hsm\"}"
  }'

```

The signing service:

1. Receives the `data_to_be_signed` from Document Engine

2. Calculates the digest using the specified hash algorithm

3. Encodes it in PKCS#1 v1.5 format

4. Signs it using the HSM’s private key using PKCS#11

5. Returns the raw signature to Document Engine

### PKCS#7 container signing

Use PKCS#7 signing when you need a complete signature container:

```bash

curl -X 'POST' 'http://localhost:5000/api/documents/my-document-id/sign' \
  -H 'Authorization: Token token="secret"' \
  -H 'Content-Type: application/json' \
  -d '{
    "signatureContainer": "pkcs7",
    "signatureType": "cms",
    "signingToken": "{\"signMethod\": \"hsm\"}"
  }'

```

The signing service:

1. Receives the document digest from Document Engine

2. Creates a PKCS#7 container

3. Uses a custom signer function that delegates signing to the HSM

4. Returns the complete DER-encoded PKCS#7 container

## Implementation details

### HSM initialization

The signing service initializes the CloudHSM connection using the `graphene-pk11` library:

```js

import * as graphene from "graphene-pk11";

const mod = graphene.Module.load(process.env.HSM_MODULE, "CloudHSM");
mod.initialize();

```

### Authentication

The service authenticates with the HSM using your crypto user credentials:

```js

const session = slot.open(
  graphene.SessionFlag.SERIAL_SESSION | graphene.SessionFlag.RW_SESSION,
);
session.login(process.env.HSM_PIN, graphene.UserType.User);

```

### Key management

The signing service retrieves the private key from the HSM for signing operations. Keys are stored securely within the HSM and never leave the hardware:

```js

const privateKeys = session.find({
  class: graphene.ObjectClass.PRIVATE_KEY,
});
const privateKey = privateKeys.items(0);

```

### Certificate management

For RAW signing, your signing service must provide the certificate chain to Document Engine. The signing service responds to the `get_certificates` callback:

```json

{
  "certificates": ["<base64-encoded-signer-certificate>"],
  "ca_certificates": ["<base64-encoded-ca-certificate>"]
}

```

## Security considerations

1. **Private key security**
   - Private keys never leave the HSM.
   - The signing service only needs the PKCS#11 library and PIN.

   - Use AWS IAM roles and security groups to control access.

2. **Credential management**
   - Store `HSM_PIN` securely using AWS Secrets Manager.
   - Rotate crypto user passwords regularly.
   - Use least-privilege principles for HSM user permissions.

3. **Network security**
   - Deploy the signing service on the same private network as Document Engine.
   - Restrict external network access to the signing service.
   - Use AWS security groups to control HSM cluster access.

4. **Signing token validation**
   - The signing service validates requests using the `signingToken` parameter.
   - Implement additional authentication as needed for your use case.

## Testing the integration

To verify your setup:

1. Start the signing service with CloudHSM configuration

2. Make a test signing request to Document Engine:

```bash

curl -X 'POST' 'http://localhost:5000/api/documents/test-doc/sign' \
  -H 'Authorization: Token token="secret"' \
  -H 'Content-Type: application/json' \
  -d '{
    "signatureContainer": "raw",
    "signatureType": "cades",
    "signingToken": "{\"signMethod\": \"hsm\"}"
  }'

```

3. Check the signing service logs for HSM connection messages

4. Verify the signed document validates correctly

## Additional resources

For a complete reference implementation of the signing service with HSM support (using SoftHSM, but adaptable to AWS CloudHSM), see the [signing service example on GitHub](https://github.com/PSPDFKit/pspdfkit-web-signing-service-example).

For more information on the signing service protocol, refer to the callbacks section in the [API reference](https://www.nutrient.io/api/reference/document-engine/upstream/#tag/Digital-Signatures/operation/sign-file) for the digital signatures endpoint.
---

## Related pages

- [Integrate digital signatures](/guides/document-engine/signatures/integrations/overview.md)
- [GlobalSign DSS Credentials.](/guides/document-engine/signatures/integrations/globalsign.md)

