Certificate Chain Architecture
CODITECT Biosciences QMS Platform
Document Control
| Field | Value |
|---|---|
| Document ID | BIO-QMS-ARCH-004 |
| Version | 1.0.0 |
| Status | Active |
| Author | CODITECT Security Architecture Team |
| Effective Date | 2026-02-16 |
| Review Cycle | Annual |
| Related Documents | Security Architecture (BIO-QMS-ARCH-001), E-Signature Architecture (BIO-QMS-ARCH-002), HSM Key Management (D.1.2) |
| Regulatory Scope | FDA 21 CFR Part 11, HIPAA §164.312(e), SOC 2 CC6.1 |
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-02-16 | Security Architect | Initial release |
1. Executive Summary
This document defines the Public Key Infrastructure (PKI) certificate hierarchy for the CODITECT Biosciences Quality Management System (BIO-QMS) platform. The architecture establishes a three-tier certificate authority structure designed to support:
- Regulatory-compliant electronic signatures (FDA 21 CFR Part 11 §11.70 cryptographic binding)
- Multi-tenant isolation (per-organization intermediate CAs)
- Service-to-service authentication (mTLS for microservices)
- Long-term signature validation (LTV for audit trails spanning decades)
The certificate chain provides the cryptographic foundation that closes the FDA Part 11 §11.70 gap identified in the Regulatory Compliance Matrix by binding electronic signatures to their respective records through verifiable certificate chains.
Key Design Principles:
- Offline Root CA: Air-gapped, HSM-backed root certificate authority used solely to sign intermediate CAs
- Per-Tenant Intermediate CAs: Each customer organization receives a dedicated intermediate CA for cryptographic tenant isolation
- Purpose-Specific End-Entity Certificates: Distinct certificate profiles for user signing, service identity, agent delegation, and code signing
- Automated Lifecycle Management: Certificate issuance, renewal, and revocation with zero-touch operations
- Long-Term Validation: Embedded OCSP responses and CRLs ensure signature validity beyond certificate expiry
Compliance Benefits:
- FDA §11.70: Cryptographic binding of signatures to records via certificate-based digital signatures
- FDA §11.100: Unique certificates per individual prevent signature reuse
- HIPAA §164.312(e): TLS certificates secure PHI transmission
- SOC 2 CC6.1: Certificate-based access controls with audit trails
2. Certificate Hierarchy Design
2.1 Three-Tier PKI Architecture
The BIO-QMS platform implements a hierarchical PKI with three certificate levels:
CODITECT Root CA (Offline, 20-year)
│
├── Intermediate CA: OrganizationA (Online, 5-year)
│ ├── User Signing Certificate: alice@orgA.bio (1-year)
│ ├── User Signing Certificate: bob@orgA.bio (1-year)
│ ├── Service Certificate: api.orgA.bio-qms.coditect.cloud (1-year)
│ └── Agent Certificate: agent-wo-12345 (24-hour)
│
├── Intermediate CA: OrganizationB (Online, 5-year)
│ ├── User Signing Certificate: charlie@orgB.bio (1-year)
│ ├── Service Certificate: api.orgB.bio-qms.coditect.cloud (1-year)
│ └── Agent Certificate: agent-wo-67890 (24-hour)
│
└── Intermediate CA: CODITECT-Services (Online, 5-year)
├── Service Certificate: platform-api.bio-qms.coditect.cloud (1-year)
├── Service Certificate: ca-service.bio-qms.coditect.cloud (1-year)
└── Code Signing Certificate: deployment-pipeline (2-year)
2.2 Root CA (Tier 1)
Purpose: Organizational trust anchor for the entire BIO-QMS PKI.
Characteristics:
| Property | Value |
|---|---|
| Subject | CN=CODITECT BIO-QMS Root CA, O=AZ1.AI INC, C=US |
| Key Algorithm | ECDSA P-256 (NIST FIPS 186-4 compliant) |
| Signature Algorithm | ECDSA with SHA-256 |
| Validity Period | 20 years (2026-2046) |
| Key Usage | Certificate Signing, CRL Signing |
| Basic Constraints | CA:TRUE, pathlen:1 (can sign intermediates only) |
| Storage | Hardware Security Module (Google Cloud HSM or Thales Luna) |
| Operational State | Offline (air-gapped system, powered on only for intermediate CA signing) |
| Key Ceremony | Multi-person control (M-of-N recovery, 3-of-5 minimum) |
Root CA Key Generation Ceremony:
-
Preparation Phase:
- Secure facility with physical access controls
- Witness panel (minimum 3: CISO, VP Engineering, Legal Counsel)
- Notarized documentation of attendees and procedures
- HSM initialization and firmware verification
-
Key Generation:
- Generate ECDSA P-256 key pair within HSM
- Export key backup shares (M-of-N scheme)
- Seal backup shares in tamper-evident envelopes
- Distribute shares to geographically separated secure storage (safety deposit boxes)
-
Self-Signature:
- Create self-signed root certificate
- Export root certificate public key (PEM format)
- Publish root certificate to trust distribution channels
-
Secure Storage:
- Power down HSM
- Store HSM in vault (dual control access)
- Document chain of custody
Root CA Usage Events:
- Initial intermediate CA signing (per new tenant onboarding)
- Intermediate CA renewal (every 5 years)
- Intermediate CA revocation (tenant offboarding or compromise)
- Annual root CA health check (verify HSM integrity, no signing operations)
2.3 Intermediate CA (Tier 2)
Purpose: Per-organization certificate authority for issuing end-entity certificates to users and services within a tenant boundary.
Multi-Tenant Isolation Model:
Each customer organization receives a dedicated intermediate CA. This provides:
- Cryptographic Tenant Isolation: Organization A's certificates cannot validate against Organization B's intermediate CA
- Independent Revocation: Tenant offboarding revokes only that tenant's intermediate CA
- Regulatory Boundary: Per-organization audit trails and compliance attestation
- Key Segregation: Compromise of one tenant's intermediate CA does not affect others
Intermediate CA Characteristics:
| Property | Value |
|---|---|
| Subject | CN={OrganizationName} BIO-QMS Intermediate CA, O={OrganizationName}, OU=BIO-QMS, C=US |
| Issuer | CODITECT BIO-QMS Root CA |
| Key Algorithm | ECDSA P-256 |
| Signature Algorithm | ECDSA with SHA-256 |
| Validity Period | 5 years (renewable before expiry) |
| Key Usage | Certificate Signing, CRL Signing, Digital Signature |
| Basic Constraints | CA:TRUE, pathlen:0 (can sign end-entities only) |
| CRL Distribution Points | http://crl.bio-qms.coditect.cloud/{orgId}/intermediate.crl |
| OCSP Responder | http://ocsp.bio-qms.coditect.cloud/{orgId} |
| Storage | Google Cloud HSM (FIPS 140-2 Level 3) |
| Operational State | Online (accessible via CA signing service with strict RBAC) |
Intermediate CA Lifecycle:
-
Provisioning (Tenant Onboarding):
- New organization signs SaaS contract
- Generate intermediate CA key pair in HSM (dedicated key per tenant)
- Create Certificate Signing Request (CSR)
- Power on Root CA HSM
- Sign intermediate CSR with Root CA key
- Power down Root CA HSM
- Publish intermediate CA certificate to tenant namespace
- Configure CRL and OCSP endpoints
-
Operation:
- Issue user signing certificates (on-demand per user registration)
- Issue service certificates (per tenant workload deployment)
- Issue agent certificates (ephemeral, 24hr validity)
- Publish hourly CRLs
- Respond to OCSP requests in real-time
-
Renewal:
- 90 days before expiry: alert CA administrators
- 60 days before expiry: generate new intermediate key pair
- 45 days before expiry: power on Root CA, sign new intermediate CSR
- 30 days before expiry: publish new intermediate certificate
- Dual-publication period: both old and new intermediates valid for 30 days
- Migration: re-issue all end-entity certificates under new intermediate
-
Revocation (Tenant Offboarding):
- Revoke intermediate CA certificate in Root CA CRL
- Destroy intermediate CA private key (crypto-shredding)
- Archive all issued end-entity certificates (compliance retention)
- Decommission tenant OCSP and CRL endpoints
Special Intermediate CA: CODITECT-Services
A dedicated intermediate CA (CN=CODITECT-Services BIO-QMS Intermediate CA) issues certificates for:
- Platform-level services (API gateway, CA service, monitoring)
- Cross-tenant infrastructure (shared Kubernetes control plane)
- Code signing certificates for deployment pipelines
This intermediate is managed by CODITECT operations and follows the same lifecycle as tenant intermediates.
2.4 End-Entity Certificates (Tier 3)
Purpose: Certificates issued to users, services, and agents for authentication and digital signatures.
2.4.1 User Signing Certificates
Use Case: Electronic signatures on quality documents, SOPs, deviations, CAPAs, work orders.
Profile:
| Property | Value |
|---|---|
| Subject | CN={firstName} {lastName} ({email}), O={OrganizationName}, OU=BIO-QMS Users, C=US |
| Issuer | {OrganizationName} BIO-QMS Intermediate CA |
| Key Algorithm | ECDSA P-256 (generated in browser WebCrypto or Yubikey) |
| Signature Algorithm | ECDSA with SHA-256 |
| Validity Period | 1 year (365 days) |
| Key Usage | Digital Signature, Non-Repudiation |
| Extended Key Usage | Email Protection (1.3.6.1.5.5.7.3.4) |
| Subject Alternative Name | email:{user}@{orgdomain}.com |
| CRL Distribution Points | http://crl.bio-qms.coditect.cloud/{orgId}/user-certs.crl |
| OCSP Responder | http://ocsp.bio-qms.coditect.cloud/{orgId} |
Unique Attributes:
- Non-Repudiation: Key usage includes non-repudiation to satisfy FDA Part 11 signature requirements
- Email Binding: SAN includes user's corporate email for identity verification
- Browser Storage: Private key stored in browser IndexedDB (WebCrypto non-extractable key) or hardware token (Yubikey, smart card)
2.4.2 Service Identity Certificates
Use Case: mTLS authentication between microservices, API gateway TLS termination.
Profile:
| Property | Value |
|---|---|
| Subject | CN={serviceName}.{orgId}.bio-qms.coditect.cloud, O={OrganizationName}, OU=BIO-QMS Services, C=US |
| Issuer | {OrganizationName} BIO-QMS Intermediate CA |
| Key Algorithm | ECDSA P-256 |
| Signature Algorithm | ECDSA with SHA-256 |
| Validity Period | 1 year (365 days) |
| Key Usage | Digital Signature, Key Encipherment |
| Extended Key Usage | Server Authentication (1.3.6.1.5.5.7.3.1), Client Authentication (1.3.6.1.5.5.7.3.2) |
| Subject Alternative Name | DNS:{serviceName}.{namespace}.svc.cluster.local, DNS:{serviceName}.{orgId}.bio-qms.coditect.cloud |
| Storage | Kubernetes Secret (encrypted at rest with Google Cloud KMS) |
Automatic Rotation:
Service certificates are automatically renewed 30 days before expiry via cert-manager Kubernetes operator. The renewal process:
- cert-manager detects expiry window
- Generates new ECDSA key pair
- Creates CSR
- Calls CA service API with service account JWT authentication
- CA service validates namespace and service identity
- Issues new certificate
- cert-manager updates Kubernetes Secret
- Workloads reload certificate (hot reload or rolling restart)
2.4.3 Agent Ephemeral Certificates
Use Case: Agent-delegated electronic signatures with pre-authorization (work order execution, automated QC checks).
Profile:
| Property | Value |
|---|---|
| Subject | CN=Agent {agentId}, O={OrganizationName}, OU=BIO-QMS Agents, C=US |
| Issuer | {OrganizationName} BIO-QMS Intermediate CA |
| Key Algorithm | ECDSA P-256 |
| Signature Algorithm | ECDSA with SHA-256 |
| Validity Period | 24 hours (86400 seconds) |
| Key Usage | Digital Signature |
| Extended Key Usage | Custom OID: 1.3.6.1.4.1.59999.1.1.1 (Agent Delegation) |
| Certificate Policy | 1.3.6.1.4.1.59999.2.1 (Agent Pre-Authorization Policy) |
| Subject Alternative Name | URI:urn:coditect:bio-qms:agent:{agentId} |
| Custom Extension | AgentAuthorization: { "delegatedBy": "{userId}", "workOrderId": "{woId}", "expiresAt": "ISO8601" } |
Agent Certificate Workflow:
- User initiates agent-delegated task (e.g., "Auto-approve QC checks for WO-12345")
- User re-authenticates with MFA (FDA Part 11 §11.200 requirement)
- System records pre-authorization: user ID, agent scope (single work order), expiry (24hr)
- CA service issues ephemeral agent certificate with custom extension containing authorization metadata
- Agent executes tasks within scope (e.g., sign QC checkpoints)
- Each signature includes agent certificate + original user pre-authorization audit record
- Certificate expires after 24hr, automatically invalidated (no revocation needed)
Regulatory Compliance:
- FDA Part 11 §11.50: Signature manifestation includes original user's name and agent authorization timestamp
- FDA Part 11 §11.100: Agent certificate is bound to specific user authorization (not reusable)
- Audit trail captures both agent action and original human authorization
2.4.4 Code Signing Certificates
Use Case: Sign container images, Kubernetes manifests, Terraform plans, and deployment artifacts.
Profile:
| Property | Value |
|---|---|
| Subject | CN=CODITECT BIO-QMS Deployment Pipeline, O=AZ1.AI INC, OU=BIO-QMS Engineering, C=US |
| Issuer | CODITECT-Services BIO-QMS Intermediate CA |
| Key Algorithm | RSA 3072-bit (broader tool compatibility vs ECDSA) |
| Signature Algorithm | SHA-256 with RSA |
| Validity Period | 2 years (730 days) |
| Key Usage | Digital Signature |
| Extended Key Usage | Code Signing (1.3.6.1.5.5.7.3.3) |
| Storage | Google Cloud KMS (HSM-backed, restricted IAM access) |
Signed Artifacts:
- Container Images: Cosign signatures for all production images pushed to GCP Artifact Registry
- Kubernetes Manifests: Signed Git commits and Helm charts
- Infrastructure as Code: Signed Terraform plans before apply
- Release Packages: Customer-downloadable installers and updates
3. Certificate Profiles
3.1 X.509 v3 Profile Summary
| Certificate Type | Algorithm | Validity | Key Usage | Extended Key Usage | Subject Format |
|---|---|---|---|---|---|
| Root CA | ECDSA P-256 | 20 years | Certificate Signing, CRL Signing | (none) | CN=CODITECT BIO-QMS Root CA, O=AZ1.AI INC, C=US |
| Intermediate CA | ECDSA P-256 | 5 years | Certificate Signing, CRL Signing, Digital Signature | (none) | CN={OrgName} BIO-QMS Intermediate CA, O={OrgName}, OU=BIO-QMS, C=US |
| User Signing | ECDSA P-256 | 1 year | Digital Signature, Non-Repudiation | Email Protection | CN={Name} ({email}), O={OrgName}, OU=BIO-QMS Users, C=US |
| Service Identity | ECDSA P-256 | 1 year | Digital Signature, Key Encipherment | Server Auth, Client Auth | CN={service}.{org}.bio-qms.coditect.cloud, O={OrgName}, OU=BIO-QMS Services, C=US |
| Agent Ephemeral | ECDSA P-256 | 24 hours | Digital Signature | Custom OID (Agent Delegation) | CN=Agent {agentId}, O={OrgName}, OU=BIO-QMS Agents, C=US |
| Code Signing | RSA 3072 | 2 years | Digital Signature | Code Signing | CN=CODITECT BIO-QMS Deployment Pipeline, O=AZ1.AI INC, OU=BIO-QMS Engineering, C=US |
3.2 Certificate Extensions
3.2.1 Standard Extensions (All Certificates)
| Extension | Critical | Value |
|---|---|---|
| Basic Constraints | Yes | CA:TRUE (CAs), CA:FALSE (end-entities) |
| Key Usage | Yes | Per certificate type (see table above) |
| Subject Key Identifier | No | SHA-1 hash of public key |
| Authority Key Identifier | No | Key identifier of issuing CA |
3.2.2 CRL Distribution Points (All Non-Root Certificates)
CRL Distribution Points:
[1] CRL Distribution Point
Distribution Point Name:
Full Name:
URI:http://crl.bio-qms.coditect.cloud/{orgId}/{certType}.crl
Published hourly. CRL validity period: 7 days (168 hours).
3.2.3 Authority Information Access (All Non-Root Certificates)
Authority Information Access:
[1] CA Issuers - URI:http://certs.bio-qms.coditect.cloud/{orgId}/intermediate-ca.cer
[2] OCSP - URI:http://ocsp.bio-qms.coditect.cloud/{orgId}
OCSP responses include:
- Good: Certificate valid, no revocation
- Revoked: Certificate revoked (reason code, revocation date)
- Unknown: Certificate not found in CA database
3.2.4 Custom Extensions (Agent Certificates Only)
OID: 1.3.6.1.4.1.59999.1.2.1 (CODITECT Private Enterprise Number assigned by IANA)
Extension Name: AgentAuthorizationInfo
ASN.1 Structure:
AgentAuthorizationInfo ::= SEQUENCE {
delegatedBy UTF8String, -- User ID who authorized agent
authorizationId UTF8String, -- Unique authorization record ID
workOrderScope UTF8String, -- Work order ID or "NONE" for global
authorizedAt GeneralizedTime, -- ISO 8601 authorization timestamp
expiresAt GeneralizedTime -- ISO 8601 expiry (max 24hr from authorized)
}
Example:
{
"delegatedBy": "alice@orgA.bio",
"authorizationId": "AUTH-20260216-001234",
"workOrderScope": "WO-12345",
"authorizedAt": "2026-02-16T08:00:00Z",
"expiresAt": "2026-02-17T08:00:00Z"
}
This extension is non-critical (systems unaware of the extension can still process the certificate, but should treat it as a regular user signature).
4. Certificate Lifecycle Management
4.1 Certificate Issuance Workflow
4.1.1 User Signing Certificate Issuance
Trigger: User completes onboarding and requests electronic signature capability.
Prerequisites:
- User account active in tenant organization
- User completed GxP training (for regulated users)
- User verified via corporate email (email confirmation link)
- User enrolled MFA device (TOTP or hardware token)
Workflow:
Step Details:
-
Key Generation (Client-Side):
const keyPair = await window.crypto.subtle.generateKey(
{
name: 'ECDSA',
namedCurve: 'P-256'
},
false, // non-extractable
['sign', 'verify']
);
const publicKeyJwk = await window.crypto.subtle.exportKey('jwk', keyPair.publicKey); -
CSR Metadata:
{
"publicKey": "{JWK format}",
"subject": {
"commonName": "Alice Johnson (alice@orgA.bio)",
"organization": "OrganizationA",
"organizationalUnit": "BIO-QMS Users",
"country": "US"
},
"subjectAltName": {
"email": "alice@orgA.bio"
}
} -
CA Service Validation:
- User ID matches authenticated JWT subject
- User belongs to specified organization ID
- User has no active (non-revoked, non-expired) signing certificate
- Public key is valid ECDSA P-256 key
-
Certificate Construction:
- Generate unique serial number (128-bit random, hex-encoded)
- Set validity: notBefore = now, notAfter = now + 1 year
- Include all required extensions (key usage, extended key usage, CRL DP, AIA)
- Sign with intermediate CA private key via HSM API
-
Storage:
- Database: Certificate metadata (serial, subject DN, PEM, validity dates)
- Audit Log: User ID, certificate serial, issuance timestamp, issuing CA admin
- No Private Key Storage: User's private key never leaves browser
-
Certificate Chain: Return to user:
- User certificate (PEM)
- Intermediate CA certificate (PEM)
- Root CA certificate (PEM)
User stores all three for signature operations (full chain required for verification).
4.1.2 Service Certificate Issuance (Automated)
Trigger: Kubernetes workload deployed with cert-manager annotation.
Workflow:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-server-tls
namespace: org-a-production
spec:
secretName: api-server-tls-secret
duration: 8760h # 1 year
renewBefore: 720h # 30 days
subject:
organizations:
- OrganizationA
organizationalUnits:
- BIO-QMS Services
commonName: api.orgA.bio-qms.coditect.cloud
dnsNames:
- api.orgA.bio-qms.coditect.cloud
- api-server.org-a-production.svc.cluster.local
issuerRef:
name: bio-qms-ca-issuer
kind: ClusterIssuer
cert-manager automatically:
- Generates ECDSA P-256 key pair
- Creates CSR
- Calls CA service API (
POST /ca/certificates/issuewith service account JWT) - Stores certificate in Kubernetes Secret
api-server-tls-secret - Triggers workload restart (or hot-reload if supported)
4.2 Certificate Renewal
4.2.1 User Certificate Renewal
Timeline:
- Day -30: Email notification to user (certificate expires in 30 days)
- Day -14: In-app banner (certificate expires in 14 days, click to renew)
- Day -7: Email notification + in-app modal (certificate expires in 7 days, action required)
- Day -1: Email notification + in-app blocking modal (certificate expires tomorrow, renew now)
- Day 0: Certificate expires, signature operations blocked
Renewal Process:
-
Option 1: Rekey (recommended for security best practices)
- User generates new key pair in browser
- Submits new CSR with new public key
- Receives new certificate
- Old certificate remains valid until expiry (both certificates valid during transition)
- Old certificate auto-revoked upon expiry
-
Option 2: Same Key Renewal (convenience)
- User requests renewal with existing public key
- CA issues new certificate with same key
- Old certificate immediately revoked
- User replaces certificate in storage
Implementation:
// User Certificate Renewal API
POST /users/me/certificates/renew
{
"renewalType": "rekey" | "same-key",
"publicKey": "{JWK}" // only if renewalType=rekey
}
Response:
{
"certificate": "{PEM}",
"chain": ["{intermediate PEM}", "{root PEM}"],
"serialNumber": "0xABCDEF123456",
"expiresAt": "2027-02-16T08:00:00Z",
"oldCertificateStatus": "active" | "revoked"
}
4.2.2 Service Certificate Renewal (Automatic)
Handled entirely by cert-manager:
- Monitors certificate expiry
- Automatically renews 30 days before expiry (configurable via
renewBefore) - Generates new key pair (always rekey for services)
- Updates Kubernetes Secret
- Triggers workload reload
No manual intervention required.
4.3 Certificate Revocation
Revocation Reasons (per RFC 5280):
| Code | Reason | Use Case |
|---|---|---|
| 0 | Unspecified | Generic revocation (no specific reason) |
| 1 | Key Compromise | User reports private key stolen/exposed |
| 2 | CA Compromise | Intermediate CA key compromised (revoke all issued certs) |
| 3 | Affiliation Changed | User left organization or role changed |
| 4 | Superseded | Certificate replaced (renewal with new key) |
| 5 | Cessation of Operation | Service decommissioned |
| 6 | Certificate Hold | Temporary suspension (investigation, not permanent revocation) |
| 9 | Privilege Withdrawn | User's signature authority revoked by admin |
4.3.1 User Certificate Revocation
Triggers:
- User reports private key compromise
- User leaves organization (offboarding)
- Administrator revokes user's signature authority (privilege withdrawn)
- User certificate superseded by renewal
Workflow:
Revocation Propagation Time:
- CRL: Published immediately upon revocation (normally hourly, but triggered on revocation event)
- OCSP: Real-time (queries database on each request)
- Certificate Validation: Applications check CRL (cached up to 1 hour) or OCSP (real-time) before accepting signatures
4.3.2 Certificate Suspension (Hold)
Use Case: Temporary suspension during security investigation (e.g., suspicious signature activity).
Behavior:
- Certificate marked with revocation reason
certificateHold(code 6) - Included in CRL and OCSP responses as revoked
- Reversible: Administrator can remove hold status, certificate becomes valid again
Workflow:
// Suspend certificate
POST /admin/certificates/{serial}/suspend
{
"reason": "Security investigation case INV-12345"
}
// Resume certificate (remove hold)
POST /admin/certificates/{serial}/resume
{
"reason": "Investigation concluded, no compromise found"
}
4.4 Certificate Revocation List (CRL)
Publication Schedule: Hourly (on the hour) + immediate publication on revocation events.
CRL Validity Period: 7 days (168 hours).
CRL Structure:
CertificateList ::= SEQUENCE {
tbsCertList TBSCertList,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}
TBSCertList ::= SEQUENCE {
version Version OPTIONAL,
signature AlgorithmIdentifier,
issuer Name,
thisUpdate Time,
nextUpdate Time,
revokedCertificates SEQUENCE OF SEQUENCE {
userCertificate CertificateSerialNumber,
revocationDate Time,
crlEntryExtensions Extensions OPTIONAL
}
}
CRL Distribution:
- Primary: Google Cloud Storage (GCS) bucket with public read access
- CDN: Cloud CDN for global low-latency access
- HTTP URL:
http://crl.bio-qms.coditect.cloud/{orgId}/{certType}.crl - HTTPS: Optional, but CRLs are signed so integrity is verified regardless of transport
CRL Files per Tenant:
user-certs.crl- All user signing certificatesservice-certs.crl- All service identity certificatesagent-certs.crl- All agent ephemeral certificates (typically empty, as 24hr expiry handles revocation)
4.5 OCSP Responder
Purpose: Real-time certificate revocation status checking.
Endpoint: http://ocsp.bio-qms.coditect.cloud/{orgId}
OCSP Request:
OCSPRequest ::= SEQUENCE {
tbsRequest TBSRequest,
optionalSignature [0] EXPLICIT Signature OPTIONAL
}
TBSRequest ::= SEQUENCE {
requestList SEQUENCE OF Request
}
Request ::= SEQUENCE {
reqCert CertID
}
CertID ::= SEQUENCE {
hashAlgorithm AlgorithmIdentifier,
issuerNameHash OCTET STRING,
issuerKeyHash OCTET STRING,
serialNumber CertificateSerialNumber
}
OCSP Response:
OCSPResponse ::= SEQUENCE {
responseStatus OCSPResponseStatus,
responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
}
OCSPResponseStatus ::= ENUMERATED {
successful (0),
malformedRequest (1),
internalError (2),
tryLater (3),
sigRequired (5),
unauthorized (6)
}
ResponseBytes ::= SEQUENCE {
responseType OBJECT IDENTIFIER,
response OCTET STRING
}
BasicOCSPResponse ::= SEQUENCE {
tbsResponseData ResponseData,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING,
certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
}
ResponseData ::= SEQUENCE {
responderID ResponderID,
producedAt GeneralizedTime,
responses SEQUENCE OF SingleResponse
}
SingleResponse ::= SEQUENCE {
certID CertID,
certStatus CertStatus,
thisUpdate GeneralizedTime,
nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL
}
CertStatus ::= CHOICE {
good [0] IMPLICIT NULL,
revoked [1] IMPLICIT RevokedInfo,
unknown [2] IMPLICIT UnknownInfo
}
OCSP Response Codes:
good: Certificate is valid and not revokedrevoked: Certificate is revoked (includes revocation time and reason)unknown: Certificate serial number not found in CA database
OCSP Performance:
- Target Latency: <50ms (p99)
- Caching: OCSP responses cached for 1 hour (configurable via
nextUpdatefield) - Availability: 99.9% SLA (backed by Google Cloud Load Balancer with regional failover)
OCSP Responder Implementation:
- Service: Go microservice (high performance, low memory footprint)
- Database: PostgreSQL read replica (low latency, eventually consistent)
- Signing: OCSP responses signed with intermediate CA key (cached signature for non-revoked certificates)
5. Multi-Tenant Isolation
5.1 Cryptographic Tenant Boundaries
Principle: Each tenant organization operates within a cryptographically isolated trust domain.
Isolation Mechanisms:
-
Dedicated Intermediate CA per Tenant:
- Each organization receives a unique intermediate CA certificate and private key
- Organization A's certificates chain to
OrganizationA BIO-QMS Intermediate CA - Organization B's certificates chain to
OrganizationB BIO-QMS Intermediate CA - No cross-validation: A's certificates cannot validate against B's intermediate CA
-
Namespace Segregation:
- Certificate subjects include organization name:
O={OrganizationName} - DNS names include tenant ID:
{service}.{orgId}.bio-qms.coditect.cloud - Certificate validation enforces organization matching (application-level policy)
- Certificate subjects include organization name:
-
Independent Revocation Infrastructure:
- Each tenant has dedicated CRL endpoints:
http://crl.bio-qms.coditect.cloud/{orgId}/ - OCSP responder partitioned by tenant:
http://ocsp.bio-qms.coditect.cloud/{orgId} - Revocation of Organization A's intermediate CA does not affect Organization B
- Each tenant has dedicated CRL endpoints:
-
HSM Key Isolation:
- Each intermediate CA key stored in HSM with unique key ID
- IAM policies restrict key access to CA service with tenant context
- Key usage logged per tenant for audit trails
5.2 Certificate Namespace Design
Subject Distinguished Name (DN) Structure:
CN={EntityName}, O={OrganizationName}, OU={OrgUnit}, C=US
Examples:
- User:
CN=Alice Johnson (alice@orgA.bio), O=OrganizationA, OU=BIO-QMS Users, C=US - Service:
CN=api.orgA.bio-qms.coditect.cloud, O=OrganizationA, OU=BIO-QMS Services, C=US - Agent:
CN=Agent 12345, O=OrganizationA, OU=BIO-QMS Agents, C=US
DNS Naming Convention:
- Tenant Services:
{service}.{orgId}.bio-qms.coditect.cloud- Example:
api.org-a.bio-qms.coditect.cloud
- Example:
- Platform Services:
{service}.bio-qms.coditect.cloud- Example:
ca-service.bio-qms.coditect.cloud
- Example:
Kubernetes Service DNS:
- Internal:
{service}.{namespace}.svc.cluster.local- Example:
api-server.org-a-production.svc.cluster.local
- Example:
5.3 Tenant Lifecycle Operations
5.3.1 Tenant Provisioning
Workflow:
-
Organization Onboarding:
- New customer signs SaaS contract
- Sales team creates organization record in CRM
- Platform admin creates organization in BIO-QMS (organization ID, name, contact info)
-
Intermediate CA Provisioning:
# Trigger CA provisioning
POST /admin/organizations/{orgId}/provision-ca
# CA Service workflow:
# 1. Generate ECDSA P-256 key pair in HSM (key ID: bio-qms-{orgId}-intermediate)
# 2. Build intermediate CA CSR:
# Subject: CN={OrgName} BIO-QMS Intermediate CA, O={OrgName}, OU=BIO-QMS, C=US
# 3. Submit CSR to Root CA offline signing process
# 4. Root CA admin reviews CSR, powers on Root CA HSM
# 5. Sign intermediate CSR with Root CA key
# 6. Import signed intermediate certificate into CA database
# 7. Configure CRL and OCSP endpoints for tenant
# 8. Publish intermediate certificate to tenant namespace -
Tenant Infrastructure Setup:
- Kubernetes namespace:
{orgId}-production - PostgreSQL schema:
tenant_{orgId} - GCS bucket:
bio-qms-{orgId}-documents - DNS zone:
{orgId}.bio-qms.coditect.cloud
- Kubernetes namespace:
-
Root of Trust Distribution:
- Intermediate CA certificate published to tenant configuration
- Root CA certificate included in platform trust store
- Tenant users download certificate chain during first login
5.3.2 Tenant Offboarding
Workflow:
-
Data Export (customer-initiated):
- Customer downloads all quality records (PDF/A format with embedded signatures)
- Signatures remain verifiable via exported certificate chain
-
Certificate Revocation:
- Revoke intermediate CA certificate in Root CA CRL
- Reason code:
cessationOfOperation(code 5) - Publish updated Root CA CRL
-
Key Destruction (Crypto-Shredding):
- Delete intermediate CA private key from HSM
- HSM logs key destruction event
- Key backup shares destroyed (or retained per data retention policy)
-
Certificate Archive:
- Export all issued end-entity certificates to long-term archive (GCS Coldline)
- Retention period: 7 years (per FDA 21 CFR Part 11 §11.10(c))
- Archive includes: certificate PEM, issuance date, revocation status (if revoked)
-
Revocation Infrastructure Decommissioning:
- Deactivate OCSP responder for tenant
- Archive final CRL snapshot
- Redirect CRL URL to archive location
-
Tenant Infrastructure Teardown:
- Kubernetes namespace deletion (after data export)
- PostgreSQL schema archival and deletion
- GCS bucket lifecycle policy (90-day soft delete, then permanent deletion)
6. Document Signing Integration
6.1 Cryptographic Signature Binding (FDA §11.70 Compliance)
Regulatory Requirement: FDA 21 CFR Part 11 §11.70 requires electronic signatures to be "linked to their respective electronic records to ensure that the signatures cannot be excised, copied, or otherwise transferred."
Implementation: Document signing uses PKI certificates to create cryptographic bindings between signatures and quality records.
6.2 Signature Creation Workflow
Step-by-Step Process:
6.3 Signature Payload Structure
Signed Data:
interface SignaturePayload {
documentId: string; // Unique document identifier (e.g., "SOP-001-v2")
documentVersion: number; // Document version number
documentHash: string; // SHA-256 hash of document content (hex-encoded)
signatureTimestamp: string; // ISO 8601 UTC timestamp
signatureMeaning: string; // "AUTHOR", "REVIEWER", "APPROVER", "ACKNOWLEDGED"
signerId: string; // User ID (matches certificate subject)
signerName: string; // User's full name
agentAuthorization?: { // Only present for agent-delegated signatures
delegatedBy: string;
authorizationId: string;
workOrderId: string;
};
}
Example:
{
"documentId": "SOP-001-v2",
"documentVersion": 2,
"documentHash": "a3c5d9f8e7b2c4a1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7",
"signatureTimestamp": "2026-02-16T10:30:45Z",
"signatureMeaning": "APPROVER",
"signerId": "alice@orgA.bio",
"signerName": "Alice Johnson"
}
Canonical Serialization: JSON payload converted to canonical form (sorted keys, no whitespace) before signing to ensure deterministic hash.
Signature Algorithm: ECDSA with SHA-256 (aligns with certificate key algorithm).
6.4 Signature Storage
Database Schema:
CREATE TABLE signatures (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id TEXT NOT NULL REFERENCES organizations(id),
document_id TEXT NOT NULL,
document_version INTEGER NOT NULL,
document_hash TEXT NOT NULL, -- SHA-256 of document content
signer_id TEXT NOT NULL REFERENCES users(id),
signer_name TEXT NOT NULL,
signature_meaning TEXT NOT NULL CHECK (signature_meaning IN ('AUTHOR', 'REVIEWER', 'APPROVER', 'ACKNOWLEDGED')),
signature_value TEXT NOT NULL, -- Base64-encoded ECDSA signature
certificate_pem TEXT NOT NULL, -- Signer's certificate (full chain)
signature_timestamp TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
-- Agent delegation (nullable)
agent_authorization_id TEXT,
agent_delegated_by TEXT,
agent_work_order_id TEXT,
-- Revocation status (checked at audit time)
revocation_checked_at TIMESTAMPTZ,
was_revoked_at_audit BOOLEAN,
-- Long-term validation data
ocsp_response BYTEA, -- DER-encoded OCSP response at signing time
crl_snapshot BYTEA, -- DER-encoded CRL at signing time
UNIQUE (document_id, document_version, signer_id, signature_meaning),
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE RESTRICT
);
CREATE INDEX idx_signatures_document ON signatures(document_id, document_version);
CREATE INDEX idx_signatures_signer ON signatures(signer_id);
CREATE INDEX idx_signatures_org ON signatures(organization_id);
CREATE INDEX idx_signatures_timestamp ON signatures(signature_timestamp);
6.5 Long-Term Signature Validation (LTV)
Problem: Electronic signatures must remain verifiable decades after creation, even if:
- Signer's certificate expires
- Intermediate CA certificate expires
- OCSP responder or CRL endpoint is decommissioned
Solution: Embed revocation status at signing time.
LTV Workflow:
-
At Signature Time:
- Query OCSP responder for signer's certificate status
- Download current CRL for signer's certificate type
- Store OCSP response (DER-encoded) in
signatures.ocsp_response - Store CRL snapshot (DER-encoded) in
signatures.crl_snapshot
-
At Audit Time (years later):
- Retrieve signature record from database
- Verify signature against payload using certificate public key
- Check embedded OCSP response: was certificate valid at signing time?
- Check embedded CRL snapshot: was certificate not revoked at signing time?
- Verify certificate chain (user → intermediate → root)
- Result: signature validity proven even if certificate expired or CA decommissioned
LTV Standards Compliance:
- ETSI TS 102 778 (PAdES - PDF Advanced Electronic Signatures)
- RFC 5126 (CMS Advanced Electronic Signatures - CAdES)
- ISO 32000-2 (PDF 2.0 long-term validation)
6.6 PDF/A Signature Embedding
Use Case: Regulatory submissions to FDA, customer exports, audit trail archives.
Format: PDF/A-3 with embedded electronic signatures.
Signature Structure:
PDF Document
├── Document Content (pages, text, images)
├── Signature Dictionary
│ ├── /Type /Sig
│ ├── /Filter /Adobe.PPKLite
│ ├── /SubFilter /ETSI.CAdES.detached
│ ├── /ByteRange [0 12345 67890 54321] -- signed byte ranges
│ ├── /Contents <hex-encoded CMS signature>
│ ├── /Cert [<signer cert> <intermediate cert> <root cert>]
│ ├── /M (D:20260216103045Z) -- signature timestamp
│ └── /Name (Alice Johnson)
└── DSS (Document Security Store)
├── /Certs [<all certificates in chain>]
├── /OCSPs [<OCSP response at signing time>]
└── /CRLs [<CRL at signing time>]
PDF Signature Workflow:
- Generate PDF document from quality record (SOP, deviation, CAPA, work order)
- User signs document via web UI (triggers signature creation workflow above)
- Backend calls PDF library (e.g., PDFKit, pdf-lib, or commercial Adobe PDF Library)
- Embed CMS signature (PKCS#7 detached signature) in PDF signature dictionary
- Embed certificate chain in
/Certarray - Embed OCSP response and CRL in DSS (Document Security Store) for LTV
- Save signed PDF to document storage (GCS)
- PDF signature remains verifiable offline (Adobe Acrobat, Foxit Reader can verify)
Benefits:
- Offline Verification: No need for online OCSP/CRL queries to verify signature
- Regulatory Compliance: FDA accepts PDF/A with embedded signatures for eCTD submissions
- Long-Term Archival: PDF/A-3 is ISO-standardized archival format (ISO 19005-3)
6.7 Signature Verification API
Endpoint: GET /documents/{docId}/signatures/verify
Response:
interface SignatureVerificationResult {
documentId: string;
documentVersion: number;
signatures: Array<{
signerId: string;
signerName: string;
signatureMeaning: string;
signatureTimestamp: string;
// Verification results
signatureValid: boolean; // Signature matches payload + certificate public key
certificateValid: boolean; // Certificate chain verified against root CA
certificateNotRevoked: boolean; // Certificate was not revoked at signing time (via LTV)
certificateNotExpired: boolean; // Certificate was valid at signing time
// Certificate details
certificateSerial: string;
certificateIssuer: string;
certificateNotBefore: string;
certificateNotAfter: string;
// Overall result
trusted: boolean; // All checks passed
errors: string[]; // Error messages if not trusted
}>;
}
Verification Logic:
async function verifySignature(signature: SignatureRecord): Promise<VerificationResult> {
const errors: string[] = [];
// 1. Parse certificate from PEM
const cert = parseCertificate(signature.certificate_pem);
// 2. Verify certificate chain
const chainValid = verifyCertificateChain(cert, intermediateCaCert, rootCaCert);
if (!chainValid) {
errors.push('Certificate chain verification failed');
}
// 3. Check certificate was valid at signing time
const signingTime = new Date(signature.signature_timestamp);
const certValid = signingTime >= cert.notBefore && signingTime <= cert.notAfter;
if (!certValid) {
errors.push('Certificate was expired at signing time');
}
// 4. Check certificate revocation status at signing time (via embedded OCSP/CRL)
const ocspResponse = parseOCSPResponse(signature.ocsp_response);
const certRevoked = ocspResponse.certStatus === 'revoked';
if (certRevoked) {
errors.push('Certificate was revoked at signing time');
}
// 5. Verify signature
const payload = canonicalizePayload({
documentId: signature.document_id,
documentVersion: signature.document_version,
documentHash: signature.document_hash,
signatureTimestamp: signature.signature_timestamp,
signatureMeaning: signature.signature_meaning,
signerId: signature.signer_id,
signerName: signature.signer_name
});
const signatureValid = verifyECDSASignature(
payload,
signature.signature_value,
cert.publicKey
);
if (!signatureValid) {
errors.push('Signature verification failed (signature does not match payload)');
}
return {
signatureValid,
certificateValid: chainValid && certValid,
certificateNotRevoked: !certRevoked,
trusted: errors.length === 0,
errors
};
}
7. Implementation Architecture
7.1 CA Service Microservice
Technology Stack:
- Language: Go 1.21+ (high performance, excellent crypto libraries)
- Framework: Gin (HTTP router), gRPC (internal service-to-service)
- Database: PostgreSQL 15 (certificate metadata, audit logs)
- HSM Integration: Google Cloud KMS (FIPS 140-2 Level 3)
- Cryptography: Go standard library
crypto/ecdsa,crypto/x509,crypto/rand
Service Architecture:
┌─────────────────────────────────────────────────────────────┐
│ CA Service │
├─────────────────────────────────────────────────────────────┤
│ HTTP API (REST) │
│ ├─ POST /ca/certificates/issue │
│ ├─ GET /ca/certificates/{serial} │
│ ├─ POST /ca/certificates/{serial}/revoke │
│ ├─ GET /ca/crl │
│ └─ GET /ca/ocsp (OCSP responder) │
├─────────────────────────────────────────────────────────────┤
│ Business Logic │
│ ├─ Certificate Issuance Service │
│ ├─ Certificate Validation Service │
│ ├─ Revocation Management Service │
│ ├─ CRL Publisher (hourly cron + event-triggered) │
│ └─ OCSP Responder │
├─────────────────────────────────────────────────────────────┤
│ HSM Abstraction Layer │
│ ├─ Google Cloud KMS Client │
│ ├─ Key Selection (map orgId → HSM key ID) │
│ └─ Signature Caching (non-revoked OCSP responses) │
├─────────────────────────────────────────────────────────────┤
│ Data Access Layer │
│ ├─ PostgreSQL (certificates, revocations, audit logs) │
│ ├─ Redis (OCSP response cache, rate limiting) │
│ └─ GCS (CRL publication, certificate archives) │
└─────────────────────────────────────────────────────────────┘
7.2 API Design
7.2.1 TypeScript Interfaces
// ============================================================================
// Certificate Request Types
// ============================================================================
export enum CertificateType {
USER_SIGNING = 'USER_SIGNING',
SERVICE_IDENTITY = 'SERVICE_IDENTITY',
AGENT_EPHEMERAL = 'AGENT_EPHEMERAL',
CODE_SIGNING = 'CODE_SIGNING'
}
export enum KeyUsage {
DIGITAL_SIGNATURE = 'digitalSignature',
NON_REPUDIATION = 'nonRepudiation',
KEY_ENCIPHERMENT = 'keyEncipherment',
CERTIFICATE_SIGNING = 'keyCertSign',
CRL_SIGNING = 'cRLSign'
}
export enum ExtendedKeyUsage {
SERVER_AUTH = '1.3.6.1.5.5.7.3.1',
CLIENT_AUTH = '1.3.6.1.5.5.7.3.2',
CODE_SIGNING = '1.3.6.1.5.5.7.3.3',
EMAIL_PROTECTION = '1.3.6.1.5.5.7.3.4',
AGENT_DELEGATION = '1.3.6.1.4.1.59999.1.1.1' // Custom OID
}
export interface CertificateSubject {
commonName: string;
organization: string;
organizationalUnit: string;
country: string;
email?: string;
}
export interface SubjectAlternativeName {
email?: string;
dns?: string[];
uri?: string;
}
export interface AgentAuthorizationInfo {
delegatedBy: string; // User ID
authorizationId: string; // Unique authorization record ID
workOrderScope: string; // Work order ID or "NONE"
authorizedAt: string; // ISO 8601 timestamp
expiresAt: string; // ISO 8601 timestamp
}
export interface CertificateRequest {
organizationId: string;
certificateType: CertificateType;
subject: CertificateSubject;
subjectAltName?: SubjectAlternativeName;
publicKey: string; // PEM-encoded or JWK
validityDays: number;
keyUsage: KeyUsage[];
extendedKeyUsage?: ExtendedKeyUsage[];
agentAuthorization?: AgentAuthorizationInfo; // Only for AGENT_EPHEMERAL
}
// ============================================================================
// Certificate Response Types
// ============================================================================
export interface IssuedCertificate {
serialNumber: string; // Hex-encoded
subject: string; // DN format
issuer: string; // DN format
notBefore: Date;
notAfter: Date;
certificate: string; // PEM-encoded
certificateChain: string[]; // Array of PEM-encoded certs [intermediate, root]
thumbprint: string; // SHA-256 hash of DER-encoded certificate
}
// ============================================================================
// Revocation Types
// ============================================================================
export enum RevocationReason {
UNSPECIFIED = 0,
KEY_COMPROMISE = 1,
CA_COMPROMISE = 2,
AFFILIATION_CHANGED = 3,
SUPERSEDED = 4,
CESSATION_OF_OPERATION = 5,
CERTIFICATE_HOLD = 6,
PRIVILEGE_WITHDRAWN = 9
}
export interface RevocationRequest {
serialNumber: string;
reason: RevocationReason;
reasonText?: string; // Human-readable explanation
revokedBy: string; // Admin user ID
}
export interface RevocationInfo {
serialNumber: string;
revokedAt: Date;
reason: RevocationReason;
reasonText?: string;
}
// ============================================================================
// Certificate Validation Types
// ============================================================================
export enum CertificateStatus {
VALID = 'VALID',
EXPIRED = 'EXPIRED',
REVOKED = 'REVOKED',
SUSPENDED = 'SUSPENDED',
UNKNOWN = 'UNKNOWN'
}
export interface CertificateValidationResult {
serialNumber: string;
status: CertificateStatus;
revocationInfo?: RevocationInfo;
expiresAt: Date;
checkedAt: Date;
}
// ============================================================================
// OCSP Types
// ============================================================================
export enum OCSPCertStatus {
GOOD = 'good',
REVOKED = 'revoked',
UNKNOWN = 'unknown'
}
export interface OCSPRequest {
serialNumber: string;
issuerNameHash: string; // SHA-1 hash of issuer DN
issuerKeyHash: string; // SHA-1 hash of issuer public key
}
export interface OCSPResponse {
serialNumber: string;
certStatus: OCSPCertStatus;
revocationTime?: Date;
revocationReason?: RevocationReason;
thisUpdate: Date;
nextUpdate: Date;
signature: string; // Base64-encoded
}
// ============================================================================
// CRL Types
// ============================================================================
export interface CRLInfo {
issuer: string; // DN of intermediate CA
thisUpdate: Date;
nextUpdate: Date;
revokedCertificates: Array<{
serialNumber: string;
revocationDate: Date;
reason: RevocationReason;
}>;
signature: string; // Base64-encoded CRL signature
downloadUrl: string; // HTTP URL to download CRL
}
7.2.2 REST API Endpoints
Base URL: https://ca-service.bio-qms.coditect.cloud
POST /ca/certificates/issue
Issue a new certificate.
Request:
{
"organizationId": "org-a",
"certificateType": "USER_SIGNING",
"subject": {
"commonName": "Alice Johnson (alice@orgA.bio)",
"organization": "OrganizationA",
"organizationalUnit": "BIO-QMS Users",
"country": "US"
},
"subjectAltName": {
"email": "alice@orgA.bio"
},
"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkw...",
"validityDays": 365,
"keyUsage": ["digitalSignature", "nonRepudiation"],
"extendedKeyUsage": ["1.3.6.1.5.5.7.3.4"]
}
Response (201 Created):
{
"serialNumber": "0x1A2B3C4D5E6F708192A3B4C5D6E7F8091A2B3C4D",
"subject": "CN=Alice Johnson (alice@orgA.bio), O=OrganizationA, OU=BIO-QMS Users, C=US",
"issuer": "CN=OrganizationA BIO-QMS Intermediate CA, O=OrganizationA, OU=BIO-QMS, C=US",
"notBefore": "2026-02-16T10:00:00Z",
"notAfter": "2027-02-16T10:00:00Z",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...",
"certificateChain": [
"-----BEGIN CERTIFICATE-----\nMIIC... (intermediate CA)",
"-----BEGIN CERTIFICATE-----\nMIIC... (root CA)"
],
"thumbprint": "a3c5d9f8e7b2c4a1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7"
}
Error Responses:
400 Bad Request: Invalid request (malformed public key, invalid organization ID)403 Forbidden: Requester not authorized to issue certificates for organization409 Conflict: User already has an active signing certificate500 Internal Server Error: HSM signing failure
GET /ca/certificates/{serialNumber}
Retrieve certificate by serial number.
Response (200 OK):
{
"serialNumber": "0x1A2B3C4D5E6F708192A3B4C5D6E7F8091A2B3C4D",
"subject": "CN=Alice Johnson (alice@orgA.bio), O=OrganizationA, OU=BIO-QMS Users, C=US",
"issuer": "CN=OrganizationA BIO-QMS Intermediate CA, O=OrganizationA, OU=BIO-QMS, C=US",
"notBefore": "2026-02-16T10:00:00Z",
"notAfter": "2027-02-16T10:00:00Z",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...",
"status": "VALID",
"thumbprint": "a3c5d9f8e7b2c4a1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a9b8c7"
}
Error Responses:
404 Not Found: Certificate not found
POST /ca/certificates/{serialNumber}/revoke
Revoke a certificate.
Request:
{
"reason": 1,
"reasonText": "User reported private key compromise",
"revokedBy": "admin@coditect.ai"
}
Response (200 OK):
{
"serialNumber": "0x1A2B3C4D5E6F708192A3B4C5D6E7F8091A2B3C4D",
"revokedAt": "2026-02-16T11:30:00Z",
"reason": 1,
"reasonText": "User reported private key compromise"
}
Error Responses:
403 Forbidden: Requester not authorized to revoke certificates404 Not Found: Certificate not found409 Conflict: Certificate already revoked
GET /ca/crl
Download Certificate Revocation List.
Query Parameters:
orgId(required): Organization IDcertType(required):user-certs|service-certs|agent-certs
Response (200 OK):
- Content-Type:
application/pkix-crl - Body: DER-encoded CRL
Example:
curl -O https://ca-service.bio-qms.coditect.cloud/ca/crl?orgId=org-a&certType=user-certs
POST /ca/ocsp
OCSP responder (per RFC 6960).
Request:
- Content-Type:
application/ocsp-request - Body: DER-encoded OCSP request
Response (200 OK):
- Content-Type:
application/ocsp-response - Body: DER-encoded OCSP response
Example (using OpenSSL):
openssl ocsp \
-issuer intermediate-ca.pem \
-cert user-cert.pem \
-url https://ca-service.bio-qms.coditect.cloud/ca/ocsp \
-resp_text
7.3 Database Schema
-- ============================================================================
-- Intermediate CAs
-- ============================================================================
CREATE TABLE intermediate_cas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id TEXT NOT NULL UNIQUE REFERENCES organizations(id),
subject_dn TEXT NOT NULL,
serial_number TEXT NOT NULL UNIQUE,
certificate_pem TEXT NOT NULL,
not_before TIMESTAMPTZ NOT NULL,
not_after TIMESTAMPTZ NOT NULL,
hsm_key_id TEXT NOT NULL, -- Google Cloud KMS key ID
status TEXT NOT NULL CHECK (status IN ('ACTIVE', 'EXPIRED', 'REVOKED')),
revoked_at TIMESTAMPTZ,
revocation_reason INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_intermediate_cas_org ON intermediate_cas(organization_id);
CREATE INDEX idx_intermediate_cas_serial ON intermediate_cas(serial_number);
CREATE INDEX idx_intermediate_cas_status ON intermediate_cas(status);
-- ============================================================================
-- End-Entity Certificates
-- ============================================================================
CREATE TABLE certificates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id TEXT NOT NULL REFERENCES organizations(id),
intermediate_ca_id UUID NOT NULL REFERENCES intermediate_cas(id),
serial_number TEXT NOT NULL UNIQUE,
certificate_type TEXT NOT NULL CHECK (certificate_type IN ('USER_SIGNING', 'SERVICE_IDENTITY', 'AGENT_EPHEMERAL', 'CODE_SIGNING')),
subject_dn TEXT NOT NULL,
subject_cn TEXT NOT NULL,
subject_email TEXT,
certificate_pem TEXT NOT NULL,
public_key_pem TEXT NOT NULL,
thumbprint TEXT NOT NULL, -- SHA-256 of DER-encoded cert
not_before TIMESTAMPTZ NOT NULL,
not_after TIMESTAMPTZ NOT NULL,
status TEXT NOT NULL CHECK (status IN ('ACTIVE', 'EXPIRED', 'REVOKED', 'SUSPENDED')),
revoked_at TIMESTAMPTZ,
revocation_reason INTEGER,
revocation_reason_text TEXT,
revoked_by TEXT, -- Admin user ID
-- Agent-specific fields
agent_authorization_id TEXT,
agent_delegated_by TEXT,
agent_work_order_id TEXT,
-- Metadata
issued_by TEXT NOT NULL, -- System or admin user ID
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE RESTRICT
);
CREATE INDEX idx_certificates_org ON certificates(organization_id);
CREATE INDEX idx_certificates_serial ON certificates(serial_number);
CREATE INDEX idx_certificates_type ON certificates(certificate_type);
CREATE INDEX idx_certificates_status ON certificates(status);
CREATE INDEX idx_certificates_subject_cn ON certificates(subject_cn);
CREATE INDEX idx_certificates_subject_email ON certificates(subject_email);
CREATE INDEX idx_certificates_expiry ON certificates(not_after);
-- ============================================================================
-- Certificate Audit Log
-- ============================================================================
CREATE TABLE certificate_audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id TEXT NOT NULL,
certificate_id UUID REFERENCES certificates(id),
serial_number TEXT NOT NULL,
event_type TEXT NOT NULL CHECK (event_type IN ('ISSUED', 'RENEWED', 'REVOKED', 'SUSPENDED', 'RESUMED', 'EXPIRED')),
event_timestamp TIMESTAMPTZ NOT NULL DEFAULT now(),
actor TEXT NOT NULL, -- User ID or "SYSTEM"
details JSONB,
ip_address INET,
user_agent TEXT
);
CREATE INDEX idx_cert_audit_org ON certificate_audit_log(organization_id);
CREATE INDEX idx_cert_audit_cert ON certificate_audit_log(certificate_id);
CREATE INDEX idx_cert_audit_serial ON certificate_audit_log(serial_number);
CREATE INDEX idx_cert_audit_timestamp ON certificate_audit_log(event_timestamp DESC);
CREATE INDEX idx_cert_audit_type ON certificate_audit_log(event_type);
-- ============================================================================
-- CRL Snapshots (for audit trail)
-- ============================================================================
CREATE TABLE crl_snapshots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id TEXT NOT NULL,
intermediate_ca_id UUID NOT NULL REFERENCES intermediate_cas(id),
certificate_type TEXT NOT NULL,
this_update TIMESTAMPTZ NOT NULL,
next_update TIMESTAMPTZ NOT NULL,
crl_der BYTEA NOT NULL, -- DER-encoded CRL
crl_url TEXT NOT NULL,
revoked_count INTEGER NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_crl_snapshots_org ON crl_snapshots(organization_id);
CREATE INDEX idx_crl_snapshots_ca ON crl_snapshots(intermediate_ca_id);
CREATE INDEX idx_crl_snapshots_this_update ON crl_snapshots(this_update DESC);
7.4 HSM Integration
Google Cloud KMS Configuration:
# Terraform configuration for Cloud KMS key ring and keys
resource "google_kms_key_ring" "bio_qms_ca" {
name = "bio-qms-ca-keys"
location = "us-central1"
}
# Root CA key (offline, used only for intermediate signing)
resource "google_kms_crypto_key" "root_ca" {
name = "root-ca-key"
key_ring = google_kms_key_ring.bio_qms_ca.id
purpose = "ASYMMETRIC_SIGN"
version_template {
algorithm = "EC_SIGN_P256_SHA256"
protection_level = "HSM"
}
lifecycle {
prevent_destroy = true
}
}
# Per-tenant intermediate CA keys
resource "google_kms_crypto_key" "intermediate_ca" {
for_each = var.organizations
name = "intermediate-ca-${each.key}"
key_ring = google_kms_key_ring.bio_qms_ca.id
purpose = "ASYMMETRIC_SIGN"
version_template {
algorithm = "EC_SIGN_P256_SHA256"
protection_level = "HSM"
}
rotation_period = "157680000s" # 5 years
}
# IAM policy: CA service can sign with intermediate CA keys
resource "google_kms_crypto_key_iam_member" "ca_service_signer" {
for_each = var.organizations
crypto_key_id = google_kms_crypto_key.intermediate_ca[each.key].id
role = "roles/cloudkms.signerVerifier"
member = "serviceAccount:ca-service@${var.project_id}.iam.gserviceaccount.com"
}
Signing Operation (Go code):
import (
kms "cloud.google.com/go/kms/apiv1"
kmspb "cloud.google.com/go/kms/apiv1/kmspb"
"crypto/sha256"
"encoding/asn1"
)
func signCertificateWithHSM(ctx context.Context, tbsCertificate []byte, hsmKeyName string) ([]byte, error) {
client, err := kms.NewKeyManagementClient(ctx)
if err != nil {
return nil, err
}
defer client.Close()
// Hash TBS certificate (HSM signs the hash, not raw data)
hash := sha256.Sum256(tbsCertificate)
req := &kmspb.AsymmetricSignRequest{
Name: hsmKeyName, // projects/{project}/locations/{loc}/keyRings/{ring}/cryptoKeys/{key}/cryptoKeyVersions/1
Digest: &kmspb.Digest{
Digest: &kmspb.Digest_Sha256{
Sha256: hash[:],
},
},
}
resp, err := client.AsymmetricSign(ctx, req)
if err != nil {
return nil, err
}
// Parse ECDSA signature (DER-encoded ASN.1)
var ecdsaSig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(resp.Signature, &ecdsaSig)
if err != nil {
return nil, err
}
return resp.Signature, nil
}
8. Certificate Storage and Distribution
8.1 Storage Locations
| Artifact | Storage | Encryption | Access Control |
|---|---|---|---|
| Root CA private key | Cloud HSM | HSM-native encryption | IAM: CA Admin only (offline operations) |
| Intermediate CA private keys | Cloud HSM | HSM-native encryption | IAM: CA Service service account |
| User private keys | Browser IndexedDB / Yubikey | WebCrypto non-extractable / hardware token | User only |
| User certificates | PostgreSQL | Application-level encryption (AES-256-GCM) | Row-level security (RLS) per tenant |
| Service certificates | Kubernetes Secrets | Google KMS encryption at rest | Namespace RBAC |
| Root CA certificate | GCS public bucket | None (public artifact) | Public read |
| Intermediate CA certificates | GCS public bucket | None (public artifact) | Public read |
| CRLs | GCS public bucket + CDN | None (signed, integrity verified) | Public read |
| OCSP responses | In-memory cache (Redis) | None (signed, integrity verified) | Public endpoint |
8.2 Trust Store Distribution
Platform Trust Store:
- Location: ConfigMap in each Kubernetes namespace
- Contents: Root CA certificate + all active intermediate CA certificates
- Update Mechanism: ConfigMap updated on intermediate CA issuance/renewal/revocation
- Application Integration: Mounted as volume at
/etc/ssl/certs/bio-qms-ca-bundle.crt
Example ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: bio-qms-ca-bundle
namespace: org-a-production
data:
ca-bundle.crt: |
# CODITECT BIO-QMS Root CA
-----BEGIN CERTIFICATE-----
MIICxzCCAa+gAwIBAgIUQZ...
-----END CERTIFICATE-----
# OrganizationA BIO-QMS Intermediate CA
-----BEGIN CERTIFICATE-----
MIIDGzCCAgOgAwIBAgIUAb...
-----END CERTIFICATE-----
Browser Trust Store:
- User downloads root + intermediate certificates during first login
- Certificates stored in browser IndexedDB (alongside user's signing certificate)
- Application bundles certificates in signature operations (full chain sent to verifiers)
8.3 CRL and OCSP Distribution
CRL Publication:
Google Cloud Storage Bucket: bio-qms-crl-public
├── org-a/
│ ├── user-certs.crl (updated hourly)
│ ├── service-certs.crl (updated hourly)
│ └── agent-certs.crl (updated hourly)
├── org-b/
│ ├── user-certs.crl
│ ├── service-certs.crl
│ └── agent-certs.crl
└── root/
└── intermediate-cas.crl (root CA CRL, updated on intermediate CA revocation)
CDN: Cloud CDN (Google Cloud)
- Cache TTL: 1 hour
- Origin: GCS bucket
- Public endpoint: https://crl.bio-qms.coditect.cloud/{orgId}/{certType}.crl
OCSP Responder:
- Service: Go microservice (separate from CA service for isolation)
- Database: PostgreSQL read replica (low latency, eventually consistent)
- Cache: Redis (1-hour TTL for "good" status responses)
- Endpoint:
https://ocsp.bio-qms.coditect.cloud/{orgId} - Load Balancer: Google Cloud Load Balancer with autoscaling (target: 100ms p99 latency)
9. Monitoring and Compliance
9.1 Certificate Expiry Monitoring
Alert Schedule:
| Days Until Expiry | Alert Level | Notification Channels |
|---|---|---|
| 30 | Info | Email to user |
| 14 | Warning | Email + in-app banner |
| 7 | Warning | Email + in-app modal |
| 1 | Critical | Email + in-app blocking modal + Slack alert to CA admins |
| 0 | Critical | Certificate expired, signature operations blocked |
Monitoring Query (PostgreSQL):
-- Certificates expiring in next 30 days
SELECT
organization_id,
certificate_type,
subject_cn,
serial_number,
not_after,
EXTRACT(DAY FROM (not_after - now())) AS days_until_expiry
FROM certificates
WHERE status = 'ACTIVE'
AND not_after <= now() + INTERVAL '30 days'
ORDER BY not_after ASC;
Prometheus Metrics:
# Certificates expiring soon (by days until expiry)
bio_qms_certificates_expiring_soon{org_id="org-a", cert_type="USER_SIGNING", days="30"} 5
bio_qms_certificates_expiring_soon{org_id="org-a", cert_type="USER_SIGNING", days="14"} 2
bio_qms_certificates_expiring_soon{org_id="org-a", cert_type="USER_SIGNING", days="7"} 1
# Total active certificates
bio_qms_certificates_total{org_id="org-a", cert_type="USER_SIGNING", status="ACTIVE"} 42
# Total revoked certificates
bio_qms_certificates_total{org_id="org-a", cert_type="USER_SIGNING", status="REVOKED"} 3
9.2 Audit Logging
Certificate Lifecycle Events:
| Event Type | Logged Data | Retention |
|---|---|---|
| CERTIFICATE_ISSUED | Serial, subject, issuer, issued_by, timestamp | 7 years |
| CERTIFICATE_RENEWED | Old serial, new serial, renewal_type (rekey/same-key), renewed_by | 7 years |
| CERTIFICATE_REVOKED | Serial, revocation_reason, revoked_by, timestamp | 7 years |
| CERTIFICATE_SUSPENDED | Serial, suspended_by, reason, timestamp | 7 years |
| CERTIFICATE_RESUMED | Serial, resumed_by, reason, timestamp | 7 years |
| CERTIFICATE_EXPIRED | Serial, expiry_date | 7 years |
| CRL_PUBLISHED | CRL URL, revoked_count, published_at | 7 years |
| OCSP_QUERY | Serial, cert_status, queried_at, client_ip | 90 days |
| HSM_KEY_USAGE | Key ID, operation (sign/verify), timestamp, actor | 7 years |
Audit Log Query API:
GET /admin/audit-log/certificates
?organizationId=org-a
&startDate=2026-01-01
&endDate=2026-02-16
&eventType=CERTIFICATE_ISSUED,CERTIFICATE_REVOKED
&limit=100
&offset=0
Response:
{
"events": [
{
"id": "evt_1A2B3C",
"timestamp": "2026-02-16T10:00:00Z",
"eventType": "CERTIFICATE_ISSUED",
"organizationId": "org-a",
"certificateSerial": "0x1A2B3C4D5E6F",
"actor": "system",
"details": {
"subject": "CN=Alice Johnson",
"certificateType": "USER_SIGNING",
"validityDays": 365
},
"ipAddress": "10.0.1.45",
"userAgent": "Mozilla/5.0..."
}
],
"total": 123,
"limit": 100,
"offset": 0
}
9.3 Compliance Reporting
Monthly Compliance Report (automated generation):
# BIO-QMS Certificate Authority - Monthly Compliance Report
**Organization**: OrganizationA
**Reporting Period**: February 2026
## Certificate Inventory
| Certificate Type | Active | Expired | Revoked | Total |
|------------------|--------|---------|---------|-------|
| User Signing | 42 | 5 | 3 | 50 |
| Service Identity | 18 | 0 | 0 | 18 |
| Agent Ephemeral | 0 | 1250 | 0 | 1250 |
| **Total** | **60** | **1255**| **3** | **1318** |
## Certificate Lifecycle Events
- **Issued**: 8 user signing certificates
- **Renewed**: 3 user signing certificates (all with rekey)
- **Revoked**: 1 user signing certificate (reason: affiliation changed - user left organization)
- **Expired**: 5 user signing certificates (all renewed before expiry)
## Revocation Activity
- **Total Revocations**: 1
- **Revocation Reasons**:
- Affiliation Changed: 1
## CRL Publication
- **Total CRLs Published**: 720 (30 days × 24 hours)
- **Average Revoked Certificates per CRL**: 3
- **CRL Publication Failures**: 0
## OCSP Activity
- **Total OCSP Queries**: 45,231
- **Good Responses**: 45,198 (99.93%)
- **Revoked Responses**: 33 (0.07%)
- **Unknown Responses**: 0
- **Average Response Time**: 38ms (p99: 72ms)
## Certificate Expiry Forecast
| Days Until Expiry | Count |
|-------------------|-------|
| 0-7 days | 1 |
| 8-14 days | 2 |
| 15-30 days | 5 |
| 31-60 days | 8 |
| 61-90 days | 12 |
## Compliance Status
- ✅ All active certificates verified against root CA
- ✅ All revoked certificates included in CRLs
- ✅ OCSP responder operational (99.99% uptime)
- ✅ No certificate compromise incidents reported
- ✅ All certificate issuance events logged and retained
- ✅ HSM key usage within normal parameters
## Recommendations
- 1 certificate expiring in next 7 days: contact user for renewal
- Consider increasing certificate validity period for service certificates (currently 1 year, recommend 2 years)
10. Disaster Recovery
10.1 Root CA Key Backup
Backup Strategy: M-of-N secret sharing (Shamir's Secret Sharing).
Configuration:
- M: 3 (minimum shares required to reconstruct key)
- N: 5 (total shares created)
- Share Holders: CISO, VP Engineering, Legal Counsel, CEO, External Auditor
Backup Procedure:
- During Root CA key ceremony, export key backup from HSM
- Split key into 5 shares using Shamir's Secret Sharing
- Seal each share in tamper-evident envelope
- Notarize envelopes with witness signatures
- Distribute shares to geographically separated secure storage:
- Share 1: CISO (safety deposit box, Bank A, San Francisco)
- Share 2: VP Engineering (safety deposit box, Bank B, New York)
- Share 3: Legal Counsel (law firm vault, Chicago)
- Share 4: CEO (safety deposit box, Bank C, Los Angeles)
- Share 5: External Auditor (audit firm vault, Washington DC)
Recovery Procedure:
- Convene 3+ share holders (requires in-person meeting or secure video conference)
- Open tamper-evident envelopes (document any tampering)
- Combine 3+ shares to reconstruct Root CA private key
- Import key into new HSM
- Verify key by signing test certificate and validating against existing intermediate CAs
- Document recovery event in audit log
Annual Test: Test recovery procedure with dummy key (not production Root CA key) to ensure process works.
10.2 Intermediate CA Key Backup
Backup Strategy: Google Cloud HSM cross-region replication + encrypted exports.
Configuration:
- Primary Region: us-central1 (Iowa)
- Backup Region: us-east1 (South Carolina)
- HSM Replication: Automatic (Google Cloud KMS multi-region keys)
Backup Procedure:
- Cloud KMS automatically replicates keys across regions (enabled by default for multi-region key rings)
- Monthly encrypted export to GCS Coldline storage (compliance retention):
# Export intermediate CA certificate (public key only)
gcloud kms keys versions get-public-key 1 \
--key bio-qms-org-a-intermediate \
--keyring bio-qms-ca-keys \
--location us-central1 \
--output-file org-a-intermediate-public.pem
# Upload to GCS archive
gsutil cp org-a-intermediate-public.pem gs://bio-qms-ca-backups/2026-02/org-a/
Recovery Procedure:
- If primary region unavailable: Cloud KMS automatically fails over to backup region (transparent to CA service)
- If HSM key destroyed: No recovery (issue new intermediate CA, revoke old intermediate in Root CA CRL)
- If Cloud KMS project deleted: Restore from Google Cloud Project recovery (contact Google Cloud support)
10.3 Certificate Database Backup
Backup Strategy: Continuous replication + daily snapshots.
Configuration:
- Primary Database: Cloud SQL PostgreSQL (us-central1)
- Read Replicas: 2 replicas (us-central1-a, us-central1-b)
- Cross-Region Replica: 1 replica (us-east1) for disaster recovery
- Automated Backups: Daily at 02:00 UTC (7-day retention)
- Point-in-Time Recovery: Enabled (7-day window)
Backup Procedure:
# Manual backup (in addition to automated daily backups)
gcloud sql backups create \
--instance bio-qms-postgres-prod \
--project coditect-bio-qms-prod
# Export to GCS (compliance archive)
gcloud sql export sql bio-qms-postgres-prod \
gs://bio-qms-db-backups/2026-02/certificates-$(date +%Y%m%d).sql \
--database=bio_qms \
--table=certificates,intermediate_cas,certificate_audit_log
Recovery Procedure:
- Read Replica Failure: Cloud SQL automatically promotes healthy replica (no data loss)
- Primary Instance Failure: Promote cross-region replica to primary (< 5 min RTO, 0 RPO)
- Database Corruption: Restore from point-in-time backup:
gcloud sql backups restore {backup-id} \
--instance bio-qms-postgres-prod \
--backup-instance bio-qms-postgres-prod
10.4 CA Compromise Scenarios
Scenario 1: User Certificate Private Key Compromise
Impact: Single user's signatures potentially forged.
Response:
- User reports private key compromise (via help desk ticket or security hotline)
- CA administrator immediately revokes user's certificate (reason: keyCompromise)
- CRL published immediately (within 5 minutes)
- OCSP cache cleared (revocation effective within 1 hour)
- Forensic investigation: review all signatures created by compromised certificate
- Audit trail: identify potentially forged signatures (compare signing timestamps with user activity logs)
- Issue new certificate to user (with new key pair)
Scenario 2: Intermediate CA Key Compromise
Impact: All certificates issued by compromised intermediate CA are untrusted.
Response:
- CA security team confirms compromise (HSM audit logs, anomalous signing activity)
- Immediate Actions (within 1 hour):
- Revoke compromised intermediate CA certificate in Root CA CRL
- Destroy compromised intermediate CA private key in HSM
- Publish Root CA CRL update
- Notify all users in affected organization (email, in-app alerts)
- Short-Term Mitigation (within 24 hours):
- Provision new intermediate CA for organization (new key pair)
- Power on Root CA HSM, sign new intermediate CSR
- Re-issue all user signing certificates under new intermediate CA
- Force user re-authentication and certificate download
- Long-Term Remediation (within 1 week):
- Forensic analysis: identify potentially forged certificates issued by compromised CA
- Review all electronic signatures created during compromise window
- Regulatory notification (FDA MedWatch if patient safety impacted)
- Incident post-mortem and security control improvements
Scenario 3: Root CA Key Compromise
Impact: Entire PKI trust hierarchy compromised. Catastrophic failure.
Response:
- Emergency Response (within 1 hour):
- Notify all customers (email, status page, direct calls)
- Revoke Root CA certificate (publish to public CT logs, browser vendors)
- Shut down CA service (prevent further certificate issuance)
- Root CA Replacement (within 1 week):
- Convene Root CA key ceremony for new Root CA
- Generate new Root CA key pair (new HSM)
- Create new Root CA self-signed certificate
- Provision new intermediate CAs for all organizations
- Re-issue all end-entity certificates
- Customer Transition (within 1 month):
- Customers download new Root CA and intermediate CA certificates
- Replace all existing certificates with new certificates
- Update trust stores in all applications
- Validate all electronic signatures under new PKI
- Regulatory Notification:
- FDA MedWatch report (if patient safety impacted)
- State data breach notifications (if PHI exposed)
- Customer SLA credits (per contract terms)
Likelihood: Extremely low (HSM with IAM controls, audit logging, multi-person access).
11. Compliance Mapping
11.1 FDA 21 CFR Part 11 Compliance
| Requirement | Implementation | Evidence |
|---|---|---|
| §11.50 Signature Manifestations | Signature includes user name, timestamp, and meaning (AUTHOR/REVIEWER/APPROVER) stored in signatures table | Database schema, API responses, PDF signature display |
| §11.70 Signature/Record Linking | Cryptographic binding via ECDSA signature over document hash + metadata; signature includes certificate chain | Signature payload structure, verification API, long-term validation |
| §11.100 Unique Signatures | Each user receives unique signing certificate; private key never shared | Certificate issuance workflow (one cert per user), user private key stored in browser (non-extractable) |
| §11.200 Electronic Signature Components | Two-factor authentication required for signature operations (password + MFA) | API authentication flow (MFA re-authentication before signing) |
| §11.300 Controls for Identification Codes/Passwords | Certificate-based authentication with HSM-backed PKI; passwords stored as bcrypt hashes | Certificate profiles, HSM integration, user authentication service |
11.2 HIPAA §164.312(e) Compliance
| Requirement | Implementation | Evidence |
|---|---|---|
| Transmission Security | TLS 1.3 for all HTTP traffic; service-to-service mTLS with certificate-based authentication | Service certificate profiles, Kubernetes network policies, load balancer TLS configuration |
| Integrity Controls | Electronic signatures provide integrity verification (document hash in signature payload) | Signature payload structure, verification API |
| Encryption | TLS encryption in transit; AES-256-GCM for certificates at rest in database | Database encryption configuration, TLS cipher suites |
11.3 SOC 2 CC6.1 (Logical Access Controls)
| Control | Implementation | Evidence |
|---|---|---|
| CC6.1.1 Unique User Identification | Each user has unique signing certificate with email-bound identity | Certificate subject format (includes user email), one cert per user policy |
| CC6.1.2 Authentication | Certificate-based authentication (possession of private key) + password + MFA | Certificate profiles (public/private key cryptography), API authentication flow |
| CC6.1.3 Authorization | Role-based access control (CA Admin, Certificate Manager, User) enforced via certificate types and IAM policies | Certificate types (user vs admin certificates), API RBAC enforcement |
| CC6.1.4 Audit Logging | All certificate lifecycle events logged with timestamp, actor, IP address | certificate_audit_log table, audit log retention (7 years) |
11.4 X.509 v3 Profile Compliance
Standards:
- RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile
- NIST SP 800-57: Recommendation for Key Management
- FIPS 186-4: Digital Signature Standard (ECDSA P-256)
Compliance Verification:
- All certificates include required extensions (Basic Constraints, Key Usage, Subject Key Identifier, Authority Key Identifier)
- CRL Distribution Points and Authority Information Access (OCSP) URLs included in all end-entity certificates
- ECDSA P-256 algorithm compliant with NIST FIPS 186-4
- Certificate validity periods align with industry best practices (1 year for end-entities, 5 years for intermediates, 20 years for root)
12. Appendices
A. Glossary
| Term | Definition |
|---|---|
| CA (Certificate Authority) | Trusted entity that issues digital certificates |
| CSR (Certificate Signing Request) | Request submitted to CA containing public key and subject identity |
| CRL (Certificate Revocation List) | List of revoked certificates published by CA |
| OCSP (Online Certificate Status Protocol) | Real-time protocol for checking certificate revocation status |
| HSM (Hardware Security Module) | Tamper-resistant hardware device for cryptographic key storage |
| mTLS (Mutual TLS) | TLS with both client and server authentication via certificates |
| LTV (Long-Term Validation) | Ability to verify signatures beyond certificate expiry via embedded revocation data |
| PAdES (PDF Advanced Electronic Signatures) | Standard for embedding electronic signatures in PDF documents |
| Non-Repudiation | Property ensuring signer cannot deny having signed document |
B. Certificate Validity Periods Summary
| Certificate Type | Validity Period | Renewal Window | Auto-Renewal |
|---|---|---|---|
| Root CA | 20 years | N/A (manual renewal) | No |
| Intermediate CA | 5 years | 90 days before expiry | No (requires Root CA signing) |
| User Signing | 1 year | 30 days before expiry | No (user-initiated) |
| Service Identity | 1 year | 30 days before expiry | Yes (cert-manager) |
| Agent Ephemeral | 24 hours | N/A (expires automatically) | No |
| Code Signing | 2 years | 60 days before expiry | No (engineering-initiated) |
C. Certificate Serial Number Format
Format: 160-bit random number, hex-encoded (40 characters).
Example: 0x1A2B3C4D5E6F708192A3B4C5D6E7F8091A2B3C4D
Rationale: Per RFC 5280, serial numbers must be unique within CA's scope. 160-bit random provides sufficient entropy to avoid collisions (2^160 possible values).
D. Contact Information
CA Security Team:
- Email: ca-security@coditect.ai
- On-Call: PagerDuty rotation (24/7/365)
- Incident Reporting: security-incidents@coditect.ai
Certificate Support:
- Help Desk: support@coditect.ai
- Documentation: https://docs.bio-qms.coditect.cloud/pki
- User Guides: https://docs.bio-qms.coditect.cloud/user-guides/electronic-signatures
Document End
Review Schedule: Annual review on February 16 each year.
Next Review Due: February 16, 2027.
Change Control: All updates to this document require approval from VP Engineering and CISO.
Distribution: Internal (Engineering, Security, Compliance teams), Customer-facing (public documentation portal).