~~NOTOC~~
====== Scenario 5.2: Chain Validation ======
**Category:** [[.:start|Validation & Trust]] \\
**Complexity:** **** (High) \\
**Prerequisites:** Built certificate chain \\
**Estimated Time:** 15-20 minutes
----
===== Description =====
This scenario describes **complete validation of a certificate chain** according to RFC 5280. The validation checks:
* **Signature validity** - Each certificate signed by issuer
* **Time validity** - All certificates within validity period
* **Key Usage** - Permitted usage purposes
* **Path Length** - BasicConstraints pathLenConstraint
* **Policy Constraints** - Certificate policies
* **Name Constraints** - Permitted/excluded names
----
===== Workflow =====
flowchart TD
BUILD[Chain Building] --> SIG[Verify signature]
SIG --> TIME[Time validity]
TIME --> KU[Key Usage]
KU --> PATH[Path Length]
PATH --> POLICY[Policy Constraints]
POLICY --> NAME[Name Constraints]
NAME --> REV[Revocation Check]
REV --> OK{All OK?}
OK -->|Yes| VALID[Certificate valid]
OK -->|No| INVALID[Certificate invalid]
style VALID fill:#e8f5e9
style INVALID fill:#ffebee
----
===== Code Example (C#) =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography.X509Certificates;
using var ctx = PqCryptoContext.Initialize();
// Load certificate
var serverCert = ctx.LoadCertificate("server.crt.pem");
// Complete chain validation
var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.UrlRetrievalTimeout = TimeSpan.FromSeconds(30);
chain.ChainPolicy.VerificationTime = DateTime.UtcNow;
// Additional intermediate certificates
chain.ChainPolicy.ExtraStore.Add(ctx.LoadCertificate("intermediate-ca.crt.pem"));
// Build and validate chain
bool isValid = chain.Build(serverCert);
// Evaluate result
Console.WriteLine($"Chain validation: {(isValid ? "VALID" : "INVALID")}");
if (!isValid)
{
foreach (var element in chain.ChainElements)
{
foreach (var status in element.ChainElementStatus)
{
Console.WriteLine($" {element.Certificate.Subject}");
Console.WriteLine($" Error: {status.Status}");
Console.WriteLine($" Details: {status.StatusInformation}");
}
}
}
----
===== Detailed Validation =====
public class ChainValidator
{
public ValidationResult ValidateChain(X509Certificate2 certificate, ValidationOptions options)
{
var result = new ValidationResult { IsValid = true };
using var chain = new X509Chain();
ConfigureChainPolicy(chain.ChainPolicy, options);
if (!chain.Build(certificate))
{
result.IsValid = false;
result.Errors = ExtractErrors(chain);
}
// Additional PQ checks
if (options.RequirePostQuantum)
{
ValidatePqRequirements(chain, result);
}
return result;
}
private void ConfigureChainPolicy(X509ChainPolicy policy, ValidationOptions options)
{
policy.RevocationMode = options.CheckRevocation
? X509RevocationMode.Online
: X509RevocationMode.NoCheck;
policy.RevocationFlag = X509RevocationFlag.EntireChain;
policy.VerificationTime = options.ValidationTime ?? DateTime.UtcNow;
// Application Policies (Extended Key Usage)
if (options.RequiredEku != null)
{
policy.ApplicationPolicy.Add(options.RequiredEku);
}
// Certificate Policies
if (options.RequiredPolicies != null)
{
foreach (var policyOid in options.RequiredPolicies)
{
policy.CertificatePolicy.Add(policyOid);
}
}
// Custom Trust Store
if (options.CustomTrustStore != null)
{
policy.CustomTrustStore.AddRange(options.CustomTrustStore);
policy.TrustMode = X509ChainTrustMode.CustomRootTrust;
}
}
private void ValidatePqRequirements(X509Chain chain, ValidationResult result)
{
foreach (var element in chain.ChainElements)
{
var cert = element.Certificate;
var algorithm = cert.PublicKey.Oid.Value;
// Check if PQ algorithm is used
if (!IsPqAlgorithm(algorithm))
{
result.Warnings.Add($"{cert.Subject}: No PQ algorithm ({algorithm})");
}
}
}
private bool IsPqAlgorithm(string oid)
{
return oid switch
{
"2.16.840.1.101.3.4.3.17" => true, // ML-DSA-44
"2.16.840.1.101.3.4.3.18" => true, // ML-DSA-65
"2.16.840.1.101.3.4.3.19" => true, // ML-DSA-87
_ => false
};
}
}
----
===== Validation Options =====
public class ValidationOptions
{
// Validation time
public DateTime? ValidationTime { get; set; }
// Revocation check
public bool CheckRevocation { get; set; } = true;
// Extended Key Usage
public Oid? RequiredEku { get; set; }
// Certificate Policies
public List? RequiredPolicies { get; set; }
// Custom Trust Store
public X509Certificate2Collection? CustomTrustStore { get; set; }
// PQ requirements
public bool RequirePostQuantum { get; set; }
// Timeout for online checks
public TimeSpan UrlTimeout { get; set; } = TimeSpan.FromSeconds(30);
}
// Example: TLS server validation
var tlsOptions = new ValidationOptions
{
RequiredEku = new Oid("1.3.6.1.5.5.7.3.1"), // serverAuth
CheckRevocation = true,
RequirePostQuantum = true
};
// Example: Code signing validation
var codeSigningOptions = new ValidationOptions
{
RequiredEku = new Oid("1.3.6.1.5.5.7.3.3"), // codeSigning
CheckRevocation = true,
ValidationTime = signatureTimestamp // Time of signature
};
----
===== Chain Status Codes =====
^ Status ^ Meaning ^ Critical? ^ Solution ^
| **NoError** | No errors | No | - |
| **NotTimeValid** | Expired/not yet valid | Yes | Renewal |
| **NotTimeNested** | Time periods don't overlap | Yes | Correct chain |
| **Revoked** | Revoked | Yes | New certificate |
| **NotSignatureValid** | Signature invalid | Yes | Check chain |
| **NotValidForUsage** | Wrong usage purpose | Yes | Correct certificate |
| **UntrustedRoot** | Root not trusted | Yes | Trust Store |
| **RevocationStatusUnknown** | CRL/OCSP unreachable | Warning | Offline check |
| **PartialChain** | Chain incomplete | Yes | Add intermediates |
----
===== Industry-Specific Validation =====
^ Industry ^ Additional Checks ^ Policy OIDs ^
| **WebPKI** | CT Logs, EV Policies | CA/B Forum |
| **eIDAS** | QC Statements, TSL Check | 0.4.0.194121.1.* |
| **Healthcare** | Professional attributes | gematik OIDs |
| **Automotive** | ECU Policies | V2X-specific |
----
===== Related Scenarios =====
^ Relationship ^ Scenario ^ Description ^
| **Prerequisite** | [[.:chain_building|5.1 Chain Building]] | Build chain |
| **Next Step** | [[.:revocation_check|5.3 Revocation Check]] | Revocation verification |
| **Related** | [[.:policy_validation|5.4 Policy Validation]] | Policy verification |
----
<< [[.:chain_building|<- 5.1 Chain Building]] | [[.:start|^ Validation Overview]] | [[.:revocation_check|5.3 Revocation Check ->]] >>
{{tag>scenario validation chain x509 rfc5280}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//