Certificate Management

X.509 certificates are essential for AS2 message security, providing encryption and digital signature capabilities. AS2aaS provides comprehensive certificate management at both account and tenant levels, supporting master certificates for operational efficiency and tenant-specific certificates for specialized requirements.

Certificate Types

Master Certificates (Account-Level)

Shared across all tenants in an account for operational efficiency:

  • Identity Certificates: Account-level signing and encryption certificates
  • Partner Certificates: Master partner certificates inherited by tenants
  • Cost Efficiency: Single certificate procurement and renewal process
  • Centralized Management: Unified certificate lifecycle management

Tenant Certificates

Tenant-specific certificates for specialized requirements:

  • Tenant Identity: Tenant-specific signing and encryption certificates
  • Tenant Partners: Partner certificates for tenant-only relationships
  • Custom Requirements: Certificates for specific tenant security needs

Certificate Usage by Type

Identity Certificates

Your organization's certificates used for:

  • Signing outbound messages (proves message authenticity)
  • Decrypting inbound messages (private key decryption)
  • Available at: Account level (shared) or tenant level (specific)

Partner Certificates

Trading partners' public certificates used for:

  • Encrypting outbound messages (using partner's public key)
  • Verifying inbound message signatures (using partner's public key)
  • Available at: Account level (master partners) or tenant level (tenant partners)

Certificate Operations

List Certificates

List Tenant Certificates

GET /v1/certificates

List Account Master Certificates

GET /v1/accounts/{account}/certificates

Query Parameters:

  • type (string) - Filter by type: identity, partner
  • active (boolean) - Filter by active status
  • expires_soon (boolean) - Certificates expiring within 30 days
  • partner_id (string) - Filter by specific partner
  • scope (string) - Filter by scope: account, tenant (tenant endpoint only)

Response (200):

{
  "data": [
    {
      "id": "cert_000001",
      "name": "Account Master Identity Certificate",
      "type": "identity",
      "usage": "signing",
      "scope": "account",
      "subject": "CN=My Company AS2, O=My Company Inc, C=US",
      "issuer": "CN=AS2aaS CA, O=AS2aaS Inc",
      "serial_number": "123456789abcdef",
      "fingerprint": "SHA256:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd",
      "active": true,
      "tenant_usage_count": 5,
      "expires_at": "2025-01-01T00:00:00Z",
      "created_at": "2024-01-01T10:00:00Z"
    },
    {
      "id": "cert_000002",
      "name": "McKesson Master Partner Certificate",
      "type": "partner",
      "usage": "encryption",
      "scope": "account",
      "partner_id": "prt_000001",
      "subject": "CN=McKesson AS2, O=McKesson Corporation, C=US",
      "issuer": "CN=McKesson CA, O=McKesson Corporation",
      "serial_number": "987654321fedcba",
      "fingerprint": "SHA256:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34",
      "active": true,
      "tenant_usage_count": 3,
      "expires_at": "2025-06-01T00:00:00Z",
      "created_at": "2024-01-01T10:00:00Z"
    },
    {
      "id": "cert_000003",
      "name": "East Coast Tenant Identity Certificate",
      "type": "identity",
      "usage": "signing",
      "scope": "tenant",
      "tenant_id": "tnt_000001",
      "subject": "CN=East Coast Division AS2, O=My Company Inc, C=US",
      "issuer": "CN=AS2aaS CA, O=AS2aaS Inc",
      "serial_number": "456789abcdef123",
      "fingerprint": "SHA256:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef",
      "active": true,
      "expires_at": "2025-03-01T00:00:00Z",
      "created_at": "2024-01-15T10:00:00Z"
    }
  ],
  "pagination": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 20,
    "total": 2
  }
}

Upload Certificate

Upload Tenant Certificate

POST /v1/certificates

Upload Account Master Certificate

POST /v1/accounts/{account}/certificates

Request (multipart/form-data):

Tenant Identity Certificate
curl -X POST https://api.as2aas.com/v1/certificates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=East Coast Identity Certificate" \
  -F "type=identity" \
  -F "usage=signing" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "password=cert-password"
Account Master Identity Certificate
curl -X POST https://api.as2aas.com/v1/accounts/acc_000001/certificates \
  -H "Authorization: Bearer YOUR_ACCOUNT_API_KEY" \
  -F "name=Account Master Identity Certificate" \
  -F "type=identity" \
  -F "usage=signing" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "password=cert-password"

Response (201):

{
  "message": "Certificate uploaded successfully",
  "data": {
    "id": "cert_000003",
    "name": "My Identity Certificate",
    "type": "identity",
    "usage": "signing",
    "subject": "CN=My Company AS2, O=My Company Inc",
    "fingerprint": "SHA256:ab:cd:ef:12...",
    "active": false,
    "expires_at": "2025-01-01T00:00:00Z",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Get Certificate Details

GET /v1/certificates/{certificate_id}

Delete Certificate

DELETE /v1/certificates/{certificate_id}

Activate Certificate

POST /v1/certificates/{certificate_id}/activate

Certificate Formats

Supported Formats

  • PEM (recommended) - Base64 encoded with headers
  • DER - Binary format
  • PKCS#12 - Combined certificate and private key
  • PKCS#7 - Certificate chain format

PEM Format Example

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvD/XaUMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
...
-----END CERTIFICATE-----

Partner Certificate Management

Upload Partner Certificate

POST /v1/partners/{partner_id}/certificates

Request:

curl -X POST https://api.as2aas.com/v1/partners/prt_000001/certificates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=Partner Encryption Certificate" \
  -F "usage=encryption" \
  -F "[email protected]"

List Partner Certificates

GET /v1/partners/{partner_id}/certificates

Activate Partner Certificate

POST /v1/partners/{partner_id}/certificates/{certificate_id}/activate

Remove Partner Certificate

DELETE /v1/partners/{partner_id}/certificates/{certificate_id}

Certificate Scoping and Inheritance

Account-Level (Master) Certificates

Master certificates are shared across all tenants in an account:

  • Automatic Inheritance: All tenants automatically inherit master certificates
  • Operational Efficiency: Single certificate management for multiple tenants
  • Cost Savings: One certificate renewal process instead of per-tenant
  • Centralized Control: Account-level certificate policies and lifecycle

Tenant-Level Certificates

Tenant-specific certificates override or supplement master certificates:

  • Tenant Isolation: Certificates scoped to specific tenant operations
  • Custom Requirements: Specialized certificates for unique tenant needs
  • Override Capability: Tenant certificates take precedence over master certificates
  • Granular Control: Tenant-specific certificate policies

Certificate Resolution Priority

When determining which certificate to use for AS2 operations:

  1. Tenant-specific certificate (highest priority)
  2. Account master certificate (inherited)
  3. Default system certificate (fallback)

Certificate Inheritance Example

{
  "account_certificates": [
    {
      "id": "cert_master_001",
      "name": "Account Master Identity",
      "type": "identity",
      "usage": "signing",
      "scope": "account",
      "inherited_by_tenants": ["tnt_001", "tnt_002", "tnt_003"]
    }
  ],
  "tenant_certificates": [
    {
      "id": "cert_tenant_001",
      "name": "East Coast Custom Identity",
      "type": "identity", 
      "usage": "signing",
      "scope": "tenant",
      "tenant_id": "tnt_001",
      "overrides": "cert_master_001"
    }
  ]
}

Certificate Usage

For Message Encryption

Using Master Certificates

Outbound Messages:

  1. Upload partner's public certificate at account level
  2. All tenants inherit this certificate automatically
  3. AS2aaS encrypts messages using partner's public key
  4. Partner decrypts using their private key

Using Tenant Certificates

Outbound Messages:

  1. Upload partner's public certificate at tenant level
  2. Only specific tenant uses this certificate
  3. Tenant certificate overrides master certificate if both exist

Inbound Messages:

  1. Upload your identity certificate (private key) at account or tenant level
  2. Partner encrypts message using your public key
  3. AS2aaS decrypts using your private key (account master or tenant-specific)

For Digital Signatures

Outbound Messages:

  1. Upload your identity certificate (private key) at appropriate level
  2. AS2aaS signs message using your private key
  3. Partner verifies signature using your public key

Inbound Messages:

  1. Upload partner's public certificate at appropriate level
  2. Partner signs message using their private key
  3. AS2aaS verifies signature using partner's public key

Certificate Lifecycle

Certificate Status

StatusDescription
pendingUploaded but not yet activated
activeCurrently in use for AS2 operations
inactiveDeactivated but retained
expiredPast expiration date

Expiry Management

Check Expiring Certificates:

GET /v1/certificates?expires_soon=true

Expiry Webhook Event:

{
  "event": "certificate.expiring",
  "data": {
    "id": "cert_000001",
    "name": "Partner Certificate",
    "type": "partner",
    "subject": "CN=Partner AS2",
    "expires_at": "2024-02-15T00:00:00Z",
    "days_until_expiry": 30
  },
  "timestamp": "2024-01-15T10:30:00Z"
}

Certificate Renewal

// Monitor and renew certificates
async function checkCertificateExpiry() {
  const expiring = await as2.certificates.list({ expires_soon: true });
  
  for (const cert of expiring.data) {
    if (cert.days_until_expiry <= 30) {
      await notifyAdmin(`Certificate ${cert.name} expires in ${cert.days_until_expiry} days`);
      
      if (cert.type === 'identity') {
        await generateNewIdentityCertificate(cert);
      } else {
        await requestPartnerCertificateUpdate(cert.partner_id);
      }
    }
  }
}

Certificate Validation

Validate Certificate

POST /v1/certificates/{certificate_id}/validate

Response (200):

{
  "valid": true,
  "checks": [
    {
      "name": "Format Validation",
      "status": "pass",
      "message": "Certificate is in valid PEM format"
    },
    {
      "name": "Expiry Check", 
      "status": "pass",
      "message": "Certificate is valid until 2025-01-01"
    },
    {
      "name": "Key Usage",
      "status": "pass",
      "message": "Certificate supports required key usage"
    },
    {
      "name": "Chain Validation",
      "status": "pass",
      "message": "Certificate chain is valid"
    }
  ],
  "details": {
    "subject": "CN=My Company AS2",
    "issuer": "CN=AS2aaS CA",
    "valid_from": "2024-01-01T00:00:00Z",
    "valid_until": "2025-01-01T00:00:00Z",
    "key_size": 2048,
    "signature_algorithm": "SHA256withRSA"
  }
}

Security Best Practices

Certificate Security

  1. Private Key Protection: Store private keys securely
  2. Regular Rotation: Renew certificates annually
  3. Strong Algorithms: Use SHA256 or higher
  4. Key Size: Use 2048-bit minimum, 4096-bit for high security
  5. Certificate Validation: Verify certificates before activation

Certificate Storage

AS2aaS securely stores certificates with:

  • Encryption at rest using AES-256
  • Access controls limited to your tenant
  • Audit logging for all certificate operations
  • Secure deletion when certificates are removed

Integration Examples

Automated Certificate Management

// Comprehensive certificate management
class CertificateManager {
  constructor(as2Client) {
    this.as2 = as2Client;
  }
  
  async uploadPartnerCertificate(partnerId, certFile, usage = 'encryption') {
    const formData = new FormData();
    formData.append('name', `Partner ${usage} Certificate`);
    formData.append('usage', usage);
    formData.append('certificate', certFile);
    
    const cert = await this.as2.partners.uploadCertificate(partnerId, formData);
    
    // Validate certificate
    const validation = await this.as2.certificates.validate(cert.id);
    if (!validation.valid) {
      throw new Error(`Certificate validation failed: ${validation.message}`);
    }
    
    // Activate certificate
    await this.as2.certificates.activate(cert.id);
    
    return cert;
  }
  
  async monitorExpiry() {
    const expiring = await this.as2.certificates.list({ expires_soon: true });
    
    for (const cert of expiring.data) {
      if (cert.days_until_expiry <= 7) {
        await this.urgentRenewalAlert(cert);
      } else if (cert.days_until_expiry <= 30) {
        await this.renewalReminder(cert);
      }
    }
  }
}

Certificate Chain Validation

// Validate complete certificate chain
async function validateCertificateChain(certificateId) {
  const validation = await as2.certificates.validate(certificateId);
  
  const issues = validation.checks
    .filter(check => check.status !== 'pass')
    .map(check => check.message);
    
  if (issues.length > 0) {
    console.warn('Certificate issues found:', issues);
    return false;
  }
  
  console.log('Certificate validation passed');
  return true;
}

Error Handling

Common Certificate Errors

Error CodeDescriptionResolution
INVALID_FORMATCertificate format not supportedUse PEM or DER format
EXPIRED_CERTIFICATECertificate has expiredUpload new certificate
INVALID_KEY_USAGECertificate doesn't support required usageCheck certificate key usage extensions
CHAIN_INCOMPLETECertificate chain is incompleteInclude intermediate certificates
PRIVATE_KEY_MISMATCHPrivate key doesn't match certificateVerify key pair matches

Certificate Error Response

{
  "error": {
    "type": "certificate_error",
    "code": "EXPIRED_CERTIFICATE",
    "message": "Certificate expired on 2024-01-10T00:00:00Z",
    "details": {
      "certificate_id": "cert_000001",
      "subject": "CN=Partner AS2",
      "expired_at": "2024-01-10T00:00:00Z",
      "days_expired": 5
    }
  }
}

Certificate Workflows

New Partner Setup

async function setupNewPartner(partnerData) {
  // 1. Create partner
  const partner = await as2.partners.create({
    name: partnerData.name,
    as2_id: partnerData.as2_id,
    url: partnerData.endpoint,
    encrypt: true,
    sign: true
  });
  
  // 2. Upload partner's encryption certificate
  if (partnerData.encryptionCert) {
    await as2.certificates.upload({
      partner_id: partner.id,
      name: `${partner.name} Encryption`,
      type: 'partner',
      usage: 'encryption',
      certificate: partnerData.encryptionCert
    });
  }
  
  // 3. Upload partner's signing certificate (if different)
  if (partnerData.signingCert && partnerData.signingCert !== partnerData.encryptionCert) {
    await as2.certificates.upload({
      partner_id: partner.id,
      name: `${partner.name} Signing`,
      type: 'partner',
      usage: 'signing',
      certificate: partnerData.signingCert
    });
  }
  
  return partner;
}

Certificate Renewal

async function renewCertificate(certificateId) {
  const cert = await as2.certificates.get(certificateId);
  
  if (cert.type === 'identity') {
    // Generate new identity certificate
    const newCert = await as2.certificates.generateIdentity({
      common_name: cert.subject.match(/CN=([^,]+)/)[1],
      organization: cert.subject.match(/O=([^,]+)/)?.[1],
      country: cert.subject.match(/C=([^,]+)/)?.[1],
      key_size: 2048,
      validity_days: 365
    });
    
    // Activate new certificate
    await as2.certificates.activate(newCert.id);
    
    // Deactivate old certificate
    await as2.certificates.deactivate(certificateId);
    
    return newCert;
  } else {
    // Partner certificate - request new one from partner
    throw new Error('Partner certificates must be renewed by the partner');
  }
}

Certificate Download

Download Certificate

GET /v1/certificates/{certificate_id}/download

Query Parameters:

  • format (string) - pem, der, pkcs12
  • include_chain (boolean) - Include certificate chain
  • password (string) - Password for PKCS12 format

Response: Certificate file with appropriate Content-Type

Download Public Key Only

GET /v1/certificates/{certificate_id}/public-key

Returns just the public key portion of the certificate.

Certificate Information

Get Certificate Info

GET /v1/certificates/{certificate_id}/info

Response (200):

{
  "data": {
    "subject": {
      "common_name": "My Company AS2",
      "organization": "My Company Inc",
      "country": "US"
    },
    "issuer": {
      "common_name": "AS2aaS CA",
      "organization": "AS2aaS Inc"
    },
    "validity": {
      "not_before": "2024-01-01T00:00:00Z",
      "not_after": "2025-01-01T00:00:00Z",
      "days_remaining": 351
    },
    "key_info": {
      "algorithm": "RSA",
      "size": 2048,
      "usage": ["digital_signature", "key_encipherment"]
    },
    "extensions": {
      "key_usage": ["digital_signature", "key_encipherment"],
      "extended_key_usage": ["client_auth", "server_auth"],
      "subject_alt_names": ["email:[email protected]"]
    },
    "fingerprints": {
      "sha1": "12:34:56:78:90:ab:cd:ef",
      "sha256": "ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd"
    }
  }
}

Certificate Monitoring

Expiry Monitoring

GET /v1/certificates/expiry-report

Response (200):

{
  "data": {
    "expiring_soon": [
      {
        "id": "cert_000001",
        "name": "Partner Certificate",
        "expires_at": "2024-02-15T00:00:00Z",
        "days_remaining": 30
      }
    ],
    "expired": [],
    "total_certificates": 5,
    "health_score": 100
  }
}

Certificate Events

Webhook Events:

  • certificate.uploaded - New certificate uploaded
  • certificate.activated - Certificate activated for use
  • certificate.expiring - Certificate expires within 30 days
  • certificate.expired - Certificate has expired
  • certificate.validation_failed - Certificate validation failed

Troubleshooting

Common Issues

Certificate Upload Fails

  • Check file format (PEM recommended)
  • Verify certificate and private key match
  • Ensure certificate is not expired
  • Check file size limits (10MB max)

Message Encryption Fails

  • Verify partner's encryption certificate is uploaded and active
  • Check encryption algorithm compatibility
  • Ensure certificate supports encryption key usage

Signature Verification Fails

  • Verify partner's signing certificate is uploaded
  • Check signature algorithm matches partner's capability
  • Ensure certificate chain is complete

Debug Certificate Issues

# Get detailed certificate information
GET /v1/certificates/{certificate_id}/debug

Returns detailed validation results, key usage information, and compatibility checks.

Getting Help

For certificate issues:

  1. Use certificate validation to identify specific problems
  2. Check expiry dates and renewal requirements
  3. Verify certificate formats and key usage
  4. Contact support with certificate ID for investigation

Advanced Features

Certificate Templates

Create reusable certificate templates for consistent partner onboarding:

{
  "name": "Standard Partner Template",
  "subject_template": "CN={{partner_name}} AS2, O={{partner_org}}, C=US",
  "key_size": 2048,
  "validity_days": 365,
  "key_usage": ["digital_signature", "key_encipherment"]
}

Bulk Certificate Operations

// Upload multiple partner certificates
async function bulkUploadCertificates(certificateList) {
  const results = [];
  
  for (const certData of certificateList) {
    try {
      const cert = await as2.certificates.upload(certData);
      await as2.certificates.activate(cert.id);
      results.push({ success: true, certificate: cert });
    } catch (error) {
      results.push({ success: false, error: error.message, data: certData });
    }
  }
  
  return results;
}

Certificate Backup

// Backup all certificates
async function backupCertificates() {
  const certificates = await as2.certificates.list({ per_page: 100 });
  
  for (const cert of certificates.data) {
    if (cert.type === 'identity') {
      // Download and backup identity certificates
      const certData = await as2.certificates.download(cert.id, { format: 'pkcs12' });
      await saveToSecureStorage(`backup-${cert.id}.p12`, certData);
    }
  }
}