Class ZeroizingBuffer
- Namespace
- PostQuantum.SecretSharing
- Assembly
- PostQuantum.SecretSharing.dll
A fixed-size byte buffer for secret material that is zeroed on disposal and is allocated on the pinned object heap so the garbage collector can never relocate (and thus silently copy) the secret elsewhere in memory.
public sealed class ZeroizingBuffer : IDisposable
- Inheritance
-
ZeroizingBuffer
- Implements
- Inherited Members
Remarks
Why pinned allocation. A normal managed array can be moved by a
compacting GC, leaving a stale copy of the secret in the old location that
ZeroMemory(Span<byte>) on the live array will never
reach. AllocateArray<T>(int, bool) with pinned: true
places the backing array on the pinned object heap, which is never compacted,
so the bytes we zero are the only copy the GC ever made.
Best-effort page-locking. On construction the buffer is locked into RAM
(VirtualLock on Windows, mlock on Linux/macOS) to resist being
paged to swap, and unlocked on disposal. This is best-effort:
IsMemoryLocked reports whether it succeeded — it can fail without
privileges or when the per-process locked-memory limit is reached, in which
case the buffer still works, just unlocked.
Still out of scope. Locking resists swap but does not defend against a process memory dump. The secret necessarily exists in cleartext in process memory while it is in use. See KNOWN-GAPS.md.
Constructors
ZeroizingBuffer(int)
Allocates a pinned, zero-initialized buffer of the given length and attempts to lock it into RAM (best-effort; see IsMemoryLocked).
public ZeroizingBuffer(int length)
Parameters
lengthintBuffer length in bytes; must be non-negative.
Exceptions
- ArgumentOutOfRangeException
If
lengthis negative.
Properties
IsMemoryLocked
Whether the backing pages were successfully locked into RAM. False is not an error — the buffer is fully functional, just not protected from swap.
public bool IsMemoryLocked { get; }
Property Value
Length
The buffer length in bytes. Remains valid after disposal.
public int Length { get; }
Property Value
Span
A writable view over the secret bytes.
public Span<byte> Span { get; }
Property Value
Exceptions
- ObjectDisposedException
If the buffer has been disposed.
Methods
Dispose()
Zeroes the buffer and marks it disposed. Idempotent: calling more than once is safe and does nothing after the first call.
public void Dispose()
~ZeroizingBuffer()
Best-effort finalizer backstop: if a caller forgets to dispose, zero and unlock the buffer when the object is collected. This is not a substitute for explicit disposal (the window between last use and collection is unbounded) and is documented as best-effort in KNOWN-GAPS.md.
protected ~ZeroizingBuffer()