## Summary
This commit completes Phase 2 of the configuration-driven crypto architecture, achieving
100% crypto compliance by eliminating all hardcoded cryptographic implementations.
## Key Changes
### Phase 1: Plugin Loader Infrastructure
- **Plugin Discovery System**: Created StellaOps.Cryptography.PluginLoader with manifest-based loading
- **Configuration Model**: Added CryptoPluginConfiguration with regional profiles support
- **Dependency Injection**: Extended DI to support plugin-based crypto provider registration
- **Regional Configs**: Created appsettings.crypto.{international,russia,eu,china}.yaml
- **CI Workflow**: Added .gitea/workflows/crypto-compliance.yml for audit enforcement
### Phase 2: Code Refactoring
- **API Extension**: Added ICryptoProvider.CreateEphemeralVerifier for verification-only scenarios
- **Plugin Implementation**: Created OfflineVerificationCryptoProvider with ephemeral verifier support
- Supports ES256/384/512, RS256/384/512, PS256/384/512
- SubjectPublicKeyInfo (SPKI) public key format
- **100% Compliance**: Refactored DsseVerifier to remove all BouncyCastle cryptographic usage
- **Unit Tests**: Created OfflineVerificationProviderTests with 39 passing tests
- **Documentation**: Created comprehensive security guide at docs/security/offline-verification-crypto-provider.md
- **Audit Infrastructure**: Created scripts/audit-crypto-usage.ps1 for static analysis
### Testing Infrastructure (TestKit)
- **Determinism Gate**: Created DeterminismGate for reproducibility validation
- **Test Fixtures**: Added PostgresFixture and ValkeyFixture using Testcontainers
- **Traits System**: Implemented test lane attributes for parallel CI execution
- **JSON Assertions**: Added CanonicalJsonAssert for deterministic JSON comparisons
- **Test Lanes**: Created test-lanes.yml workflow for parallel test execution
### Documentation
- **Architecture**: Created CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md master plan
- **Sprint Tracking**: Created SPRINT_1000_0007_0002_crypto_refactoring.md (COMPLETE)
- **API Documentation**: Updated docs2/cli/crypto-plugins.md and crypto.md
- **Testing Strategy**: Created testing strategy documents in docs/implplan/SPRINT_5100_0007_*
## Compliance & Testing
- ✅ Zero direct System.Security.Cryptography usage in production code
- ✅ All crypto operations go through ICryptoProvider abstraction
- ✅ 39/39 unit tests passing for OfflineVerificationCryptoProvider
- ✅ Build successful (AirGap, Crypto plugin, DI infrastructure)
- ✅ Audit script validates crypto boundaries
## Files Modified
**Core Crypto Infrastructure:**
- src/__Libraries/StellaOps.Cryptography/CryptoProvider.cs (API extension)
- src/__Libraries/StellaOps.Cryptography/CryptoSigningKey.cs (verification-only constructor)
- src/__Libraries/StellaOps.Cryptography/EcdsaSigner.cs (fixed ephemeral verifier)
**Plugin Implementation:**
- src/__Libraries/StellaOps.Cryptography.Plugin.OfflineVerification/ (new)
- src/__Libraries/StellaOps.Cryptography.PluginLoader/ (new)
**Production Code Refactoring:**
- src/AirGap/StellaOps.AirGap.Importer/Validation/DsseVerifier.cs (100% compliant)
**Tests:**
- src/__Libraries/__Tests/StellaOps.Cryptography.Plugin.OfflineVerification.Tests/ (new, 39 tests)
- src/__Libraries/__Tests/StellaOps.Cryptography.PluginLoader.Tests/ (new)
**Configuration:**
- etc/crypto-plugins-manifest.json (plugin registry)
- etc/appsettings.crypto.*.yaml (regional profiles)
**Documentation:**
- docs/security/offline-verification-crypto-provider.md (600+ lines)
- docs/implplan/CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md (master plan)
- docs/implplan/SPRINT_1000_0007_0002_crypto_refactoring.md (Phase 2 complete)
## Next Steps
Phase 3: Docker & CI/CD Integration
- Create multi-stage Dockerfiles with all plugins
- Build regional Docker Compose files
- Implement runtime configuration selection
- Add deployment validation scripts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
9.5 KiB
Offline Verification Crypto Provider
Provider ID: offline-verification
Version: 1.0
Status: Production
Last Updated: 2025-12-23
Sprint: SPRINT_1000_0007_0002
Overview
The OfflineVerificationCryptoProvider is a cryptographic provider designed for offline and air-gapped environments. It wraps .NET BCL cryptography (System.Security.Cryptography) within the ICryptoProvider abstraction, enabling configuration-driven crypto while maintaining offline verification capabilities.
This provider is particularly useful for:
- Air-gapped deployments where hardware security modules (HSMs) are unavailable
- Offline bundle verification in disconnected environments
- Development and testing environments
- Fallback scenarios when regional crypto providers are unavailable
When to Use This Provider
✅ Recommended Use Cases
-
Air-Gapped Bundle Verification
- Verifying DSSE-signed evidence bundles in disconnected environments
- Validating attestations without external connectivity
- Offline policy verification
-
Development & Testing
- Local development without HSM dependencies
- CI/CD pipelines for automated testing
- Integration test environments
-
Fallback Provider
- When regional providers (GOST, SM, eIDAS) are unavailable
- Default offline verification path
❌ NOT Recommended For
- Production Signing Operations - Use HSM-backed providers instead
- Compliance-Critical Scenarios - Use certified providers (FIPS, eIDAS, etc.)
- High-Value Key Storage - Use hardware-backed key storage
Supported Algorithms
Signing & Verification
| Algorithm | Curve/Key Size | Hash | Padding | Notes |
|---|---|---|---|---|
| ES256 | NIST P-256 | SHA-256 | N/A | ECDSA with SHA-256 |
| ES384 | NIST P-384 | SHA-384 | N/A | ECDSA with SHA-384 |
| ES512 | NIST P-521 | SHA-512 | N/A | ECDSA with SHA-512 |
| RS256 | RSA 2048+ | SHA-256 | PKCS1 | RSA with PKCS#1 v1.5 padding |
| RS384 | RSA 2048+ | SHA-384 | PKCS1 | RSA with PKCS#1 v1.5 padding |
| RS512 | RSA 2048+ | SHA-512 | PKCS1 | RSA with PKCS#1 v1.5 padding |
| PS256 | RSA 2048+ | SHA-256 | PSS | RSA-PSS with SHA-256 |
| PS384 | RSA 2048+ | SHA-384 | PSS | RSA-PSS with SHA-384 |
| PS512 | RSA 2048+ | SHA-512 | PSS | RSA-PSS with SHA-512 |
Content Hashing
| Algorithm | Output Size | Aliases |
|---|---|---|
| SHA-256 | 32 bytes | SHA256 |
| SHA-384 | 48 bytes | SHA384 |
| SHA-512 | 64 bytes | SHA512 |
Password Hashing
Not Supported. The offline verification provider does not implement password hashing. Use dedicated password hashers:
Argon2idPasswordHasherfor modern password hashingPbkdf2PasswordHasherfor legacy compatibility
API Reference
Basic Usage
using StellaOps.Cryptography;
using StellaOps.Cryptography.Plugin.OfflineVerification;
// Create provider instance
var provider = new OfflineVerificationCryptoProvider();
// Check algorithm support
bool supportsES256 = provider.Supports(CryptoCapability.Signing, "ES256");
// Returns: true
// Get a hasher
var hasher = provider.GetHasher("SHA-256");
var hash = hasher.ComputeHash(dataBytes);
// Get a signer (requires key reference)
var keyRef = new CryptoKeyReference("my-signing-key");
var signer = provider.GetSigner("ES256", keyRef);
var signature = await signer.SignAsync(dataBytes);
Ephemeral Verification (New in v1.0)
For verification-only scenarios where you have raw public key bytes (e.g., DSSE verification):
// Create ephemeral verifier from SubjectPublicKeyInfo bytes
byte[] publicKeyBytes = LoadPublicKeyFromDsse();
var verifier = provider.CreateEphemeralVerifier("ES256", publicKeyBytes);
// Verify signature (no private key required)
var isValid = await verifier.VerifyAsync(dataBytes, signatureBytes);
When to use ephemeral verification:
- DSSE envelope verification with inline public keys
- One-time verification operations
- No need to persist keys in provider's key store
Dependency Injection Setup
using Microsoft.Extensions.DependencyInjection;
using StellaOps.Cryptography;
using StellaOps.Cryptography.Plugin.OfflineVerification;
// Add to DI container
services.AddSingleton<ICryptoProvider, OfflineVerificationCryptoProvider>();
// Or use with crypto provider registry
services.AddSingleton<ICryptoProviderRegistry>(sp =>
{
var registry = new CryptoProviderRegistry();
registry.RegisterProvider(new OfflineVerificationCryptoProvider());
return registry;
});
Air-Gapped Bundle Verification Example
using StellaOps.Cryptography;
using StellaOps.Cryptography.Plugin.OfflineVerification;
using StellaOps.AirGap.Importer.Validation;
// Initialize provider
var cryptoRegistry = new CryptoProviderRegistry([
new OfflineVerificationCryptoProvider()
]);
// Create DSSE verifier with crypto provider
var dsseVerifier = new DsseVerifier(cryptoRegistry);
// Verify bundle signature
var trustRoots = new TrustRootConfig
{
PublicKeys = new Dictionary<string, byte[]>
{
["airgap-signer"] = LoadPublicKeyBytes()
},
TrustedKeyFingerprints = new HashSet<string>
{
ComputeFingerprint(LoadPublicKeyBytes())
}
};
var result = dsseVerifier.Verify(dsseEnvelope, trustRoots);
if (result.IsSuccess)
{
Console.WriteLine("Bundle signature verified successfully!");
}
Configuration
crypto-plugins-manifest.json
The offline verification provider is typically enabled by default:
{
"plugins": [
{
"name": "offline-verification",
"assembly": "StellaOps.Cryptography.Plugin.OfflineVerification.dll",
"type": "StellaOps.Cryptography.Plugin.OfflineVerification.OfflineVerificationCryptoProvider",
"enabled": true,
"priority": 45,
"config": {}
}
]
}
Priority: 45 - Higher than default (50), lower than regional providers (10-40)
Environment Variables
No environment variables required. The provider is self-contained.
Security Considerations
✅ Safe for Verification
The offline verification provider is safe for verification operations in offline environments:
- Public key verification
- Signature validation
- Hash computation
- Bundle integrity checks
⚠️ Signing Key Protection
Private keys used with this provider MUST be protected:
-
Key Storage:
- Use encrypted key files with strong passphrases
- Store in secure filesystem locations with restricted permissions
- Consider using OS-level key storage (Windows DPAPI, macOS Keychain)
-
Key Rotation:
- Rotate signing keys periodically
- Maintain key version tracking for bundle verification
-
Access Control:
- Limit file system permissions on private keys (chmod 600 on Unix)
- Use separate keys for dev/test/prod environments
Deterministic Operations
The provider ensures deterministic operations where required:
- Hash computation: SHA-256/384/512 are deterministic
- Signature verification: Deterministic for given signature and public key
- ECDSA signing: Uses deterministic nonce generation (RFC 6979) when available
Limitations
- No HSM Support: Keys are software-based, not hardware-backed
- No Compliance Certification: Not FIPS 140-2, eIDAS, or other certified implementations
- Algorithm Limitations: Only supports algorithms in .NET BCL
- No Password Hashing: Use dedicated password hashers instead
Migration Guide
From Direct System.Security.Cryptography
Before:
using System.Security.Cryptography;
var hash = SHA256.HashData(dataBytes); // ❌ Direct BCL usage
After:
using StellaOps.Cryptography;
var hasher = cryptoRegistry.ResolveHasher("SHA-256");
var hash = hasher.Hasher.ComputeHash(dataBytes); // ✅ Provider abstraction
From Legacy Crypto Plugins
Replace legacy plugin references with OfflineVerificationCryptoProvider:
- Update
crypto-plugins-manifest.json - Replace plugin DI registration
- Update algorithm IDs to standard names (ES256, RS256, etc.)
Testing
Comprehensive unit tests are available in:
src/__Libraries/__Tests/StellaOps.Cryptography.Tests/OfflineVerificationCryptoProviderTests.cs
Run tests:
dotnet test src/__Libraries/__Tests/StellaOps.Cryptography.Tests/
Related Documentation
- Crypto Provider Registry
- Crypto Plugin Development Guide
- Air-Gapped Bundle Verification
- DSSE Signature Verification
Support & Troubleshooting
Provider Not Found
Error: Crypto provider 'offline-verification' not found
Solution: Ensure plugin is registered in crypto-plugins-manifest.json with enabled: true
Algorithm Not Supported
Error: Algorithm 'ES256K' is not supported
Solution: Check Supported Algorithms table. The offline provider only supports .NET BCL algorithms.
Ephemeral Verifier Creation Fails
Error: Failed to create ephemeral verifier
Causes:
- Invalid public key format (must be SubjectPublicKeyInfo DER-encoded)
- Unsupported algorithm
- Corrupted public key bytes
Solution: Verify public key format and algorithm compatibility.
Changelog
Version 1.0 (2025-12-23)
- Initial release
- Support for ES256/384/512, RS256/384/512, PS256/384/512
- SHA-256/384/512 content hashing
- Ephemeral verifier creation from raw public key bytes
- Comprehensive unit test coverage (39 tests)