CNSA 2.0 Validator — Compliance Validation Engine
The CNSA 2.0 Validator is the compliance verification engine that evaluates cryptographic assets (CBOMs) against the NSA's Commercial National Security Algorithm Suite 2.0 (CNSA 2.0) requirements. It produces binary verdicts, per-asset classifications, gap analyses, and timeline-aware roadmaps — all driven by Knowledge Base profiles.
Table of Contents
- What It Does
- Why It's Needed
- Architecture Overview
- Installation
- How to Run / Use
- User Manual
- Developer Manual
- Code Examples
- API Reference
- Configuration Options
- Value Showcase
What It Does
The CNSA 2.0 Validator takes a CBOM (Cryptography Bill of Materials) and evaluates every cryptographic asset against the CNSA 2.0 profile:
| Capability | Description |
|---|---|
| Profile Factory | CnsaProfileFactory programmatically defines the CNSA 2.0 profile as KB-encoded data — no hardcoded checks |
| Validator Engine | CnsaValidator iterates all CBOM components and classifies each asset |
| Per-Asset Verdicts | Each asset receives a Compliant, NonCompliant, or Indeterminate verdict with detailed reasoning |
| Gap Analysis | Non-compliant and indeterminate assets generate CnsaGapItem entries with requirements, deadlines, and recommended actions |
| Timeline Awareness | Validates against CNSA 2.0's phased deadlines: Procurement (2027), Key Establishment (2030), General Phase-Out (2033), NSM-10 Goal (2035) |
| Fail-Safe for Unknown Algorithms | Any algorithm not recognized by the Knowledge Base yields Indeterminate — never a silent pass |
| Low-Confidence Flagging | Assets detected with Low confidence are flagged separately for manual review |
| Reproducible Evidence | Each validation run produces a CnsaEvidence record for audit trails |
| Certificate Validation | Validates certificate signing algorithms against CNSA 2.0 requirements |
| Parameter Set Checking | Enforces CNSA 2.0 minimum parameter sets: ML-KEM-1024 (not 512/768), ML-DSA-87 (not 44/65), AES-256 (not 128/192) |
CNSA 2.0 Approved Algorithms
| Algorithm | Role | FIPS Standard | Status |
|---|---|---|---|
| ML-KEM-1024 | Key Encapsulation | FIPS 203 | ✅ Required |
| ML-DSA-87 | Digital Signature | FIPS 204 | ✅ Required |
| AES-256 | Symmetric Encryption | FIPS 197 | ✅ Required |
| SHA-384 | Hash | FIPS 180-4 | ✅ Approved |
| SHA-512 | Hash | FIPS 180-4 | ✅ Approved |
| LMS | Firmware/Software Signing | NIST SP 800-208 | ✅ Approved |
| XMSS | Firmware/Software Signing | NIST SP 800-208 | ✅ Approved |
Why It's Needed
The Problem
National Security Systems (NSS) and organizations handling classified or sensitive data must comply with CNSA 2.0 timelines:
- 2027: All new software/firmware signing must use CNSA 2.0
- 2030: All new key establishment must transition to quantum-safe
- 2033: All remaining systems must be migrated
- 2035: NSM-10 full compliance goal
Without automated validation:
- Manual code reviews miss cryptographic assets buried in dependencies
- Teams don't know which algorithms they need to migrate and by when
- Unknown algorithms (e.g., from third-party libraries) silently pass reviews
- Parameter set violations (using ML-KEM-768 instead of ML-KEM-1024) go undetected
- There's no reproducible evidence of compliance status for auditors
The Value Proposition
| Stakeholder | Benefit |
|---|---|
| ISSOs / ISSMs | Binary compliant/non-compliant verdict with evidence suitable for RMF packages |
| System Architects | Gap analysis shows exactly which assets need migration, why, and by when |
| Developers | Per-asset verdicts with recommended PQC targets — no crypto expertise required |
| Compliance Officers | CNSA 2.0 timeline awareness with phased deadline tracking |
| Auditors | Reproducible evidence. Run the same CBOM through the validator — same result every time. |
The CNSA 2.0 Validator turns a 200-page advisory into an automated, per-asset compliance decision that runs in milliseconds.
Architecture Overview
Verdict Decision Tree
For each CBOM component:
│
├── Asset is a Certificate?
│ ├── Signature algo is RSA/ECDSA/DSA? → NonCompliant
│ └── Otherwise → Compliant
│
├── Algorithm is in CNSA 2.0 approved list?
│ ├── Parameter check: meets ML-KEM-1024/ML-DSA-87/AES-256 minimum?
│ │ ├── Yes → Compliant (with low-confidence flag if applicable)
│ │ └── No → NonCompliant (parameter set too low)
│ └── Not in approved list
│
├── Algorithm is known to be CNSA-excluded?
│ └── NonCompliant (excluded: RSA, ECDSA, SLH-DSA, DES, MD5, low param sets)
│
├── Algorithm is known in KB (but not CNSA-approved)?
│ └── NonCompliant (known, needs review)
│
└── Algorithm is completely unknown to KB?
└── Indeterminate (FAIL-SAFE: never a silent pass)
Installation
The CNSA 2.0 Validator is part of CipherShift365.Core.Analysis:
dotnet add package CipherShift365.Core.Analysis
<PackageReference Include="CipherShift365.Core.Analysis" Version="1.0.0" />
Dependencies
CipherShift365.Core.Analysis
├── CipherShift365.Core.Runtime (KB types, contracts, CBOM model)
├── Microsoft.CodeAnalysis.CSharp (Roslyn source analysis)
├── Microsoft.CodeAnalysis.CSharp.Workspaces
└── Microsoft.Extensions.Logging.Abstractions
Targets net10.0.
How to Run / Use
Quick Start: Validate a CBOM
using CipherShift365.Core.Runtime;
using CipherShift365.Core.Analysis;
using CipherShift365.Core.Analysis.Cnsa;
// 1. Load the Knowledge Base
var loader = new KbLoader(encryptionKey, signingKey);
var result = loader.Load(File.ReadAllBytes("kb.cskb"));
var kb = new SignedKnowledgeBase(result.Content!);
// 2. Create the CNSA 2.0 profile
var (profile, entries, timeline) = CnsaProfileFactory.Create();
// 3. Run an analysis to produce a CBOM (or load one)
var analysisEngine = new AnalysisEngine(new RiskModel());
var ctx = new AnalysisContext("./src/MyApp", kb, new IdentityService());
var analysis = await analysisEngine.AnalyzeAsync(ctx);
// 4. Validate against CNSA 2.0
var validator = new CnsaValidator(kb, profile, timeline);
var validationResult = validator.Validate(analysis.Cbom!);
// 5. Inspect the results
Console.WriteLine($"Overall: {validationResult.OverallVerdict}");
Console.WriteLine(validationResult.Summary);
Standalone Validation
// If you already have a CBOM (e.g., from a file)
var cbom = CbomSerializer.Deserialize<Cbom>(json);
var (profile, _, timeline) = CnsaProfileFactory.Create();
var validator = new CnsaValidator(kb, profile, timeline);
var result = validator.Validate(cbom);
// Check the verdict
if (result.OverallVerdict == CnsaVerdict.Compliant)
Console.WriteLine("PASS: All crypto assets are CNSA 2.0 compliant.");
else if (result.OverallVerdict == CnsaVerdict.NonCompliant)
Console.WriteLine($"FAIL: {result.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.NonCompliant)} non-compliant assets.");
else
Console.WriteLine($"INDETERMINATE: {result.IndeterminateCount} assets need manual review.");
User Manual
Understanding the Verdicts
Compliant
The algorithm is on the CNSA 2.0 approved list and meets all parameter set requirements. Example:
Algorithm: ML-KEM-1024
Verdict: Compliant
Reason: Algorithm 'ML-KEM-1024' is CNSA 2.0 approved for Key Establishment.
NonCompliant
The algorithm is known and explicitly not compliant. Examples:
Algorithm: RSA
Verdict: NonCompliant
Reason: Algorithm 'RSA' is NOT CNSA 2.0 approved.
Requirement: CNSA 2.0 algorithm approval
Deadline: 2033-01-01
PqcTarget: ML-DSA-87
Algorithm: ML-KEM-768
Verdict: NonCompliant
Reason: ML-KEM variant is CNSA 2.0 approved but parameter set 'ML-KEM-768' is too low.
Requirement: CNSA 2.0: parameter set minimum
PqcTarget: ML-KEM-1024
Indeterminate (Fail-Safe)
The algorithm is not recognized by the Knowledge Base. The validator refuses to pass it. Example:
Algorithm: CustomCryptoV3
Verdict: Indeterminate
Reason: Algorithm 'CustomCryptoV3' is not recognized — manual review required.
Requirement: CNSA 2.0: unclassified algorithm
This is a critical security property: unknown does not mean safe. An attacker who introduces a novel or obfuscated algorithm cannot hide behind a silent pass.
CNSA 2.0 Timeline
| Milestone | Deadline | Description |
|---|---|---|
| Procurement Gate | 2027-01-01 | All new software/firmware signing must use CNSA 2.0 approved algorithms |
| Key Establishment | 2030-01-01 | All new key establishment (KEM) must transition to ML-KEM-1024 |
| General Phase-Out | 2033-01-01 | All remaining systems must be migrated to CNSA 2.0 |
| NSM-10 Goal | 2035-01-01 | NSM-10 National Security Systems full compliance |
The validator maps each asset to its relevant deadline based on its cryptographic role:
- Signature assets → Procurement Gate (2027)
- Key Establishment assets → Key Establishment deadline (2030)
- All others → General Phase-Out (2033)
Gap Analysis Output
Each non-compliant asset generates a CnsaGapItem:
foreach (var gap in result.Gaps)
{
Console.WriteLine($"Asset: {gap.AssetIdentifier}");
Console.WriteLine($" Algorithm: {gap.Algorithm}");
Console.WriteLine($" Gap: {gap.GapDescription}");
Console.WriteLine($" Requirement: {gap.Requirement}");
Console.WriteLine($" Action: {gap.RecommendedAction}");
Console.WriteLine($" Deadline: {gap.Deadline}");
}
This bridges the gap from "we're non-compliant" to "here's exactly what to fix, by when, and how."
Low-Confidence Flagging
When the analysis engine detects a crypto asset with Low confidence, the CNSA Validator flags it:
Algorithm: ML-KEM-1024
Verdict: Compliant
Reason: Algorithm 'ML-KEM-1024' is CNSA 2.0 approved for Key Establishment. [FLAGGED: low-confidence finding — verify manually]
The CnsaValidationResult includes LowConfidenceFlaggedCount so you can track how many assets need manual verification even if they pass automated checks.
Developer Manual
Class Hierarchy
CnsaProfileFactory (static)
├── ProfileName: "CNSA 2.0"
├── ProfileVersion: "2024-09"
├── ProfileSource: "CNSSP-15 Annex B / NSA CNSA 2.0 Advisory"
└── Create() → (ComplianceProfile, IReadOnlyList<KbEntry>, IReadOnlyList<CnsaTimelineEntry>)
CnsaValidator
├── Constructor: IKnowledgeBase, ComplianceProfile, IReadOnlyList<CnsaTimelineEntry>
├── Validate(Cbom) → CnsaValidationResult
├── (private) ComputeOverallVerdict()
├── (private) EvaluateAsset() → AssetEvaluation
├── (private) EvaluateCertificate() → AssetEvaluation
├── (private) CheckParameters() → (verdict, reason, requirement)
├── (private) IsCnsaExcluded() → bool
├── (private) MapAlgorithmToRole() → string
├── (private) GetRelevantDeadline() → string?
├── (private) GetPqcTarget() → string?
└── (private) GetRecommendedAction() → string?
CnsaValidationResult (record)
├── OverallVerdict: CnsaVerdict
├── AssetVerdicts: IReadOnlyList<CnsaAssetVerdict>
├── Gaps: IReadOnlyList<CnsaGapItem>
├── Evidence: CnsaEvidence
├── Timeline: IReadOnlyList<CnsaTimelineEntry>
├── Summary: string
├── IndeterminateCount: int
└── LowConfidenceFlaggedCount: int
CnsaAssetVerdict (record)
├── AssetIdentifier, Algorithm, Verdict, Reason
└── Requirement?, Deadline?, Confidence?, PqcTarget?
CnsaGapItem (record)
├── AssetIdentifier, Algorithm, GapDescription, Requirement
└── RecommendedAction?, Deadline?
CnsaEvidence (record)
├── ProfileName, ProfileVersion, KbVersion
├── EvaluatedAt, DrivingAssets, ProfileSource
CnsaTimelineEntry (record)
├── Category, Deadline, Description
CnsaVerdict (enum)
├── Compliant
├── NonCompliant
└── Indeterminate
The Validation Algorithm (Detailed)
Validate(Cbom cbom):
assetVerdicts = []
gaps = []
drivingAssets = []
indeterminateCount = 0
lowConfidenceCount = 0
for each component in cbom.Components:
if component.CryptoProperties is null → skip (not a crypto asset)
assetId = component.BomRef ?? component.Name
algorithm = component.Name
confidence = extract from component.Properties (CipherShiftAnnotations.PropConfidence)
if confidence == Low → lowConfidenceCount++
eval = EvaluateAsset(algorithm, cryptoProperties, confidence)
if eval.IsIndeterminate → indeterminateCount++
deadline = GetRelevantDeadline(cryptoProperties) // Timelines-aware
pqcTarget = GetPqcTarget(algorithm)
assetVerdicts += new CnsaAssetVerdict(assetId, algorithm, eval.Verdict, eval.Reason,
eval.Requirement, deadline, confidence, pqcTarget)
if eval.Verdict != Compliant:
gaps += new CnsaGapItem(assetId, algorithm, eval.Reason, eval.Requirement,
GetRecommendedAction(algorithm, cryptoProperties), deadline)
overallVerdict = ComputeOverallVerdict(assetVerdicts)
// NonCompliant > Indeterminate > Compliant (worst-case wins)
evidence = new CnsaEvidence(profile.Name, profile.Version, kb.Version,
UtcNow, drivingAssets, CnsaProfileFactory.ProfileSource)
return new CnsaValidationResult(overallVerdict, assetVerdicts, gaps, evidence,
timeline, summary, indeterminateCount, lowConfidenceCount)
Fail-Safe Implementation
The critical fail-safe is the last branch of EvaluateAsset:
// If algorithm is not in approved list, not excluded, and not in KB:
return new AssetEvaluation(CnsaVerdict.Indeterminate,
$"Algorithm '{algorithm}' is not recognized — manual review required.",
"CNSA 2.0: unclassified algorithm", isIndeterminate: true);
There is no code path that returns Compliant for an unrecognized algorithm. This prevents:
- Novel attacks using custom crypto implementations
- Typos or mis-identified algorithms slipping through
- New NIST finalists that haven't been added to the KB yet (they'll be flagged, not silently approved)
The IsIndeterminate flag on AssetEvaluation is used for counting but does not affect verdict computation — all indeterminate assets are counted and included in the summary.
Overall Verdict Computation
static CnsaVerdict ComputeOverallVerdict(IReadOnlyList<CnsaAssetVerdict> assets)
{
if (assets.Count == 0) return CnsaVerdict.Compliant;
if (assets.Any(a => a.Verdict == CnsaVerdict.NonCompliant)) return CnsaVerdict.NonCompliant;
if (assets.Any(a => a.Verdict == CnsaVerdict.Indeterminate)) return CnsaVerdict.Indeterminate;
return CnsaVerdict.Compliant;
}
Priority: NonCompliant > Indeterminate > Compliant. One non-compliant asset makes the entire system non-compliant.
Adding a New CNSA-Excluded Algorithm
// In CnsaValidator.IsCnsaExcluded(), add a new case:
private static bool IsCnsaExcluded(string algorithm)
{
var upper = algorithm.ToUpperInvariant();
return upper switch
{
// ... existing cases ...
var a when a.StartsWith("CHACHA", StringComparison.Ordinal) => true, // NEW
_ => false
};
}
// Add the corresponding KB entry in CnsaProfileFactory.Create()
new("ChaCha20", CryptoRole.Symmetric, RiskLevel.QuantumVulnerable,
Description: "Not CNSA 2.0 approved. Use AES-256.",
StandardsReferences: new[] { "CNSA 2.0" },
MigrationNotes: "Replace with AES-256-GCM.")
Data-Driven Design
All CNSA 2.0 rules are defined in CnsaProfileFactory.Create(), not hardcoded in the validator:
// ✅ Data-driven: the approved list is in the KB profile
var profile = new ComplianceProfile("CNSA 2.0", "2024-09",
new[] { "ML-KEM-1024", "ML-DSA-87", "AES-256", "SHA-384", "SHA-512", "LMS", "XMSS" },
RiskLevel.QuantumSafe);
// ❌ Anti-pattern avoided: no hardcoded lists in the validator
// if (algo == "ML-KEM-1024" || algo == "ML-DSA-87") ...
This means updating the CNSA guidance requires updating the KB, not the validator code.
Thread Safety
CnsaValidatoris stateless after construction. Thread-safe for concurrentValidate()calls.CnsaProfileFactory.Create()is a static method with no side effects. Thread-safe.- All result types (
CnsaValidationResult,CnsaAssetVerdict,CnsaGapItem,CnsaEvidence) are immutable records.
Code Examples
Example 1: Full Compliance Pipeline
// Build the CNSA 2.0 profile
var (profile, entries, timeline) = CnsaProfileFactory.Create();
// Run analysis to produce a CBOM
var kb = new SignedKnowledgeBase(content);
var engine = new AnalysisEngine(new RiskModel());
var context = new AnalysisContext("./src", kb, new IdentityService());
var analysis = await engine.AnalyzeAsync(context);
// Validate
var validator = new CnsaValidator(kb, profile, timeline);
var result = validator.Validate(analysis.Cbom!);
// Print results
Console.WriteLine($"CNSA 2.0 Validation: {result.OverallVerdict}");
Console.WriteLine(result.Summary);
Console.WriteLine($" Compliant: {result.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.Compliant)}");
Console.WriteLine($" Non-Compliant: {result.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.NonCompliant)}");
Console.WriteLine($" Indeterminate: {result.IndeterminateCount}");
Console.WriteLine($" Low Confidence: {result.LowConfidenceFlaggedCount}");
if (result.Gaps.Count > 0)
{
Console.WriteLine("\n--- GAP ANALYSIS ---");
foreach (var gap in result.Gaps)
Console.WriteLine($" [{gap.Deadline ?? "N/A"}] {gap.AssetIdentifier}: {gap.GapDescription}");
}
Console.WriteLine("\n--- TIMELINE ---");
foreach (var t in result.Timeline)
Console.WriteLine($" {t.Deadline:yyyy-MM-dd} — {t.Category}: {t.Description}");
Example 2: Per-Asset Migration Roadmap
var result = validator.Validate(cbom);
Console.WriteLine("=== CNSA 2.0 Migration Roadmap ===\n");
// Sort non-compliant assets by deadline
var needsMigration = result.AssetVerdicts
.Where(a => a.Verdict != CnsaVerdict.Compliant)
.OrderBy(a => a.Deadline);
foreach (var asset in needsMigration)
{
Console.WriteLine($"📦 {asset.AssetIdentifier}");
Console.WriteLine($" Algorithm: {asset.Algorithm}");
Console.WriteLine($" Verdict: {asset.Verdict}");
Console.WriteLine($" Reason: {asset.Reason}");
Console.WriteLine($" Migrate to: {asset.PqcTarget ?? "manual review needed"}");
Console.WriteLine($" Deadline: {asset.Deadline ?? "unknown"}");
Console.WriteLine();
}
// Summary for leadership
var byDeadline = needsMigration.GroupBy(a => a.Deadline);
Console.WriteLine("=== SUMMARY BY DEADLINE ===");
foreach (var group in byDeadline.OrderBy(g => g.Key))
Console.WriteLine($" {group.Key ?? "unknown"}: {group.Count()} assets");
Example 3: API Endpoint (Portal)
[HttpGet("cnsa/verdict")]
public async Task<IActionResult> GetCnsaVerdict([FromQuery] string project)
{
// Load KB
var kb = LoadKb();
var (profile, _, timeline) = CnsaProfileFactory.Create();
// Run analysis
var engine = new AnalysisEngine(new RiskModel());
var ctx = new AnalysisContext(project, kb, new IdentityService());
var analysis = await engine.AnalyzeAsync(ctx);
if (analysis.Cbom is null)
return BadRequest("Analysis produced no CBOM.");
// Validate
var validator = new CnsaValidator(kb, profile, timeline);
var result = validator.Validate(analysis.Cbom);
return Ok(new
{
overallVerdict = result.OverallVerdict.ToString(),
compliant = result.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.Compliant),
nonCompliant = result.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.NonCompliant),
indeterminate = result.IndeterminateCount,
summary = result.Summary,
gaps = result.Gaps.Select(g => new
{
g.AssetIdentifier, g.Algorithm, g.GapDescription,
g.Requirement, g.RecommendedAction, g.Deadline
}),
timeline = result.Timeline
});
}
Example 4: CI/CD Gate Integration
// Fail the build if CNSA 2.0 validation fails
var result = validator.Validate(cbom);
if (result.OverallVerdict != CnsaVerdict.Compliant)
{
Console.Error.WriteLine("=== CNSA 2.0 VALIDATION FAILED ===");
Console.Error.WriteLine(result.Summary);
foreach (var gap in result.Gaps)
Console.Error.WriteLine($" GAP: {gap.AssetIdentifier} — {gap.RecommendedAction}");
Environment.Exit(1); // Fail the build
}
Console.WriteLine("CNSA 2.0 validation passed.");
Example 5: Custom Profile Comparison
// Compare CNSA 2.0 against a hypothetical future profile
var (cnsaProfile, _, cnsaTimeline) = CnsaProfileFactory.Create();
var (customProfile, customEntries, customTimeline) = MyProfileFactory.Create();
var cnsaValidator = new CnsaValidator(kb, cnsaProfile, cnsaTimeline);
var customValidator = new CnsaValidator(kb, customProfile, customTimeline);
var cnsaResult = cnsaValidator.Validate(cbom);
var customResult = customValidator.Validate(cbom);
// Assets that pass CNSA but fail the stricter profile
var additionalFailures = customResult.AssetVerdicts
.Where(c => c.Verdict != CnsaVerdict.Compliant)
.Where(c => !cnsaResult.AssetVerdicts
.Any(n => n.AssetIdentifier == c.AssetIdentifier && n.Verdict != CnsaVerdict.Compliant));
Console.WriteLine($"CNSA 2.0 violations: {cnsaResult.AssetVerdicts.Count(a => a.Verdict == CnsaVerdict.NonCompliant)}");
Console.WriteLine($"Additional custom violations: {additionalFailures.Count()}");
API Reference
CnsaProfileFactory (Static)
| Member | Type | Description |
|---|---|---|
ProfileName |
const string |
"CNSA 2.0" |
ProfileVersion |
const string |
"2024-09" |
ProfileSource |
const string |
"CNSSP-15 Annex B / NSA CNSA 2.0 Advisory" |
Create() |
Static Method | Returns (ComplianceProfile, IReadOnlyList<KbEntry>, IReadOnlyList<CnsaTimelineEntry>) — the profile, KB entries, and timeline |
CnsaValidator
| Member | Type | Description |
|---|---|---|
CnsaValidator(IKnowledgeBase, ComplianceProfile, IReadOnlyList<CnsaTimelineEntry>) |
Constructor | Creates a validator. Profile and timeline from CnsaProfileFactory.Create(). |
Validate(Cbom) |
Method | Validates a CBOM. Returns CnsaValidationResult. |
CnsaValidationResult
| Property | Type | Description |
|---|---|---|
OverallVerdict |
CnsaVerdict |
Aggregate verdict (worst-case: NonCompliant > Indeterminate > Compliant) |
AssetVerdicts |
IReadOnlyList<CnsaAssetVerdict> |
Per-asset detailed verdicts |
Gaps |
IReadOnlyList<CnsaGapItem> |
Gap analysis for all non-compliant/indeterminate assets |
Evidence |
CnsaEvidence |
Reproducible validation evidence |
Timeline |
IReadOnlyList<CnsaTimelineEntry> |
CNSA 2.0 phased deadlines |
Summary |
string |
Human-readable summary (e.g., "CNSA 2.0 Validation: NonCompliant. 3 compliant, 2 non-compliant, 1 indeterminate. 3 gaps identified. 1 low-confidence finding(s) flagged.") |
IndeterminateCount |
int |
Number of assets with indeterminate verdicts |
LowConfidenceFlaggedCount |
int |
Number of assets with low-confidence detection |
CnsaVerdict (Enum)
| Value | Description |
|---|---|
Compliant |
Asset meets all CNSA 2.0 requirements |
NonCompliant |
Asset is known and does not meet CNSA 2.0 requirements |
Indeterminate |
Asset is unknown — fail-safe. Manual review required. |
CnsaAssetVerdict
| Property | Type | Description |
|---|---|---|
AssetIdentifier |
string |
CBOM component BomRef or name |
Algorithm |
string |
Algorithm name |
Verdict |
CnsaVerdict |
Compliant, NonCompliant, or Indeterminate |
Reason |
string |
Detailed explanation of the verdict |
Requirement |
string? |
CNSA 2.0 requirement being evaluated |
Deadline |
string? |
Relevant CNSA 2.0 deadline (ISO date) |
Confidence |
Confidence? |
Detection confidence (from analysis) |
PqcTarget |
string? |
Recommended PQC migration target |
CnsaGapItem
| Property | Type | Description |
|---|---|---|
AssetIdentifier |
string |
Which asset has the gap |
Algorithm |
string |
Which algorithm |
GapDescription |
string |
What the gap is |
Requirement |
string |
What requirement is not met |
RecommendedAction |
string? |
What to do about it |
Deadline |
string? |
When it must be addressed |
CnsaEvidence
| Property | Type | Description |
|---|---|---|
ProfileName |
string |
"CNSA 2.0" |
ProfileVersion |
string |
"2024-09" |
KbVersion |
KbVersion |
KB version used for validation |
EvaluatedAt |
DateTimeOffset |
When validation ran |
DrivingAssets |
IReadOnlyList<string> |
Asset identifiers driving the evaluation |
ProfileSource |
string |
Authority document reference |
CnsaTimelineEntry
| Property | Type | Description |
|---|---|---|
Category |
string |
Milestone category (e.g., "ProcurementGate", "KeyEstablishment") |
Deadline |
DateTimeOffset |
Compliance deadline |
Description |
string |
Human-readable requirement |
Configuration Options
Profile Selection
// Default CNSA 2.0 profile
var (profile, entries, timeline) = CnsaProfileFactory.Create();
// Or use a custom profile from the KB
var customProfile = kb.ComplianceProfiles.First(p => p.Name == "Custom Profile");
var validator = new CnsaValidator(kb, customProfile, myTimeline);
KB Version Management
The validator records which KB version was used:
var evidence = result.Evidence;
Console.WriteLine($"Validated with KB v{evidence.KbVersion} (profile v{evidence.ProfileVersion})");
// Store evidence for auditors
File.WriteAllText("cnsa-evidence.json", JsonSerializer.Serialize(evidence));
Custom Timeline
You can provide a custom timeline instead of the CNSA 2.0 defaults:
var customTimeline = new[]
{
new CnsaTimelineEntry("InternalGate", new DateTimeOffset(2026, 6, 1, 0, 0, 0, TimeSpan.Zero),
"Internal PQC migration deadline."),
new CnsaTimelineEntry("ExternalGate", new DateTimeOffset(2028, 1, 1, 0, 0, 0, TimeSpan.Zero),
"Customer-facing PQC requirement."),
};
var validator = new CnsaValidator(kb, cnsaProfile, customTimeline);
Confidence Thresholds
The validator currently flags all Low confidence findings. For stricter handling:
// Custom wrapper that treats Low-confidence as failures
public static class StrictCnsaValidator
{
public static CnsaValidationResult ValidateStrict(CnsaValidator inner, Cbom cbom)
{
var result = inner.Validate(cbom);
if (result.LowConfidenceFlaggedCount > 0)
{
// Optionally promote low-confidence to failures
// Currently, low-confidence findings are flagged but don't change the overall verdict
// This is a policy choice you can implement in a wrapper
}
return result;
}
}
Integration Points
| Integration | How |
|---|---|
| Compass CLI | compass cnsa --profile CNSA.2.0 --project . |
| Guardian Gate | Embedded in CI/CD pipeline — fail build on NonCompliant |
| Portal API | GET /v1/cnsa/verdict?project=./src — returns verdict + gaps + timeline |
| PDF Reports | CNSA verdict drives color-coded summary pages in branded PDFs |
| Custom scripts | CnsaValidator is a standalone class — use in any .NET console app |
Value Showcase
Before CNSA 2.0 Validator
Q: "Are our 15 microservices CNSA 2.0 compliant?"
A: "We cross-referenced our crypto inventory against the advisory.
It took 2 analysts 3 weeks. The spreadsheet is on SharePoint somewhere.
Also, we're not sure about the third-party libraries."
Risk: HIGH — manual, slow, incomplete, not reproducible
After CNSA 2.0 Validator
Q: "Are our 15 microservices CNSA 2.0 compliant?"
A: "Ran Compass with CNSA 2.0 profile across all repos.
12 are Compliant. 2 have NonCompliant assets (RSA in legacy modules).
1 has Indeterminate (unknown NuGet crypto).
Gap analysis with deadlines and migration targets attached.
Evidence timestamped and signed.
Total time: 4 seconds."
Risk: LOW — automated, complete, reproducible with evidence
Quantitative Impact
| Metric | Without Validator | With CNSA 2.0 Validator |
|---|---|---|
| Per-project compliance evaluation time | ~2 days (manual) | <1 second |
| Coverage | Sampled (cannot review every asset) | Every crypto asset in the CBOM |
| Unknown algorithm detection | Manual guesswork | Automatic fail-safe (Indeterminate) |
| Parameter set checking | Requires crypto expertise | Automatic (ML-KEM-1024 vs 768) |
| Audit evidence | Manual spreadsheets | Machine-verifiable CnsaEvidence record |
| Timeline tracking | Spreadsheet column | Automatic deadline mapping per asset |
Example: Real Compliance Scenario
Organization: Government contractor managing 50 .NET microservices with 340 cryptographic assets.
| Asset Type | Count | Compliant | NonCompliant | Indeterminate |
|---|---|---|---|---|
| Signatures (ML-DSA-87) | 120 | 120 | 0 | 0 |
| Signatures (RSA/ECDSA) | 80 | 0 | 80 | 0 |
| KEM (ML-KEM-1024) | 60 | 60 | 0 | 0 |
| KEM (ML-KEM-768) | 15 | 0 | 15 | 0 |
| Symmetric (AES-256) | 40 | 40 | 0 | 0 |
| Symmetric (AES-128) | 10 | 0 | 10 | 0 |
| Unknown (third-party) | 15 | 0 | 0 | 15 |
Overall Verdict: NonCompliant (105 non-compliant, 15 indeterminate)
Gap Analysis Output: 120 gap items with prioritized deadlines:
- 80 signature assets → Procurement Gate deadline (2027)
- 15 KEM assets → Key Establishment deadline (2030)
- 10 symmetric assets → General Phase-Out (2033)
- 15 indeterminate → manual investigation required immediately
Migration Roadmap: Automatically generated with per-asset PQC targets (ML-DSA-87, ML-KEM-1024, AES-256).
This analysis, which previously took weeks of expert time, now runs in seconds on every commit.
Compliance Alignment
| Framework | How CNSA 2.0 Validator Helps |
|---|---|
| CNSA 2.0 (CNSSP-15 Annex B) | Direct implementation of the advisory as automated validation |
| NSM-10 | Timeline-aware validation aligned with NSM-10 milestones |
| NIST SP 800-53 (CA-7) | Continuous monitoring of compliance posture |
| RMF (Risk Management Framework) | Evidence package ready for security control assessment |
| NIST SP 800-161 | Identifies supply chain crypto risks from third-party components |
Note: The CNSA 2.0 Validator is built on the Knowledge Base and produces per-asset verdicts consumed by Guardian Gate for enforcement and Compass for reporting.