PostQuantum.DataProtection.AzureKeyVault 0.1.0-preview.5

This is a prerelease version of PostQuantum.DataProtection.AzureKeyVault.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package PostQuantum.DataProtection.AzureKeyVault --version 0.1.0-preview.5
                    
NuGet\Install-Package PostQuantum.DataProtection.AzureKeyVault -Version 0.1.0-preview.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PostQuantum.DataProtection.AzureKeyVault" Version="0.1.0-preview.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PostQuantum.DataProtection.AzureKeyVault" Version="0.1.0-preview.5" />
                    
Directory.Packages.props
<PackageReference Include="PostQuantum.DataProtection.AzureKeyVault" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PostQuantum.DataProtection.AzureKeyVault --version 0.1.0-preview.5
                    
#r "nuget: PostQuantum.DataProtection.AzureKeyVault, 0.1.0-preview.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PostQuantum.DataProtection.AzureKeyVault@0.1.0-preview.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PostQuantum.DataProtection.AzureKeyVault&version=0.1.0-preview.5&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=PostQuantum.DataProtection.AzureKeyVault&version=0.1.0-preview.5&prerelease
                    
Install as a Cake Tool

PostQuantum.DataProtection.AzureKeyVault

License: MIT

Azure Key Vault-backed IPostQuantumKeyStore for PostQuantum.DataProtection. Stores the long-lived ML-KEM-768 keypairs that wrap ASP.NET Core Data Protection keys in an Azure Key Vault Secrets vault — durable, audited, shareable across replicas — without ever placing plaintext on disk.

⚠️ Preview (0.1.0-preview.3). Tracks the core PostQuantum.DataProtection preview cadence. API and storage layout may still change before 1.0.

Why

The default FilePostQuantumKeyStore is single-writer + many-readers on a shared file. That is fine for single-host deployments; it does not survive serverless, multi-replica containers, or truly stateless hosts. Azure Key Vault Secrets gives you:

  • Durable, replicated storage (the vault's own SLA, not your container's).
  • Audit trail (every read and write logs to the vault's audit pipeline).
  • Shared access across every replica that runs your service principal / managed identity.
  • No new trust boundary — the PQ secret key is already wrapped by the host IContentKeyProvider before it reaches the vault. Key Vault sees an opaque blob.

Install

dotnet add package PostQuantum.DataProtection.AzureKeyVault --prerelease

Wire it up

using PostQuantum.DataProtection.Hybrid;
using PostQuantum.KeyManagement;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// 1. The classical KEK provider (host KEK that wraps the ML-KEM secret key).
builder.Services.AddPostQuantumKeyManagement(o =>
{
    o.Passphrase = builder.Configuration["KeyManagement:Passphrase"]
        ?? throw new InvalidOperationException("Missing passphrase");
    o.WorkFactor = KekWorkFactor.Moderate;
    o.KeyringPath = "keys/host-keyring.bin"; // or your own IKeyringStore
});

// 2. ASP.NET Core Data Protection with the PQ wrap.
builder.Services
    .AddDataProtection()
    .PersistKeysToAzureBlobStorage(/* ... */)
    .ProtectKeysWithPostQuantum(o =>
    {
        // KeyStorePath is required by the bundled file store but is ignored when we override the
        // IPostQuantumKeyStore below. Pass any placeholder.
        o.KeyStorePath = "keys/unused-pq-keystore.txt";
        o.Mode = HybridKemMode.Hybrid;
    });

// 3. Replace the file store with Azure Key Vault.
builder.Services.AddPostQuantumDataProtectionAzureKeyVault(new Uri("https://my-vault.vault.azure.net/"));

WebApplication app = builder.Build();

For full control over credential resolution:

builder.Services.AddPostQuantumDataProtectionAzureKeyVault(options =>
{
    options.VaultUri = new Uri("https://my-vault.vault.azure.net/");
    options.Credential = new ManagedIdentityCredential();   // or any TokenCredential
    options.SecretPrefix = "pq-dp-prod";                    // optional: share one vault across rings
});

What goes into the vault

The store creates two kinds of secrets per host:

Secret name Contents
pq-dataprotection-{keyId} The PostQuantumKeyPair.Encode() token
pq-dataprotection-active The active keypair id

Where {keyId} is the pq-mlkem768-<6 hex> value the library generates. The keypair token is non-secret in the sense that it carries no plaintext key material — the secret key is wrapped under the host KEK. The active pointer is non-secret as well.

Customise the pq-dataprotection prefix via AzureKeyVaultDataProtectionOptions.SecretPrefix if you share one vault across multiple PQ rings.

Required Key Vault permissions

The credential you supply needs Get, List, and Set permissions on Secrets:

  • Access policy: secret get, secret list, secret set.
  • RBAC: Key Vault Secrets Officer (or a custom role with the three actions above).

The store never deletes or purges secrets. Pruning historical keypairs is a deliberate operator action — see the retention discussion in KNOWN-GAPS.md §5.

Cost

  • Startup: 1 List + N Get calls, where N is the number of keypairs ever generated.
  • Rotation: 2 Set calls per rotation.
  • Steady state: zero — the store caches in memory after first load.

At one rotation per quarter and a fleet of 100 replicas, that is on the order of 2 vault writes per quarter from the rotator, plus 100 × (1 + N) reads per cold start. Well below any Key Vault throughput limit.

Testing

The store is built around a narrow IKeyVaultSecretClient seam — for your own tests you can substitute an in-memory fake without standing up a real vault. The unit-test project in this repo (tests/PostQuantum.DataProtection.AzureKeyVault.Tests) does exactly that.


To God be the glory — 1 Corinthians 10:31.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.7 56 6/4/2026
0.1.0-preview.6 52 6/4/2026
0.1.0-preview.5 57 6/4/2026
0.1.0-preview.4 54 6/4/2026

0.1.0-preview.3: First public preview. Azure Key Vault-backed IPostQuantumKeyStore for PostQuantum.DataProtection. Stores ML-KEM-768 keypairs as Key Vault Secrets (one secret per keypair plus a small "active" pointer secret); the PQ secret key is already envelope-encrypted by the host IContentKeyProvider before it touches the vault. Supports DefaultAzureCredential out of the box and any TokenCredential a caller wants to supply. Concurrent-safe; the "active" pointer is updated atomically through Key Vault's per-secret versioning. Tracks roadmap items in PostQuantum.DataProtection/future.md. No third-party audit yet; see PostQuantum.DataProtection/KNOWN-GAPS.md for scope.