Analyze Operations
Purpose: Validating and assessing imported cryptographic material before conversion
Version: 3.0.0
Overview of Analyze Phase
The Analyze phase is the second step in the migration workflow: Import → Analyze → Convert. After importing cryptographic keys and certificates, you must validate their compatibility and security status before attempting conversion to post-quantum algorithms.
Purpose: Validate before conversion
Key Activities:
- Certificate validation (X.509 structure, expiration, chain integrity)
- Key compatibility analysis (algorithm identification, key sizes, usage constraints)
- Security analysis (expiration assessment, weakness detection)
- Status determination — the certificate's temporal and revocation state and the operation restrictions it implies (not the imported key's own lifecycle status, which is one of the nine published key-status tokens:
active,pending_rotation,rotated,expired,revoked,archived,deleted_logical,suspended,pending_destruction) - PQC migration path mapping (which classical algorithm maps to which PQC algorithm)
Outcome: Clear understanding of which keys can be converted, which operations are allowed, and what PQC algorithms to use.
Certificate Validation Analysis
X.509 Structure Validation
Purpose: Ensure imported certificates conform to X.509 standard
Validation Checks:
- Certificate version (v1, v2, v3)
- Serial number uniqueness
- Signature algorithm compatibility
- Subject and Issuer DN (Distinguished Name) structure
- Validity dates format (notBefore, notAfter)
- Public key algorithm and parameters
- Extensions structure (if present)
Common Issues:
- Malformed certificates (encoding errors, truncated data)
- Unsupported certificate versions
- Invalid DN syntax
- Missing required fields
Resolution: Reject import with detailed error message identifying structural issue.
Key Binding Validation
Purpose: Cryptographic proof that private key matches certificate's public key
Validation Process:
graph LR
PrivKey["Private Key"] -->|1. Sign| TestData["Test Data<br/>Random bytes"]
TestData -->|2. Signature| Sig["Digital Signature"]
Cert["Certificate"] -->|3. Extract| PubKey["Public Key"]
Sig -->|4. Verify| Verify{"Verification"}
PubKey -->|4. Verify| Verify
Verify -->|Success| Match["✅ Keys Match<br/>Import allowed"]
Verify -->|Failure| Mismatch["❌ Keys Mismatch<br/>Reject import"]
style Match fill:#51cf66,stroke:#333,stroke-width:2px
style Mismatch fill:#ff6b6b,stroke:#333,stroke-width:2px Why This Matters: Prevents importing mismatched key-certificate pairs that would fail in production.
Temporal Validation
Purpose: Check certificate validity period
Validation Rules:
| Condition | validationMode=STRICT | validationMode=IMPORT_ONLY | validationMode=SKIP |
|---|---|---|---|
| Not yet valid (now < notBefore) | ❌ Reject | ❌ Reject | ❌ Reject |
| Valid (notBefore ≤ now ≤ notAfter) | ✅ Accept, ACTIVE | ✅ Accept, ACTIVE | ✅ Accept, ACTIVE |
| Expired (now > notAfter) | ❌ Reject | ✅ Accept, EXPIRED, restricted=true | ✅ Accept, ACTIVE |
Key Insight: Expired certificates can still decrypt historical data, hence IMPORT_ONLY mode allows import with restrictions.
Chain Signature Verification
Purpose: Validate cryptographic integrity of certificate chain
Validation Process:
graph TD
EndEntity["End-Entity Certificate<br/>CN=server.example.com"]
Intermediate["Intermediate CA<br/>CN=Example Intermediate CA"]
Root["Root CA<br/>CN=Example Root CA"]
EndEntity -->|Signed by| Intermediate
Intermediate -->|Signed by| Root
Root -->|Self-signed| Root
EndEntity -->|Verify signature| V1{"Valid?"}
Intermediate -->|Verify signature| V2{"Valid?"}
V1 -->|Yes| V2
V2 -->|Yes| TrustChain["✅ Chain Valid"]
V1 -->|No| ChainBroken["❌ Chain Broken"]
V2 -->|No| ChainBroken
style TrustChain fill:#51cf66,stroke:#333,stroke-width:2px
style ChainBroken fill:#ff6b6b,stroke:#333,stroke-width:2px Common Issues:
- Intermediate CA missing from PKCS#12 file (incomplete chain)
- Signature algorithm mismatch between certificates
- Self-signed end-entity certificate (no chain validation possible)
PKIX Trust Anchor Validation
Purpose: Verify chain terminates at a trusted root CA (RFC 5280)
When Performed: Only if the operator has configured trusted CA certificates on the deployment
Validation Logic:
graph TD
Start{"Trust anchors<br/>configured?"}
Start -->|No| SkipPKIX["Skip PKIX validation"]
Start -->|Yes| CheckCert{"Certificate type?"}
CheckCert -->|Self-signed| SkipPKIX
CheckCert -->|Public CA| ValidatePublic["Validate against<br/>Mozilla CA bundle"]
CheckCert -->|Private CA| ValidatePrivate["Validate against<br/>custom trust anchors"]
ValidatePublic -->|Root found| PKIXPass["✅ PKIX validation passed"]
ValidatePublic -->|Root NOT found| PKIXFail["❌ Untrusted root CA"]
ValidatePrivate -->|Root found| PKIXPass
ValidatePrivate -->|Root NOT found| PKIXFail
PKIXPass -->|STRICT mode| AcceptImport["Accept import"]
PKIXFail -->|STRICT mode| RejectImport["Reject import"]
PKIXFail -->|IMPORT_ONLY| AcceptRestricted["Accept with<br/>origin=IMPORTED<br/>restricted=true<br/>decrypt/verify only"]
style PKIXPass fill:#51cf66,stroke:#333,stroke-width:2px
style PKIXFail fill:#ff6b6b,stroke:#333,stroke-width:2px
style AcceptRestricted fill:#ffd43b,stroke:#333,stroke-width:2px Supported Trust Anchors:
- Public CAs: Mozilla CA bundle (144 trusted root CAs)
- Corporate CAs: Custom root CAs added to trust-anchors directory
- Self-signed: Automatically skipped (no trust anchor applicable)
Extension Validation
Purpose: Validate certificate extensions (keyUsage, extendedKeyUsage)
Key Extensions Analyzed:
keyUsage (RFC 5280):
- digitalSignature
- nonRepudiation
- keyEncipherment
- dataEncipherment
- keyAgreement
- keyCertSign
- cRLSign
extendedKeyUsage (RFC 5280):
- serverAuth (TLS server)
- clientAuth (TLS client)
- codeSigning
- emailProtection
- timeStamping
Validation Rules:
| Extension | Present | Validation |
|---|---|---|
| keyUsage | Yes | Verify usage aligns with intended operations |
| keyUsage | No | ⚠️ Warning only (older certificates may lack this) |
| extendedKeyUsage | Yes | Informational (log usage types) |
| extendedKeyUsage | No | No action |
Key Compatibility Analysis
Algorithm Identification
Purpose: Determine current cryptographic algorithm for migration path mapping
Supported Algorithms:
| Algorithm Family | Specific Algorithms | PQC Equivalent |
|---|---|---|
| RSA Encryption | RSA-1024, RSA-2048, RSA-3072, RSA-4096 | ML-KEM-512/768/1024 |
| ECC Encryption | ECDH P-256, P-384, P-521 | ML-KEM-768/1024 |
| RSA Signing | RSA-SHA256, RSA-SHA512 | ML-DSA-65/87, FALCON-512/1024 |
| ECC Signing | ECDSA P-256, P-384, P-521 | ML-DSA-65/87, FALCON-512/1024 |
Algorithm Detection:
graph TD
Cert["Certificate"] -->|Extract| PubKey["Public Key"]
PubKey -->|OID Analysis| OID{"Algorithm OID?"}
OID -->|1.2.840.113549.1.1.*| RSA["RSA Family"]
OID -->|1.2.840.10045.2.1| ECC["ECC Family"]
OID -->|Other| Unsupported["⚠️ Unsupported Algorithm"]
RSA -->|Key size| RSASize{"Size?"}
RSASize -->|1024 bits| RSA1024["RSA-1024<br/>→ ML-KEM-512"]
RSASize -->|2048 bits| RSA2048["RSA-2048<br/>→ ML-KEM-768"]
RSASize -->|4096 bits| RSA4096["RSA-4096<br/>→ ML-KEM-1024"]
ECC -->|Curve| ECCCurve{"Curve?"}
ECCCurve -->|P-256| P256["P-256<br/>→ ML-KEM-768"]
ECCCurve -->|P-384| P384["P-384<br/>→ ML-KEM-1024"]
style RSA2048 fill:#4dabf7,stroke:#333,stroke-width:2px
style RSA4096 fill:#4dabf7,stroke:#333,stroke-width:2px
style P256 fill:#4dabf7,stroke:#333,stroke-width:2px Key Size Verification
Purpose: Ensure key size is within acceptable security parameters
Security Thresholds:
| Algorithm | Minimum Size | Recommended Size | Status |
|---|---|---|---|
| RSA | 1024 bits | 2048+ bits | 1024 deprecated |
| ECC | 224 bits | 256+ bits | 224 deprecated |
| AES | 128 bits | 256 bits | All sizes valid |
Analysis Output:
{
"algorithm": "RSA",
"keySize": 2048,
"securityLevel": "112-bit classical security",
"pqcEquivalent": "ML-KEM-768",
"migrationRecommendation": "Suitable for migration to ML-KEM-768"
}
Usage Constraints (keyOps)
Purpose: Determine which operations are allowed based on certificate validation results
keyOps Determination Logic:
stateDiagram-v2
[*] --> ValidateCert: Import request
ValidateCert --> CheckStatus: Validation complete
CheckStatus --> ValidCert: Certificate valid
CheckStatus --> ExpiredCert: Certificate expired
CheckStatus --> RevokedCert: Certificate revoked
ValidCert --> AllOps: keyOp [sign, verify, encrypt, decrypt]
ValidCert --> SetActive: status ACTIVE
ValidCert --> SetOrigin: origin IMPORTED, restricted false
ExpiredCert --> CheckMode: Check validationMode
CheckMode --> StrictMode: STRICT
CheckMode --> ImportOnlyMode: IMPORT_ONLY
StrictMode --> Reject: ❌ Reject import
ImportOnlyMode --> RestrictedOps: keyOps [decrypt, verify]
ImportOnlyMode --> SetExpired: status EXPIRED
ImportOnlyMode --> SetRestricted: origin IMPORTED, restricted true
RevokedCert --> AllowDecrypt: keyOps [decrypt, verify]
RevokedCert --> SetRevoked: status REVOKED
RevokedCert --> SetRestrictedRevoked: origin IMPORTED, restricted true
AllOps --> [*]
Reject --> [*]
RestrictedOps --> [*] keyOps Rules:
- Valid certificate: All operations allowed (sign, verify, encrypt, decrypt)
- Expired certificate (IMPORT_ONLY): Read-only operations (decrypt, verify) - cannot create new encrypted data or signatures
- Revoked certificate: Read-only operations (decrypt, verify) - same as expired
- Not yet valid: Rejected (no keyOps assigned)
PQC Migration Path Mapping
Purpose: Recommend post-quantum algorithm for migration
Mapping Matrix:
graph LR
subgraph Classical["Classical Algorithms"]
RSA2048["RSA-2048"]
RSA4096["RSA-4096"]
ECDSA256["ECDSA P-256"]
ECDSA384["ECDSA P-384"]
end
subgraph PQC["Post-Quantum Recommendations"]
MLKEM768["ML-KEM-768<br/>Encryption"]
MLKEM1024["ML-KEM-1024<br/>Encryption"]
MLDSA65["ML-DSA-65<br/>Signatures"]
MLDSA87["ML-DSA-87<br/>Signatures"]
end
RSA2048 -->|Encryption| MLKEM768
RSA4096 -->|Encryption| MLKEM1024
RSA2048 -->|Signing| MLDSA65
RSA4096 -->|Signing| MLDSA87
ECDSA256 -->|Signing| MLDSA65
ECDSA384 -->|Signing| MLDSA87
style MLKEM768 fill:#51cf66,stroke:#333,stroke-width:2px
style MLKEM1024 fill:#51cf66,stroke:#333,stroke-width:2px
style MLDSA65 fill:#4dabf7,stroke:#333,stroke-width:2px
style MLDSA87 fill:#4dabf7,stroke:#333,stroke-width:2px Security Analysis
Expiration Assessment
Purpose: Determine urgency and risk of migration
Timeline Categories:
| Certificate Status | Days Until Expiry | Risk Level | Action Required |
|---|---|---|---|
| Expired | < 0 (already expired) | 🔴 Critical | Immediate: Use IMPORT_ONLY to decrypt legacy data |
| Near expiry | 0-30 days | 🟠 High | Urgent: Migrate within 1 week |
| Short-term valid | 31-90 days | 🟡 Medium | Plan: Migrate within 1 month |
| Long-term valid | 91-365 days | 🟢 Low | Schedule: Migrate within quarter |
| Very long-term | > 365 days | 🔵 Minimal | Defer: Include in annual migration cycle |
Weakness Detection
Purpose: Identify cryptographic weaknesses requiring immediate attention
Analyzed Weaknesses:
-
Deprecated Algorithms:
- RSA < 2048 bits (NIST deprecated 2013)
- ECC < 224 bits (NIST deprecated 2015)
- SHA-1 signatures (NIST deprecated 2017)
- 3DES encryption (NIST deprecated 2023)
-
Weak Key Generation:
- Low-entropy keys (e.g., generated on embedded devices)
- Small prime factors (RSA-specific)
- Predictable random number generators
-
Implementation Vulnerabilities:
- Padding oracle vulnerabilities (PKCS#1 v1.5)
- Timing attacks (RSA decryption without blinding)
- Side-channel attack susceptibility
Detection Output:
{
"weaknesses": [
{
"type": "DEPRECATED_ALGORITHM",
"severity": "HIGH",
"message": "RSA-1024 deprecated since 2013",
"recommendation": "Migrate to ML-KEM-768 immediately"
},
{
"type": "WEAK_HASH",
"severity": "MEDIUM",
"message": "Certificate uses SHA-1 signature (deprecated)",
"recommendation": "Re-issue certificate with SHA-256+"
}
]
}
Compliance Checking
Purpose: Verify alignment with regulatory requirements
Compliance Frameworks Checked:
- NIST SP 800-57: Key management guidelines
- NIST SP 800-131A: Transitioning to stronger cryptography
- FIPS 140-3: Cryptographic module validation
- PCI-DSS 4.0: Payment card industry requirements
- HIPAA: Healthcare data encryption requirements
Compliance Rules:
| Framework | RSA Minimum | ECC Minimum | Hash Minimum | Verdict |
|---|---|---|---|---|
| NIST 2024 | 2048 bits | 256 bits | SHA-256 | ✅/❌ |
| PCI-DSS 4.0 | 2048 bits | 256 bits | SHA-256 | ✅/❌ |
| FIPS 140-3 | 2048 bits | 256 bits | SHA-256 | ✅/❌ |
Analysis Results Interpretation
Status Codes
Keys can be in one of the following states after import and analysis:
| Status | Meaning | Operations Allowed | Migration Priority |
|---|---|---|---|
| ACTIVE | Valid certificate, all operations allowed | All (sign, verify, encrypt, decrypt) | Medium (scheduled migration) |
| EXPIRED | Certificate expired, read-only operations | decrypt, verify only | High (migrate soon to restore functionality) |
| REVOKED | Certificate revoked, read-only operations | decrypt, verify only | High (security risk if used for new operations) |
| PENDING_ROTATION | Scheduled for PQC migration | All (during transition period) | In progress |
| ROTATED | Successfully migrated to PQC | Legacy: decrypt/verify, PQC: all ops | Complete (cleanup legacy key) |
Key Origin and Restriction Status
The origin and restricted fields indicate special handling requirements:
origin: "IMPORTED", restricted: false (Valid Imported Key):
- Imported with valid certificate
- All operations allowed
- Behaves identically to native ANKASecure key
- Can be rotated to PQC successor
- Subject to standard lifecycle policies
origin: "IMPORTED", restricted: true (Restricted Key):
- Imported with expired/revoked certificate or untrusted CA
- Operations restricted to decrypt/verify only
- Cannot create new encrypted data or signatures
- Cannot be rotated (migration requires new key generation)
- Intended for legacy data recovery
Allowed Operations Matrix
graph TD
Key["Imported Key"] -->|Analyze| Status{"Status?"}
Status -->|ACTIVE| RestrictedCheck{"restricted?"}
Status -->|EXPIRED| RestrictedOps["decrypt, verify only"]
Status -->|REVOKED| RestrictedOps
RestrictedCheck -->|false| AllOps["All operations:<br/>sign, verify, encrypt, decrypt"]
RestrictedCheck -->|true| RestrictedOps
AllOps -->|Can perform| NewData["Create new encrypted data<br/>Create new signatures"]
RestrictedOps -->|Can perform| OldData["Decrypt restricted data<br/>Verify restricted signatures"]
AllOps -.->|Cannot perform| RestrictedOnly["Restricted data recovery<br/>if future cert expires"]
RestrictedOps -.->|Cannot perform| NewData
style AllOps fill:#51cf66,stroke:#333,stroke-width:2px
style RestrictedOps fill:#ffd43b,stroke:#333,stroke-width:2px Example: Analyzing Multi-Key PKCS#12
Step-by-Step Analysis Workflow
Scenario: Import PKCS#12 file with 3 keys, analyze each for migration planning.
PKCS#12 Contents:
- Key 1: RSA-2048, certificate expires 2026-12-31 (valid)
- Key 2: RSA-4096, certificate expired 2023-06-15
- Key 3: ECDSA P-256, certificate expires 2027-03-31 (valid)
Analysis Process:
sequenceDiagram
participant Admin
participant Import as Import API
participant Analyze as Analysis Engine
participant Output as Analysis Report
Admin->>Import: POST /keystores<br/>{validationMode: IMPORT_ONLY}
Import->>Analyze: Analyze Key 1 (RSA-2048, valid)
Analyze->>Output: ✅ ACTIVE, origin: IMPORTED, restricted: false<br/>keyOps: all → Migrate to ML-KEM-768
Import->>Analyze: Analyze Key 2 (RSA-4096, expired)
Analyze->>Output: ⚠️ EXPIRED, origin: IMPORTED, restricted: true<br/>keyOps: [decrypt, verify]<br/>→ Generate new ML-KEM-1024
Import->>Analyze: Analyze Key 3 (ECDSA P-256, valid)
Analyze->>Output: ✅ ACTIVE, keyOps: all<br/>→ Migrate to ML-DSA-65
Output-->>Admin: Analysis Complete<br/>Migration plan generated Analysis Report:
{
"totalKeys": 3,
"activeKeys": 2,
"expiredKeys": 1,
"migrationPlan": [
{
"kid": "key-1-rsa2048",
"status": "active",
"algorithm": "RSA-2048",
"expiresAt": "2026-12-31T23:59:59Z",
"pqcTarget": "ML-KEM-768",
"migrationStrategy": "Rotate to ML-KEM-768",
"priority": "MEDIUM"
},
{
"kid": "key-2-rsa4096",
"status": "expired",
"origin": "IMPORTED",
"restricted": true,
"algorithm": "RSA-4096",
"expiresAt": "2023-06-15T23:59:59Z",
"pqcTarget": "ML-KEM-1024",
"migrationStrategy": "Generate new ML-KEM-1024, decrypt restricted data, retire RSA key",
"priority": "HIGH"
},
{
"kid": "key-3-ecdsa256",
"status": "active",
"algorithm": "ECDSA P-256",
"expiresAt": "2027-03-31T23:59:59Z",
"pqcTarget": "ML-DSA-65",
"migrationStrategy": "Rotate to ML-DSA-65",
"priority": "MEDIUM"
}
]
}
Decision Making Based on Results
For Key 1 (ACTIVE, RSA-2048):
- ✅ All operations allowed
- Migration path: RSA-2048 → ML-KEM-768
- Timeline: Before 2026-12-31
- Strategy: Standard rotation workflow
For Key 2 (EXPIRED, RSA-4096, restricted=true):
- ⚠️ Read-only operations (decrypt, verify)
- Cannot use for new encryptions
- Migration path: Generate new ML-KEM-1024 key
- Timeline: Immediate (already expired)
- Strategy:
- Keep RSA-4096 for decrypting historical data
- Generate new ML-KEM-1024 key for new operations
- Eventually retire RSA-4096 when restricted data no longer needed
For Key 3 (ACTIVE, ECDSA P-256):
- ✅ All operations allowed
- Migration path: ECDSA P-256 → ML-DSA-65 (signatures)
- Timeline: Before 2027-03-31
- Strategy: Standard rotation workflow with hybrid signatures during transition
PKCS#7 File Analysis
For organizations migrating from legacy PKCS#7/CMS systems (S/MIME and other legacy systems), ANKASecure provides specialized analysis endpoints.
Purpose: Inspect PKCS#7 structure before conversion to understand:
- Number of signers and recipients
- Algorithms used (signature, encryption)
- Certificate metadata
- Conversion feasibility (supported / unsupported)
Endpoints:
POST /api/v3/migration/analyze-pkcs7(compact; the decoded PKCS#7 data is bounded by the key-import bound, 5 MB by default, which the operator can change)POST /api/v3/migration/stream/analyze-pkcs7(streaming; the file is parsed incrementally as it is received)
Both carry the scope migration.analyzePkcs7.
The streaming arm declares a 413 for the 2 MiB cap on the metadata part; it never refers to the file part. See the declared error contract below.
The streaming request is multipart/form-data with metadata first and file second, both required; see PKCS#7 Conversion for the part-ordering contract and the 400 .../errors/multipart-part-order it produces.
Declared error contract
The streaming arm's documented status set is 200, 400, 401, 403, 408, 413, 422, 429, 500, 503. The 408 is the streaming read budget while the metadata part is read, and the 503 the effective-status check, which fails closed when the calling application's or actor's status cannot be verified.
About that set:
-
400reports a malformed CMS structure. -
413is themetadatapart cap. The streaming arm answers413with thetypemultipart-part-too-largewhen themetadatapart exceeds 2 MiB. Branch on thetype, never on the status alone: the compact arm's413ispayload-too-large, answered when the decoded data exceeds the key-import bound. -
429limits concurrency. It bounds how many streaming requests may be in flight at once, globally and per tenant. The refusal is immediate and carriesRetry-After; requests are not queued. -
404is not returned. Analysis performs no decryption and no key resolution, so no not-found condition can arise. -
422reports an unsupported PKCS#7 structure.
The two arms differ only where their behaviour differs
POST /api/v3/migration/analyze-pkcs7 requires the same scope as its streaming sibling, so a token without migration.analyzePkcs7 is refused with a 403. The compact arm returns that 403, and the same effective-status 503, so its documented set is 200, 400, 401, 403, 413, 422, 500, 503. It differs from the streaming arm's in three places: the compact arm has no 429 (the concurrency bound covers the streaming routes only) and no 408 (it reads no multipart body), and its 413 is payload-too-large, answered when the decoded data exceeds the key-import bound.
Example request:
Analysis takes no key and no option. It is purely structural — nothing is decrypted, no certificate path and no timestamp is validated — so the compact request carries pkcs7Data only, and the streaming request's metadata part is an empty JSON object, {}, still required and still first. A member either request does not define is refused 400 invalid-input with a detail naming the member (never its value): a client that still sends decryptionKid, validateCertificates or validateTimestamp is refused. decryptionKid belongs to the convert operations, where it names the decrypting recipient.
Every actor is reported. signers[] and recipients[] list each signer and each recipient in encoded order, and the number of either never makes a structure unsupported. For SignedAndEnvelopedData the signers are the outer signerInfos of RFC 2315 §11. A serialNumber is 0x followed by the upper-case hexadecimal of the serial's DER INTEGER content octets, as the certificate carries them (a serial whose first octet is 80-FF keeps its leading 00, for example 0x009F8E7D6C5B4A3B2C); matching uses the serial number itself, never this text.
What recommendations says:
| Member | Meaning |
|---|---|
migrationPath | The JOSE form a conversion under serialization AUTO produces, per structure: CONVERT_TO_JWS_* (SignedData), CONVERT_TO_JWE_* (EnvelopedData), CONVERT_TO_JWE_JWS_* (SignedAndEnvelopedData — a JWE whose plaintext is a JWS). The suffix is _COMPACT when the structure carries at most one signer and at most one recipient, _JSON (General JSON serialization, RFC 7515 §7.2.1 / RFC 7516 §7.2.1) otherwise. |
requiredKeys[] | One entry per actor: every signer (purpose signing), then every recipient (purpose encryption), each named by the issuerDN and serialNumber the tenant key's certificate must carry. Every one needs a key imported with its private key: a signer a key admissible to sign; the recipient that decrypts a key admissible to decrypt and encrypt; every other recipient a key admissible to encrypt (a keystore import with its private key, or the encryption key of a DUAL import). Current limitation: a certificate imported alone is a verify-only trust anchor and is admissible neither as a signer nor as a recipient. |
decryptionRequirement | Present for an encrypted structure, always ONE_RECIPIENT_PRIVATE_KEY: exactly one recipient's key opens the content — the one decryptionKid names, or else the first recipient in encoded order whose tenant key admits decryption and encryption. |
estimatedComplexity | LOW, MEDIUM or HIGH; HIGH whenever there is more than one signer or more than one recipient. |
What supportStatus says. Analysis runs every check a conversion runs without a key and reports each refusal with the conversion's own code, so supported is false exactly when the conversion would refuse the structure before any key is used. The reasons are listed in the order the conversion decides them, so the first ERROR reason is the refusal a conversion of the same bytes answers:
ERROR— the structure refusals. For aSignedData:INVALID_PKCS7, what the conversion answers400 invalid-pkcs7(no signer, or no encapsulated content). For aSignedAndEnvelopedData:UNSUPPORTED_CONTENT_ENCRYPTION(a content cipher other than AES-CBC or 3DES), thenSIGNED_AND_ENVELOPED_WITHOUT_SIGNER,UNSUPPORTED_SIGNED_AND_ENVELOPED_SIGNER_KEYandSIGNED_AND_ENVELOPED_DIGEST_NOT_ENCRYPTED.ERROR—ACTOR_LIMIT_EXCEEDED: more signers and recipients together than one conversion accepts. The bound is 16, and every analysis response states it inlimits.maxActors, the same value the conversion enforces — the way a client discovers the bound rather than hard-coding it.WARNING—LEGACY_ALGORITHM_REJECTED: a signer on SHA-1 or MD5, which the conversion refuses unlessalgorithmPolicy.allowLegacyHashistrue.INFO—TIMESTAMP_DETECTED: an RFC 3161 timestamp in a signer, reported and not validated.
Content-encryption parameters that encode a key size their RFC does not define are not a reason either: RC2/CAST5 parameters outside RFC 2268 §6 / RFC 2984 §2.1 (undefined effective key size, malformed CAST5 parameters) refuse the analysis itself 422 unsupported-pkcs7-format with errorCode UNSUPPORTED_CONTENT_ENCRYPTION, on every structure, EnvelopedData included, as they refuse every conversion parse. On the streaming analysis, a declared ASN.1 length above the structure budget (1 MiB) is refused 400 invalid-pkcs7 before it is allocated, with the body a malformed file receives.
A signer identified by SubjectKeyIdentifier rather than issuer and serial number is refused 422 unsupported-pkcs7-format with errorCode UNSUPPORTED_SIGNER_IDENTIFIER, and a recipient that is not RSA key transport named by issuer and serial number with UNSUPPORTED_RECIPIENT_TYPE — the analysis itself is refused, since those actors cannot be reported. The detail names the signer's index. For a recipient it names the index — "PKCS#7 recipient at index N is not a key-transport recipient named by issuer and serial number. Only KeyTransRecipientInfo (RSA) is supported." — for a key-transport recipient identified by SubjectKeyIdentifier on any structure and for every recipient refusal of a SignedAndEnvelopedData; for any other recipient of an EnvelopedData it names the index and the recipient's RecipientInfo alternative as RFC 5652 §6.2 names it (KeyAgreeRecipientInfo, KEKRecipientInfo, PasswordRecipientInfo; KEMRecipientInfo per RFC 9629; OtherRecipientInfo otherwise) — "PKCS#7 recipient at index 0 is a KeyAgreeRecipientInfo. Only KeyTransRecipientInfo (RSA) is supported."
Both responses below are complete: they carry every member the service returns for that case, including the null ones. Only certificatePEM is shortened, after its first base64 line.
Example response (complete — three signers):
{
"detectedFormat": {
"standard": "PKCS#7",
"structure": "SignedData",
"contentTypeOID": "1.2.840.113549.1.7.2",
"encoding": "BER",
"payloadEmbedded": true
},
"signers": [
{"index": 0, "issuerDN": "CN=Legacy Audit Signer,O=Example Corp,C=US", "serialNumber": "0x7E6D5C4B3A291807", "signatureAlgorithmOID": "1.2.840.10045.4.3.2", "signatureAlgorithm": "SHA256withECDSA", "digestAlgorithmOID": "2.16.840.1.101.3.4.2.1", "digestAlgorithm": "SHA-256", "certificatePresent": true, "certificatePEM": "-----BEGIN CERTIFICATE-----\nMIIBizCCATKgAwIBAgIIfm1cSzopGAcwCgYIKoZIzj0EAwIwQjELMAkGA1UEBhMC\n...\n-----END CERTIFICATE-----", "certificateChainLength": 1, "keyUsage": ["digitalSignature", "nonRepudiation"], "timestampPresent": false, "timestampTSA": null, "timestampGenTime": null},
{"index": 1, "issuerDN": "CN=Legacy Finance Signer,O=Example Corp,C=US", "serialNumber": "0x4A3F2E1D5B6C7A8B", "signatureAlgorithmOID": "1.2.840.113549.1.1.11", "signatureAlgorithm": "SHA256withRSA", "digestAlgorithmOID": "2.16.840.1.101.3.4.2.1", "digestAlgorithm": "SHA-256", "certificatePresent": true, "certificatePEM": "-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIISj8uHVtseoswDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE\n...\n-----END CERTIFICATE-----", "certificateChainLength": 1, "keyUsage": ["digitalSignature", "nonRepudiation"], "timestampPresent": false, "timestampTSA": null, "timestampGenTime": null},
{"index": 2, "issuerDN": "CN=Legacy Legal Signer,O=Example Corp,C=US", "serialNumber": "0x1B2C3D4E5F607182", "signatureAlgorithmOID": "1.2.840.113549.1.1.10", "signatureAlgorithm": "RSASSA-PSS", "digestAlgorithmOID": "2.16.840.1.101.3.4.2.1", "digestAlgorithm": "SHA-256", "certificatePresent": true, "certificatePEM": "-----BEGIN CERTIFICATE-----\nMIIDGDCCAgCgAwIBAgIIGyw9Tl9gcYIwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UE\n...\n-----END CERTIFICATE-----", "certificateChainLength": 1, "keyUsage": ["digitalSignature", "nonRepudiation"], "timestampPresent": false, "timestampTSA": null, "timestampGenTime": null}
],
"recipients": [],
"supportStatus": { "supported": true, "reasons": [] },
"recommendations": {
"migrationPath": "CONVERT_TO_JWS_JSON",
"requiredKeys": [
{"purpose": "signing", "issuerDN": "CN=Legacy Audit Signer,O=Example Corp,C=US", "serialNumber": "0x7E6D5C4B3A291807", "algorithm": "SHA256withECDSA", "importHint": "Use POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore to import the private key and certificate of this signer"},
{"purpose": "signing", "issuerDN": "CN=Legacy Finance Signer,O=Example Corp,C=US", "serialNumber": "0x4A3F2E1D5B6C7A8B", "algorithm": "SHA256withRSA", "importHint": "Use POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore to import the private key and certificate of this signer"},
{"purpose": "signing", "issuerDN": "CN=Legacy Legal Signer,O=Example Corp,C=US", "serialNumber": "0x1B2C3D4E5F607182", "algorithm": "RSASSA-PSS", "importHint": "Use POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore to import the private key and certificate of this signer"}
],
"estimatedComplexity": "HIGH"
},
"limits": { "maxActors": 16 }
}
Example response (complete — EnvelopedData, two recipients):
{
"detectedFormat": {
"standard": "PKCS#7",
"structure": "EnvelopedData",
"contentTypeOID": "1.2.840.113549.1.7.3",
"encoding": "BER",
"payloadEmbedded": true
},
"signers": [],
"recipients": [
{"index": 0, "issuerDN": "CN=Records Office,O=Example Corp,C=US", "serialNumber": "0x5A6B7C8D9E0F1021", "keyEncryptionAlgorithmOID": "1.2.840.113549.1.1.1", "keyEncryptionAlgorithm": "RSA", "certificatePresent": false, "certificatePEM": null},
{"index": 1, "issuerDN": "CN=Treasury Archive,O=Example Corp,C=US", "serialNumber": "0x2F4E6D8C0B1A3928", "keyEncryptionAlgorithmOID": "1.2.840.113549.1.1.1", "keyEncryptionAlgorithm": "RSA", "certificatePresent": false, "certificatePEM": null}
],
"encryption": { "contentEncryptionAlgorithmOID": "2.16.840.1.101.3.4.1.42", "contentEncryptionAlgorithm": "AES-256-CBC", "ivLength": 16 },
"supportStatus": { "supported": true, "reasons": [] },
"recommendations": {
"migrationPath": "CONVERT_TO_JWE_JSON",
"requiredKeys": [
{"purpose": "encryption", "issuerDN": "CN=Records Office,O=Example Corp,C=US", "serialNumber": "0x5A6B7C8D9E0F1021", "algorithm": "RSA", "importHint": "Use POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore to import the private key and certificate of this recipient (a certificate imported alone only verifies and is not admissible as a recipient)"},
{"purpose": "encryption", "issuerDN": "CN=Treasury Archive,O=Example Corp,C=US", "serialNumber": "0x2F4E6D8C0B1A3928", "algorithm": "RSA", "importHint": "Use POST /api/v3/admin/tenants/{tenantId}/keys/import-keystore to import the private key and certificate of this recipient (a certificate imported alone only verifies and is not admissible as a recipient)"}
],
"decryptionRequirement": "ONE_RECIPIENT_PRIVATE_KEY",
"estimatedComplexity": "HIGH"
},
"limits": { "maxActors": 16 }
}
See: PKCS#7 Conversion for complete workflow and conversion process.
Related Documentation
- API Reference - Complete endpoint documentation
- Convert Operations - Data re-encryption and signature conversion
- Planning & Assessment - Algorithm compatibility mapping
- Error Reference - one page per failure
typeURI; the decision matrices are delivered with a licensed deployment
Version: 3.0.0
Last Updated: 2025-12-24
Status: Production Ready