Skip to content

Convert Operations

Purpose: Migration of legacy cryptographic data to modern formats and algorithms

Version: 3.0.0


Overview of Convert Phase

The Convert phase encompasses two distinct types of conversion:

1. Format Conversion (Legacy Containers → Modern JOSE)

Transforms legacy container formats to modern JOSE standards with the same classical keys — no post-quantum algorithm is introduced.

Key Operations:

  • PKCS#7/CMS to JWE/JWS: Convert S/MIME and legacy system files to JOSE format
  • Signatures produced again: each signer's content is re-signed with its matched key, under the JWS alg that key signs with (PS256 for RSA, ES* / ESB* for EC)
  • Content encrypted again: the content is always re-encrypted under A256GCM (whatever cipher the PKCS#7 used — AES-CBC, 3DES, RC2 or CAST5), and a new content-encryption key is wrapped to every recipient under its key's alg (RSA-OAEP-512 for RSA)
  • Every actor needs a key imported with its private key: current limitation — a certificate imported alone is a verify-only trust anchor and is refused as a signer or a recipient
  • The caller needs re-operation grants on those keys: REENCRYPT from the recipient that decrypts to every recipient (its own pair included) and RESIGN from each signer's key to itself. A REENCRYPT or RESIGN grant is requested with exactly two assetKids: N recipients need N-1 pair grants [decrypting recipient, recipient], one recipient needs the in-place grant, requested with its kid twice (assetKids: [kid, kid]) and stored as [kid], and each signer needs RESIGN [signer, signer]; there is no wildcard REENCRYPT or RESIGN grant. DECRYPT, ENCRYPT and SIGN grants, and the migration.convertPkcs7 scope alone, authorize no conversion; a missing grant is 403

Endpoints:

  • POST /api/v3/migration/convert-pkcs7-to-jose (compact; bounded by migration.max-upload-bytes, default 5 MB)
  • POST /api/v3/migration/stream/convert-pkcs7-to-jose (streaming; the upload is bounded at 100 MB and refused 413 payload-too-large above it — a proxy in front of the deployment may cap uploads lower; see Behind a buffering proxy)

What unbounded size costs on the streaming endpoint, and how a failure reaches you

Cost. EnvelopedData converts in a single pass with bounded memory, whatever the number of recipients. The signed shapes read the uploaded file once per signer plus once more, because RFC 2315 places the signer metadata after the content and each signature is computed in its own pass: SignedData with N signers costs N + 1 passes, SignedAndEnvelopedData N + 3. Expect the wall-clock time to scale with the signer count. Every signer and recipient is resolved to a tenant key before the first byte is written, which is why a missing key is a 422 naming every unresolved actor, at every input size. The streaming route is also under the streaming concurrency bound (429 with Retry-After when it is full).

Failures. Every failure decidable before the first payload byte is a response status with an application/problem+json body. An EnvelopedData content-decryption failure — a PKCS #1 v1.5 encrypted key that does not unwrap included, since it is replaced by a random key (RFC 3218 §2.3.2) and fails at the content — is raised while the output is being emitted: it is the 422 decryption-failed problem document while the response is still uncommitted, and once the response is committed the response is aborted — its framing is never completed and no problem document is written into the body, so a response that stops short is a failure; discard the partial output. See PKCS#7 Conversion — the abort contract.

decryptionKid is optional, and a dual-use legacy key

For EnvelopedData and SignedAndEnvelopedData, decryptionKid is optional. When it is absent, the first recipient in encoded order whose tenant key admits decryption and encryption decrypts; when it is present it must name one of the recipients (a kid that names none of them is 400 invalid-input). If a recipient key was a dual-use legacy RSA keypair imported with purpose: DUAL, it was projected onto two single-purpose identities that share one certificate; the conversion selects the projection each role admits (the ENCRYPT_DECRYPT projection for a recipient, the SIGN_VERIFY projection for a signer). To name it explicitly, pass the <kid>-enc identity as decryptionKid, NOT the -sig identity. The DUAL projection is declared on the import request itself, POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore.

targetFormat must match the parsed structure (else 422)

targetFormat selects the JOSE output: AUTO (default) auto-detects from the parsed PKCS#7 structure, while an explicit JWS / JWE / JWE_JWS_NESTED forces that output. An explicit targetFormat incompatible with the structure (JWS↔SignedData, JWE↔EnvelopedData, JWE_JWS_NESTED↔SignedAndEnvelopedData) is rejected with 422 unsupported-pkcs7-format (errorCode = INCOMPATIBLE_TARGET_FORMAT). The streaming endpoint honors targetFormat for this rejection too, returning the 422 as a response status with an application/problem+json body before any payload byte, at every input size. See PKCS#7 Conversion — Error Response Contract.

See: PKCS#7 Conversion for detailed workflow


2. Algorithm Conversion (Classical → Post-Quantum)

Transforms data from classical algorithms to quantum-resistant algorithms.

Key Operations:

  • Data re-encryption: Decrypt with RSA/AES → Encrypt with ML-KEM/AES-GCM
  • Signature conversion: Verify RSA/ECDSA → Re-sign with ML-DSA/FALCON
  • Batch conversion: Bulk operations with checkpoints
  • Streaming re-encryption: Large files with constant 2 MiB memory footprint (USPTO patent architecture)

Endpoints:

  • POST /api/v3/crypto/reencrypt, POST /api/v3/crypto/stream/reencrypt
  • POST /api/v3/crypto/resign, POST /api/v3/crypto/stream/resign

Outcome: Data and signatures protected by quantum-resistant algorithms (ML-KEM, ML-DSA, FALCON, SLH-DSA)


Migration Path

For legacy PKCS#7 files:

  1. Format conversion first: PKCS7 → JOSE (using /api/v3/migration/convert-pkcs7-to-jose)
  2. Algorithm conversion second (optional): JOSE classical → JOSE PQC (using /api/v3/crypto/reencrypt or /api/v3/crypto/resign)

Step 2 accepts every conversion result, whether it names one key or several. On a General JSON JWS with several signatures or a General JSON JWE with several recipients — the output of a multi-signer or multi-recipient PKCS#7 — the crypto operations (decryptData, verifySignature, reencryptData, resignData, decryptThenVerify, and their streaming twins) follow four rules: decrypt uses the recipient the caller names in recipientKid and holds a grant on; verify requires every signature to be valid and reports each signer; re-sign verifies every signature first and replaces only the rotated one (sourceKid → newKid); re-encrypt always draws a fresh content-encryption key and replaces only the rotated recipient. Each key needs its own grant. See Operating on a converted result.

These are separate sequential steps, not a single operation.


Data Re-encryption Workflows

Compact Re-encryption (≤5MB files)

Purpose: Decrypt data encrypted with classical algorithms and re-encrypt with new keys

Process (in-memory):

graph LR
    Ciphertext["Legacy Ciphertext<br/>RSA-encrypted data"] -->|1. Decrypt| LegacyKey["Imported RSA Key<br/>From PKCS#12"]
    LegacyKey -->|2. Produces| Plaintext["Plaintext Data<br/>Decrypted payload<br/>Full byte array in RAM"]

    Plaintext -->|3. Encrypt| PQCKey["New ML-KEM Key<br/>Generated in ANKASecure"]
    PQCKey -->|4. Produces| PQCCiphertext["PQC Ciphertext<br/>ML-KEM-encrypted data"]

    style Ciphertext fill:#ffcccc,stroke:#333,stroke-width:2px
    style PQCCiphertext fill:#51cf66,stroke:#333,stroke-width:2px
    style Plaintext fill:#ffd43b,stroke:#333,stroke-width:2px

Endpoint: POST /api/v3/crypto/reencrypt

Key Considerations:

  • Legacy key must have decrypt in keyOps: Expired certificates imported with IMPORT_ONLY mode allow decryption
  • Server-side operation: Re-encryption performed entirely server-side; plaintext exists as full byte array in server memory
  • Memory zeroing: Plaintext is zeroized immediately after re-encryption (defense-in-depth)
  • Size limit: ≤5MB (for larger files use streaming mode)

Streaming Re-encryption (any file size)

Purpose: Re-encrypt large files with constant memory footprint

Process (USPTO patent architecture):

graph LR
    Ciphertext["Legacy Ciphertext<br/>Stream input"] -->|Decrypt Thread| Pipe["BoundedByteQueue<br/>2 MiB pipe<br/>32 chunks × 64 KiB"]
    Pipe -->|Encrypt Thread| NewCipher["New Ciphertext<br/>Stream output"]

    style Ciphertext fill:#ffcccc,stroke:#333,stroke-width:2px
    style Pipe fill:#ffd43b,stroke:#333,stroke-width:2px
    style NewCipher fill:#51cf66,stroke:#333,stroke-width:2px

Endpoint: POST /api/v3/crypto/stream/reencrypt

Key Considerations:

  • No full plaintext accumulation: Only small chunks (64 KiB) exist in memory at any time
  • Constant memory footprint: 2 MiB regardless of file size (works with GB/TB files)
  • Virtual threads: Decrypt and encrypt operate in parallel for performance
  • Server-side operation: Plaintext chunks never leave server memory, never written to disk or sent to client
  • A failure after the response is committed aborts it: the framing is never completed and no problem document is written into the body; treat a short read as a failure and discard the partial output. Before the response is committed the same failure is an application/problem+json status
  • A producer failure is never an end-of-stream: the pipe between them carries one terminal state — complete only on a normal return, failed otherwise — so a decrypt failure makes the consumer's read throw instead of letting it finish over a short stream and report success

PQC Encryption (With New Keys)

Purpose: Encrypt data with quantum-resistant algorithms

Supported PQC Encryption Algorithms:

  • ML-KEM-512: Equivalent to ~128-bit classical security
  • ML-KEM-768: Equivalent to ~192-bit classical security (recommended)
  • ML-KEM-1024: Equivalent to ~256-bit classical security (high security)

Process:

  1. Generate PQC key (if not already exists)
  2. Encrypt plaintext using ML-KEM + AES-256-GCM (hybrid encryption)
  3. Store ciphertext (replacing legacy encrypted version)
  4. Verify decryption (test round-trip to confirm success)

Streaming Re-encryption (Large Files)

Purpose: Convert large encrypted files without loading entire plaintext into memory

ANKASecure USPTO Patent (2025): Streaming re-encryption technology

Architecture:

graph TD
    LegacyFile["Legacy Encrypted File<br/>e.g., 10 GB archive"] -->|Stream chunks| Decrypt["Decrypt Chunk<br/>with Legacy Key"]
    Decrypt -->|Plaintext chunk| Encrypt["Encrypt Chunk<br/>with PQC Key"]
    Encrypt -->|PQC ciphertext chunk| PQCFile["PQC Encrypted File<br/>Output stream"]

    Decrypt -.->|No full plaintext| Memory["Memory Usage:<br/>Only 1 chunk at a time"]
    Encrypt -.->|Streaming| Memory

    style LegacyFile fill:#ffcccc,stroke:#333,stroke-width:2px
    style PQCFile fill:#51cf66,stroke:#333,stroke-width:2px
    style Memory fill:#4dabf7,stroke:#333,stroke-width:2px

Advantages:

  • ✅ Memory efficient: Only one chunk in memory at a time (typically 4 MB chunks)
  • ✅ Plaintext never fully exposed: Only partial plaintext exists momentarily
  • ✅ Progress tracking: Can report conversion progress per chunk
  • ✅ Resumable: Can checkpoint and resume if interrupted

Endpoint: See Streaming Operations* for detailed API documentation

Verification After Conversion

Purpose: Ensure converted data can be decrypted successfully

Verification Process:

sequenceDiagram
    participant Admin
    participant Convert as Conversion Service
    participant PQCKey as PQC Key
    participant Test as Verification

    Admin->>Convert: Convert file X from RSA to ML-KEM
    Convert->>PQCKey: Encrypt with ML-KEM-768
    Convert->>Test: Test decryption

    Test->>PQCKey: Decrypt with ML-KEM-768
    PQCKey-->>Test: Decrypted plaintext

    Test->>Test: Compare with original
    alt Match
        Test-->>Admin: ✅ Conversion successful
    else Mismatch
        Test-->>Admin: ❌ Conversion failed<br/>Rollback recommended
    end

Validation Steps:

  1. Decrypt converted file with PQC key
  2. Compare hash of decrypted plaintext with original plaintext hash
  3. If match: Conversion successful
  4. If mismatch: Rollback, investigate issue, retry

Signature Conversion Workflows

Legacy Signature Verification

Purpose: Verify signatures created with classical algorithms

Process:

graph LR
    Document["Signed Document"] -->|1. Extract| Signature["Legacy RSA Signature"]
    Document -->|2. Hash| Hash["Document Hash"]

    Signature -->|3. Verify| LegacyKey["Imported RSA Public Key"]
    Hash -->|3. Verify| LegacyKey

    LegacyKey -->|4. Result| Verdict{"Valid?"}
    Verdict -->|Yes| Valid["✅ Signature Valid<br/>Proceed to re-sign"]
    Verdict -->|No| Invalid["❌ Signature Invalid<br/>Do not convert"]

    style Valid fill:#51cf66,stroke:#333,stroke-width:2px
    style Invalid fill:#ff6b6b,stroke:#333,stroke-width:2px

Key Consideration: Only convert if legacy signature is valid. Invalid signatures indicate data tampering or corruption.

PQC Re-signing

Purpose: Create new signatures using quantum-resistant algorithms

Supported PQC Signature Algorithms:

  • ML-DSA-44: Small signature size (~2.4 KB), 128-bit security
  • ML-DSA-65: Standard signature size (~3.3 KB), 192-bit security (recommended)
  • ML-DSA-87: Large signature size (~4.6 KB), 256-bit security
  • FALCON-512: Compact signature (~666 bytes), 128-bit security
  • FALCON-1024: Compact signature (~1.3 KB), 256-bit security

Process:

  1. Verify legacy signature (ensure document authentic)
  2. Generate PQC signing key (ML-DSA or FALCON)
  3. Sign document with PQC key
  4. Store new signature (optionally keep legacy signature for transition period)

Hybrid Signatures (Dual Algorithms)

Purpose: Maintain both classical and PQC signatures during transition period

Use Case: Gradual migration where some systems still require classical signatures

This pattern signs with two separate SIMPLE keys, so each signature verifies on its own. It is not a COMPOSITE_SIGNATURE key, whose one composite signature is valid only when both of its components verify (see Composite Hybrid Keys*).

Architecture:

graph TD
    Document["Document to Sign"] -->|Sign| LegacyKey["Legacy RSA Key"]
    Document -->|Sign| PQCKey["PQC ML-DSA Key"]

    LegacyKey -->|Produces| LegacySig["RSA Signature"]
    PQCKey -->|Produces| PQCSig["ML-DSA Signature"]

    LegacySig -->|Attach| Dual["Dual-Signed Document"]
    PQCSig -->|Attach| Dual

    Dual -->|Verify with| LegacyVerifier["Legacy Systems<br/>Use RSA signature"]
    Dual -->|Verify with| PQCVerifier["PQC-Ready Systems<br/>Use ML-DSA signature"]

    style Dual fill:#ffd43b,stroke:#333,stroke-width:2px
    style LegacyVerifier fill:#ffcccc,stroke:#333,stroke-width:2px
    style PQCVerifier fill:#51cf66,stroke:#333,stroke-width:2px

Dual Signature Format (JWS with multiple signatures):

{
  "payload": "eyJkYXRhIjogInNhbXBsZSJ9",
  "signatures": [
    {
      "protected": "eyJhbGciOiJQUzI1NiJ9",
      "signature": "RSA_SIGNATURE_HERE"
    },
    {
      "protected": "eyJhbGciOiJNTC1EU0EtNjUifQ",
      "signature": "ML_DSA_SIGNATURE_HERE"
    }
  ]
}

Transition Strategy:

  • Month 1-2: Add ML-DSA signature alongside RSA (dual signatures)
  • Month 3-4: Verify both systems accept ML-DSA
  • Month 5: Remove RSA signature, keep only ML-DSA

Key Format Conversion

Export Operations

Purpose: Retrieve keys for external system integration

Endpoint: GET /api/v3/admin/tenants/{tenantId}/keys/{kid}/export (Admin API; the Core API has no export route)

Scope Required: SCOPE_admin.keys.read

Use Cases:

  • Sharing public keys with partner organizations
  • Integrating ANKASecure keys with external verification systems
  • Key distribution for multi-party encryption
  • Comparing a tenant key with a certificate held elsewhere

Request:

GET /api/v3/admin/tenants/00000000-0000-0000-0000-000000000001/keys/prod-signing-key/export HTTP/1.1
Host: api.ankatech.co
Authorization: Bearer {jwt-token}

Response - Asymmetric Key (public portion only):

{
  "kid": "prod-signing-key",
  "kty": "ML-DSA",
  "alg": "ML-DSA-87",
  "type": "SIMPLE",
  "publicKey": "MIIHsjALBglghkgBZQMEAxMDggehAE...",
  "keyOps": ["sign", "verify"],
  "exportable": true,
  "origin": "GENERATED",
  "restricted": false,
  "status": "active",
  "createdAt": "2025-01-15T10:20:00Z",
  "expiresAt": "2030-01-15T10:20:00Z",
  "usageCount": 1542
}

Response - Symmetric Key (secret omitted):

{
  "kid": "aes-session-key",
  "kty": "oct",
  "alg": "AES-GCM-256",
  "type": "SIMPLE",
  "keyOps": ["encrypt", "decrypt"],
  "exportable": true,
  "origin": "GENERATED",
  "status": "active",
  "createdAt": "2025-12-01T08:00:00Z"
}

Private Material Never Exported

For asymmetric keys, only the public key is returned; a composite key returns its component public keys in components[]. For symmetric keys (kty=oct), the secret is deliberately omitted for security. A key marked non-exportable (exportable false) is refused 400 invalid-input with no key material.

Response - Not Found: a kid that does not exist for the tenant — or a kid of another tenant, or a path naming another tenant — answers 404 with type https://docs.ankatech.co/errors/not-found.

Format Transformation

Purpose: Convert between key formats (PEM, DER, JWK)

Supported Formats:

Format Description Use Case
PEM Base64-encoded DER with headers Traditional Unix/Linux systems
DER Binary X.509 encoding Java keystores, Windows systems
JWK JSON Web Key format Modern web applications, REST APIs

Note: ANKASecure stores keys internally in wrapped format. Export API returns keys in standard formats for interoperability.

Key Wrapping/Unwrapping

Purpose: Encrypt keys for secure transport

Key Wrapping Process:

graph LR
    PlainKey["Plain PQC Key"] -->|Wrap with| KEK["Key Encryption Key<br/>AES-256-GCM"]
    KEK -->|Produces| WrappedKey["Wrapped Key<br/>Encrypted blob"]

    WrappedKey -->|Transmit| Transport["Secure Transport<br/>HTTPS, TLS"]
    Transport -->|Receive| Destination["Destination System"]

    Destination -->|Unwrap with| KEK2["Same KEK<br/>Pre-shared"]
    KEK2 -->|Produces| PlainKey2["Plain PQC Key<br/>Restored"]

    style WrappedKey fill:#51cf66,stroke:#333,stroke-width:2px
    style Transport fill:#4dabf7,stroke:#333,stroke-width:2px

Use Case: Migrating keys between ANKASecure instances or to external HSMs


Batch Conversion Operations

Bulk Re-encryption Strategies

Purpose: Convert large numbers of encrypted files efficiently

Strategy 1: Parallel Conversion

graph TD
    FileList["1000 Encrypted Files"] -->|Split| Batch1["Batch 1<br/>Files 1-200"]
    FileList -->|Split| Batch2["Batch 2<br/>Files 201-400"]
    FileList -->|Split| Batch3["Batch 3<br/>Files 401-600"]
    FileList -->|Split| Batch4["Batch 4<br/>Files 601-800"]
    FileList -->|Split| Batch5["Batch 5<br/>Files 801-1000"]

    Batch1 -->|Thread 1| Convert1["Convert to ML-KEM"]
    Batch2 -->|Thread 2| Convert2["Convert to ML-KEM"]
    Batch3 -->|Thread 3| Convert3["Convert to ML-KEM"]
    Batch4 -->|Thread 4| Convert4["Convert to ML-KEM"]
    Batch5 -->|Thread 5| Convert5["Convert to ML-KEM"]

    Convert1 -->|Complete| Results["Aggregated Results"]
    Convert2 -->|Complete| Results
    Convert3 -->|Complete| Results
    Convert4 -->|Complete| Results
    Convert5 -->|Complete| Results

    style Results fill:#51cf66,stroke:#333,stroke-width:2px

Advantages:

  • ⚡ Faster completion (parallel processing)
  • 📊 Progress tracking per batch
  • ♻️ Resource utilization (CPU/memory distributed)

Disadvantages:

  • 🔧 More complex coordination
  • 💾 Higher memory usage (multiple concurrent operations)

Strategy 2: Sequential Conversion with Checkpoints

graph LR
    Start["File 1"] -->|Convert| C1["✓ File 1"]
    C1 -->|Checkpoint| CP1["Checkpoint 1:<br/>1 file complete"]

    CP1 -->|Continue| C2["✓ File 2"]
    C2 -->|Checkpoint| CP2["Checkpoint 2:<br/>2 files complete"]

    CP2 -->|Continue| Dots["..."]
    Dots -->|Final| Complete["All Files Complete"]

    style CP1 fill:#ffd43b,stroke:#333,stroke-width:2px
    style CP2 fill:#ffd43b,stroke:#333,stroke-width:2px
    style Complete fill:#51cf66,stroke:#333,stroke-width:2px

Advantages:

  • ✅ Simple implementation
  • 💾 Low memory usage (one file at a time)
  • ♻️ Easy resume (from last checkpoint)

Disadvantages:

  • 🐢 Slower completion (sequential processing)

Performance Optimization

Batch Size Recommendations:

Total Files Recommended Batch Size Parallel Threads Estimated Time
< 100 20 files/batch 2 threads Minutes
100-1,000 50 files/batch 4 threads Hours
1,000-10,000 100 files/batch 8 threads Days
> 10,000 200 files/batch 16 threads Weeks

Optimization Tips:

  1. Pre-validate keys: Ensure all legacy keys loaded before starting batch
  2. Warm up: Convert 10 sample files first to identify issues early
  3. Monitor resources: Track CPU, memory, disk I/O during conversion
  4. Rate limiting: If API-based, respect rate limits (e.g., 100 req/sec)

Checkpoint/Resume Patterns

Purpose: Handle interruptions gracefully without starting over

Checkpoint Format:

{
  "batchKey": "batch-2025-12-24-001",
  "totalFiles": 1000,
  "completedFiles": 342,
  "failedFiles": 3,
  "checkpointTime": "2025-12-24T14:30:00Z",
  "nextFileIndex": 343,
  "failedFilesList": [
    {"file": "file_150.enc", "error": "Decryption failed"},
    {"file": "file_201.enc", "error": "Legacy key expired"},
    {"file": "file_299.enc", "error": "Corrupted ciphertext"}
  ]
}

Resume Process:

  1. Load checkpoint: Read last checkpoint from persistent storage
  2. Verify completed files: Optionally re-check last N files to ensure integrity
  3. Resume from nextFileIndex: Continue conversion from where left off
  4. Update checkpoint periodically: Every N files or every M minutes

Failure Recovery

Failure Types:

Failure Type Recovery Strategy Prevention
Decryption failure Log error, skip file, continue Pre-validate keys before batch
Network timeout Retry with exponential backoff Use connection pooling
Out of memory Reduce batch size, restart Monitor memory, use streaming
Disk full Pause, free space, resume Pre-check disk space
API rate limit Wait, then resume Implement rate limiting client-side

Error Handling Pattern:

graph TD
    Convert["Convert File"] -->|Error?| Check{"Error Type?"}

    Check -->|Transient<br/>Network, timeout| Retry["Retry with Backoff<br/>Max 3 attempts"]
    Check -->|Permanent<br/>Bad key, corrupt data| LogSkip["Log Error<br/>Skip file<br/>Continue batch"]
    Check -->|Critical<br/>Out of memory, disk full| Abort["Abort Batch<br/>Save checkpoint<br/>Alert admin"]

    Retry -->|Success| Next["Next File"]
    Retry -->|Still failing| LogSkip
    LogSkip -->|Continue| Next

    style Next fill:#51cf66,stroke:#333,stroke-width:2px
    style Abort fill:#ff6b6b,stroke:#333,stroke-width:2px

Conversion Verification

Integrity Checks

Purpose: Ensure data integrity after conversion

Verification Methods:

  1. Hash Comparison:

    • Hash original plaintext: SHA-256(original_plaintext)
    • Decrypt converted ciphertext: plaintext' = decrypt_PQC(converted_ciphertext)
    • Hash decrypted plaintext: SHA-256(plaintext')
    • Compare hashes: original_hash == new_hash
  2. Content Comparison:

    • Decrypt both legacy and PQC ciphertexts
    • Compare byte-by-byte
    • Verify exact match
  3. Selective Sampling:

    • For large batches, verify random sample (e.g., 5% of files)
    • If sample passes, assume batch successful
    • If sample fails, verify all files

Functionality Testing

Purpose: Ensure converted data works in production scenarios

Test Cases:

Scenario Test Expected Result
Decrypt test Decrypt PQC ciphertext with PQC key Plaintext matches original
Sign/verify test Create PQC signature, verify with PQC public key Signature valid
Cross-system test Export PQC key, decrypt on external system Successful decryption
Performance test Decrypt 100 PQC ciphertexts Acceptable latency (<100ms/file)
Stress test Decrypt 10,000 files concurrently No errors, acceptable throughput

Performance Validation

Purpose: Ensure PQC operations meet performance requirements

Baseline Metrics (RSA-2048 vs. ML-KEM-768):

Operation RSA-2048 ML-KEM-768 Relative Performance
Encryption ~0.5 ms ~0.05 ms 10x faster
Decryption ~5 ms ~0.06 ms 83x faster
Key Generation ~50 ms ~1 ms 50x faster

Validation:

  • Measure actual performance after conversion
  • Compare to baseline
  • If degradation > 20%: Investigate (likely infrastructure issue)
  • If improvement: Confirm and document

  • API Reference - Complete endpoint documentation
  • Analyze Operations - Certificate validation and compatibility analysis
  • Streaming Operations* - Streaming re-encryption architecture
  • RSA to ML-KEM Migration* - Complete encryption migration workflow
  • Monitoring & Validation - Success criteria and health checks

Version: 3.0.0
Last Updated: 2025-12-24 Status: Production Ready

* restricted content — see higher-tier documentation