DAT C# Library
GitHub NuGet · Test Codeリポジトリ
bash
powershell
Requires: .NET 8.0 or .NET 10.0 (
net8.0/net10.0multi-target)
DatManager,DatCmsManager,DatCertificateand the signature types hold native crypto handles and implementIDisposable— dispose them (or useusing).
サンプル
DAT証明書管理サービス
cs
// singleton — dispose on shutdown (stops the sync loop and releases the HttpClient)
DatCmsManager manager = await DatCmsManager.Builder()
.Host("localhost")
.Port(8088)
//.IntervalOff() // auto sync off
.IntervalSeconds(60)
.Token("12345678901b")
//.Logger(logger)
.BuildAsync();
// BuildAsync always returns a manager, even when the first sync failed — it
// becomes usable once the network recovers. Ask separately whether it synced.
DatException? syncError = manager.LastError;
if (syncError is not null)
{
// A permanent failure (bad token, wrong URL) will never resolve on its own.
Console.WriteLine($"initial sync failed: {syncError.Code} (retry={syncError.Retry})");
}
Console.WriteLine($"synced version: {manager.GetVersion()}");
// manual sync
// await manager.Sync();
string plain = "Unicode 유니코드 ユニコード 万国码 يونيكود यूनिकोड Юникод 🦄💻";
string secure = "Ciphertext 암호문 暗号文 密文 Шифротекст Texte chiffré Geheimtext نص مشفر सिफरपाठ 🔐";
Console.WriteLine("plain : " + plain);
Console.WriteLine("secure : " + secure);
// issue dat
string dat = manager.Issue(plain, secure);
Console.WriteLine("dat : " + dat);
// parse dat
Payload payload = manager.Parse(dat);
string payloadPlain = payload.Plain;
string payloadSecure = payload.Secure;
Console.WriteLine("payload plain : " + payloadPlain);
Console.WriteLine("payload secure : " + payloadSecure);手動実装
cs
using var datManager = DatManager.NewInstance();
// (cid, issuanceStart, issuanceDuration, datTtl, signatureAlgorithm, cryptoAlgorithm)
long now = Unixtime.Now();
using var cert = DatCertificate.Generate(
0,
now - 10,
7200,
1800,
DatSignatureAlgorithm.EcdsaP256,
DatCryptoAlgorithm.IvAes128Gcm
);
// Imports copies the certificates, so the caller keeps ownership of `cert`.
datManager.Imports(new List<DatCertificate> { cert }, false);
string plain = "Unicode 유니코드 ユニコード 万国码 يونيكود यूनिकोड Юникод 🦄💻";
string secure = "Ciphertext 암호문 暗号文 密文 Шифротекст Texte chiffré Geheimtext نص مشفر सिफरपाठ 🔐";
string dat = datManager.Issue(plain, secure);
Payload payload = datManager.Parse(dat);
Assert.That(payload.Plain, Is.EqualTo(plain));
Assert.That(payload.Secure, Is.EqualTo(secure));
TestContext.Progress.WriteLine($"PARSE DAT: {dat}");
TestContext.Progress.WriteLine($"plain: {payload.Plain}");
TestContext.Progress.WriteLine($"secure: {payload.Secure}");エラー処理
Every failure is a DatException carrying a Code. The string is the contract; the message is free to change.
cs
// Expiry, forgery and malformed input each need a different response.
try
{
Payload payload = manager.Parse(dat);
}
catch (DatException e) when (e.Code == DatErrorCode.TokenExpired)
{
// Normal end of life — let the client refresh its token.
}
catch (DatException e) when (e.SecurityEvent)
{
// DAT_SIG_MISMATCH or DAT_CRYPTO_TAG_MISMATCH: forged or tampered with.
Console.Error.WriteLine($"[SECURITY] {e.Code}");
}
catch (DatException e)
{
// Anything else: just reject the request.
Console.Error.WriteLine($"rejected: {e.Code}");
}cs
try
{
string dat = manager.Issue(plain, secure);
}
catch (DatException e)
{
// Never retry a permanent failure — it will not resolve on its own.
if (e.Retry == DatRetry.Transient)
{
// back off, then retry
}
// Why issuing failed is chained, not folded into the outer code.
// Waiting helps for DAT_CERT_NOT_YET_ISSUABLE and nothing else.
if (e.Code == DatErrorCode.ManagerNoIssuableCertificate)
{
Console.Error.WriteLine($"cannot issue: {DatException.CodeOf(e.InnerException)}");
}
}