LibTab 0.1.0
dotnet add package LibTab --version 0.1.0
NuGet\Install-Package LibTab -Version 0.1.0
<PackageReference Include="LibTab" Version="0.1.0" />
<PackageVersion Include="LibTab" Version="0.1.0" />
<PackageReference Include="LibTab" />
paket add LibTab --version 0.1.0
#r "nuget: LibTab, 0.1.0"
#:package LibTab@0.1.0
#addin nuget:?package=LibTab&version=0.1.0
#tool nuget:?package=LibTab&version=0.1.0
LibTab for .NET
Pure C# implementation of libtab, the Plan 9 ndb-shaped table format.
LibTab reads and writes the same text table files as the C library while
keeping the crypto wire format compatible for HASHED, SIGNED, and
ENCRYPTED cells. It has no native runtime dependency; cryptographic
primitives use Bouncy Castle plus managed compatibility code where libtab's
Monocypher wire format requires it.
Install
dotnet add package LibTab --version 0.1.0
Format
A table starts with a schema entry, followed by rows made of attr=value
tuples:
schema=users
col=name
col=uid
col=password type=HASHED
name=alice
uid=1000
password=hashed:Aa5Kr7PH2GFrc58Fow0GtOIjb96nEhaBWfNG6KPv1X2e
Plain cells preserve libtab's ndb text semantics: semantic nil and the literal
string nil are distinct, unsafe ndb text is entity-escaped, and legacy
__libtab_text64_v1: cells remain readable.
Basic Use
using System.Text;
using LibTab;
var columns = new[]
{
new TabColumn("name"),
new TabColumn("uid"),
new TabColumn("password", "HASHED"),
};
TabTable table = TabTable.Create("users.tab", "users", columns);
TabRow alice = table.AddRow("name", "alice");
table.Set(alice, "uid", "1000");
table.SetHashed(alice, "password", Encoding.UTF8.GetBytes("secret"));
table.Commit();
TabTable reopened = TabTable.Open("users.tab");
TabRow found = reopened.Search("name", "alice").Single();
bool passwordMatches = reopened.VerifyHash(found, "password", Encoding.UTF8.GetBytes("secret"));
Signed Cells
using System.Collections.Generic;
using System.Text;
using LibTab;
TabKeyPair keyPair = TabKeyPair.Generate();
var columns = new[]
{
new TabColumn("id"),
new TabColumn("payload", "SIGNED", new Dictionary<string, string> { ["signer"] = "local" }),
};
TabTable table = TabTable.Create("audit.tab", "audit", columns);
TabRow row = table.AddRow("id", "event-1");
table.SetSigned(row, "payload", Encoding.UTF8.GetBytes("created"), keyPair.SecretKey);
table.Commit();
byte[] body = table.VerifySigned(row, "payload", keyPair.PublicKey);
Encrypted Cells
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using LibTab;
byte[] key = RandomNumberGenerator.GetBytes(TabTable.EncryptedKeyLength);
var columns = new[]
{
new TabColumn("id"),
new TabColumn("secret", "ENCRYPTED", new Dictionary<string, string> { ["key"] = "local" }),
};
TabTable table = TabTable.Create("secrets.tab", "secrets", columns);
TabRow row = table.AddRow("id", "entry-1");
table.SetEncrypted(row, "secret", Encoding.UTF8.GetBytes("hunter2"), key);
table.Commit();
byte[] plaintext = table.Decrypt(row, "secret", key);
ENCRYPTED cells use the C library's wire format:
encrypted:<base64url(ver | nonce[24] | mac[16] | ciphertext)>. The cipher is
Monocypher-compatible XChaCha20-Poly1305, not AES-GCM. Keys are raw 32-byte
values supplied by the caller; schema key=<name> attributes are labels only.
Compatibility
The regular gate compiles a temporary C harness against the local C libtab
archive, creates equivalent C and C# tables, byte-compares deterministic output,
and cross-verifies files in both directions. Argon2id and ENCRYPTED cells are
checked by verification instead of byte comparison because correct
implementations generate fresh salts and nonces.
Current implemented cell types:
- plain ndb text
HASHEDwith BLAKE2b and Argon2id verificationSIGNEDwith Monocypher-compatible EdDSAENCRYPTEDwith Monocypher-compatible XChaCha20-Poly1305
TabTable.MaxCellLineBytes exposes the C library's TabMaxCell value. Plain
setters, row heads, streaming writer cells, SIGNED, and ENCRYPTED refuse
values whose emitted ndb line would exceed that encoded limit; HASHED
preimages remain unbounded because the stored digest is fixed-size.
Build And Test
dotnet restore LibTab.slnx
scripts/test.sh
scripts/full-gates.sh
The full gate requires the C libtab repository and plan9port tools. Set
LIBTAB_C_REPO if the C repository is not at /home/scott/Repo/libtab.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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. |
-
net9.0
- BouncyCastle.Cryptography (>= 2.5.1)
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 | 134 | 10/4/2026 |
Initial pure C# libtab port with ndb-shaped read/write support, HASHED, SIGNED, and ENCRYPTED typed cells, TabMaxCell write guards, and C interop verification.