Skip to content

Encrypting Content (Optional)

The Digital Post Platform supports optional client-side encryption of message content before upload.

When client-side encryption is used, files are encrypted by the sending system before being uploaded to the storage bucket. The encryption key must be provided in the Create Delivery request using the encryptionKey field so the platform can decrypt and process the content.

This mechanism provides an additional security layer on top of transport and storage encryption.

Encryption is optional. Unencrypted files are also supported.


Overview

When encryption is enabled:

  • Files are encrypted before upload
  • Encrypted files are uploaded to storage
  • The encryption key is provided in the Create Delivery request using the encryptionKey field
  • The platform decrypts files during processing
  • Each file is re-encrypted for recipient access

Encryption applies to:

  • Message bodies
  • Attachments

Metadata and envelope files are not encrypted.


Supported Encryption Algorithms

The platform supports the following encryption modes:

ModeAlgorithmIntegrity ProtectionRecommendation
GCMAES-256-GCMYesPreferred
CBCAES-256-CBCNoLegacy

AES-256-GCM provides authenticated encryption and is the recommended mode.

AES-256-CBC does not include integrity protection. When CBC is used, a content hash should be provided in the envelope to detect corruption.


When to Use Client-Side Encryption

Client-side encryption may be used when:

  • Regulatory requirements mandate sender-controlled encryption
  • Additional security controls are required
  • Content must be encrypted before leaving the sender environment

If these requirements do not apply, standard platform encryption is sufficient.


File Size and Encoding Limits

Encrypted files must be encoded in chunks.

The following limits apply:

ParameterLimit
Maximum chunk size1 MB
Maximum chunks20
Maximum encoded file sizeApproximately 20 MB

Files exceeding these limits must be split before delivery.


Encryption Encoding Format

Encrypted files must follow a specific binary encoding format.

Encryption Indicator

The first byte indicates encryption mode:

ValueMode
1AES-256-CBC
2AES-256-GCM

GCM Chunk Encoding

When using AES-256-GCM, files must be chunked.

Each chunk contains:

FieldSize
Chunk size4 bytes
Nonce12 bytes
Encrypted dataVariable
Authentication tag16 bytes

Encoding format:

  1. Encryption indicator byte (2)
  2. Chunk 1
  3. Chunk 2
  4. ...
  5. Chunk N

Each chunk is encoded as:

[Chunk Size][Nonce][Encrypted Data][Auth Tag]


CBC Encoding

When using AES-256-CBC:

FieldSize
Encryption indicator1 byte
Initialization vector16 bytes
Encrypted dataVariable

Encoding format:

[Indicator][IV][Encrypted Data]

CBC mode does not include authentication tags.


Encryption Key Handling

When encrypting files:

  • A unique symmetric key must be generated per delivery
  • The same key must be used for all encrypted files in that delivery
  • The key must be securely stored by the sending system
  • The key must be provided in the Create Delivery request as the encryptionKey field
  • The key must never be embedded in the file itself

If the encryptionKey provided in the delivery request does not match the key used to encrypt the files, the platform will fail the delivery during processing.

Key management is the responsibility of the sending system.

See Upload Content to S3. for details about including the encryptionKey field in the delivery request.


Referencing Encrypted Files in Envelopes

Encrypted files are referenced in envelopes in the same way as unencrypted files.

Example:

{
  "body": {
    "artifact": {
      "name": "invoice-880942299.enc",
      "filename": "invoice.pdf"
    }
  }
}

The platform determines encryption based on file content encoding.


AES-256-GCM Reference Implementation (Node.js)

The following example demonstrates encryption and encoding using AES-256-GCM.

Prerequisites • Node.js • crypto module • fs module


Example Implementation

const crypto = require('crypto');
const fs = require('fs');

const ALGORITHM = 'aes-256-gcm';
const ENCRYPTION_INDICATOR = 2;
const CHUNK_SIZE = 1024 * 1024;
const MAX_CHUNKS = 20;

// Replace with secure key storage
const KEY = crypto.randomBytes(32);

function generateNonce() {
  return crypto.randomBytes(12);
}

function encryptChunk(data, key) {
  const nonce = generateNonce();
  const cipher = crypto.createCipheriv(ALGORITHM, key, nonce);

  const encrypted = Buffer.concat([
    cipher.update(data),
    cipher.final()
  ]);

  const authTag = cipher.getAuthTag();

  return {
    encrypted,
    nonce,
    authTag
  };
}

function encryptAndEncodeData(data, key) {
  const chunks = [];

  for (let i = 0; i < data.length; i += CHUNK_SIZE) {
    chunks.push(data.slice(i, i + CHUNK_SIZE));
  }

  if (chunks.length > MAX_CHUNKS) {
    throw new Error('File exceeds maximum size');
  }

  const encodedChunks = chunks.map(chunk => {
    const result = encryptChunk(chunk, key);

    const size = Buffer.alloc(4);
    size.writeUInt32BE(
      result.encrypted.length +
      result.nonce.length +
      result.authTag.length
    );

    return Buffer.concat([
      size,
      result.nonce,
      result.encrypted,
      result.authTag
    ]);
  });

  return Buffer.concat([
    Buffer.from([ENCRYPTION_INDICATOR]),
    ...encodedChunks
  ]);
}

// Example usage
const input = fs.readFileSync('input.pdf');

const encrypted = encryptAndEncodeData(input, KEY);

fs.writeFileSync('encrypted.bin', encrypted);

console.log('Encryption completed');

Data Integrity Considerations

When using GCM mode: • Authentication tags verify integrity • Corruption is detected automatically

When using CBC mode: • No integrity verification exists • Corruption may go undetected • Hash values should be provided in envelopes

GCM is strongly recommended.


Common Errors

The following table lists common encryption related errors and recommended actions.

ErrorDescriptionTypical CauseRecommended Action
Invalid encodingThe encrypted file does not follow the required chunk formatIncorrect chunk structure or missing fieldsVerify chunk size, nonce length, and authentication tag
Unsupported encryption modeThe encryption indicator is not recognizedInvalid first byte in encoded fileEnsure the correct encryption mode value is used
Decryption failureThe platform cannot decrypt the fileIncorrect encryption keyVerify that the correct key is provided in the delivery request
Authentication tag validation failedIntegrity verification failed (GCM mode)Corrupted data or incorrect keyRegenerate the encrypted file and verify transmission
Corrupted encrypted contentFile contents are incomplete or alteredTransmission error or storage corruptionRe-upload the encrypted file
File size limit exceededEncoded file exceeds platform limitsToo many chunks or oversized input fileSplit the file or reduce file size
Duplicate nonce detectedNonce reuse detectedNonce generation not uniqueEnsure each chunk uses a unique nonce
Missing encryption keyNo key provided with deliveryMisconfigured delivery requestInclude the encryption key in the delivery request
Invalid hash valueContent hash does not match decrypted dataHash mismatch or incorrect encryptionRecalculate and update the hash

Troubleshooting

If encrypted files fail to process:

  1. Verify encryption mode indicator
  2. Verify chunk structure
  3. Verify key correctness
  4. Check file size limits
  5. Validate nonce uniqueness
  6. Confirm envelope references

Next Steps

After encryption is configured, continue with:

  • Upload Content to Storage
  • Create Delivery
  • Verify and Troubleshoot
  • Monitor Processing Reports