Paseto.Core
1.6.0
dotnet add package Paseto.Core --version 1.6.0
NuGet\Install-Package Paseto.Core -Version 1.6.0
<PackageReference Include="Paseto.Core" Version="1.6.0" />
<PackageVersion Include="Paseto.Core" Version="1.6.0" />
<PackageReference Include="Paseto.Core" />
paket add Paseto.Core --version 1.6.0
#r "nuget: Paseto.Core, 1.6.0"
#:package Paseto.Core@1.6.0
#addin nuget:?package=Paseto.Core&version=1.6.0
#tool nuget:?package=Paseto.Core&version=1.6.0
Paseto.NET, a Paseto (Platform-Agnostic Security Tokens) implementation for .NET
Table of Contents
Features
PASETO protocols
| purpose | v1 | v2 | v3 | v4 |
|---|---|---|---|---|
| local | ✅ | ✅ | ✅ | ✅ |
| public | ✅ | ✅ | ✅ | ✅ |
PASERK extension
| purpose | type | support |
|---|---|---|
| local | local | ✅ |
| local | lid | ✅ |
| local | local-wrap | ✅ |
| local | local-pw | ✅ |
| local | seal | ❌ |
| public | public | ✅ |
| public | pid | ✅ |
| public | secret | ✅ |
| public | sid | ✅ |
| public | secret-wrap | ✅ |
| public | secret-pw | ✅ |
Installation
Targets net8.0 and net10.0.
Install the Paseto.Core NuGet package from the .NET CLI using:
dotnet add package Paseto.Core
or from the NuGet package manager:
Install-Package Paseto.Core
Usage
PASETO
The library exposes a Fluent API with several method overloads found in Use(), WithKey(), AddClaim(), AddFooter() and so on to provide the flexibility needed for encoding and decoding PASETO tokens and also for generating the required symmetric or asymmetric key pairs. However, you can use the Protocols and Handlers directly if you like.
Implicit assertions (AddImplicitAssertion()) are only supported by protocol versions v3 and v4. For v1 and v2 tokens the assertion is ignored, as the PASETO spec provides no way to bind it — do not rely on it for those versions.
Below are a couple of examples for the most common use cases:
Generating a crypto random Symmetric Key
var pasetoKey = new PasetoBuilder().Use(version, Purpose.Local)
.GenerateSymmetricKey();
Generating an Asymmetric Key Pair
var pasetoKey = new PasetoBuilder().Use(version, Purpose.Public)
.GenerateAsymmetricKeyPair(seed);
NOTE: A seed is not required for protocol v1.
Generating a Token
var token = new PasetoBuilder().Use(version, purpose)
.WithKey(key)
.AddClaim("data", "this is a secret message")
.Issuer("https://github.com/daviddesmet/paseto-dotnet")
.Subject(Guid.NewGuid().ToString())
.Audience("https://paseto.io")
.NotBefore(DateTime.UtcNow.AddMinutes(5))
.IssuedAt(DateTime.UtcNow)
.Expiration(DateTime.UtcNow.AddHours(1))
.TokenIdentifier("123456ABCD")
.AddFooter("arbitrary-string-that-isn't-json")
.Encode();
Decoding a Token
var result = new PasetoBuilder().Use(version, purpose)
.WithKey(key)
.Decode(token);
Or validate the token's payload while decoding (the header and signature is always validated):
var valParams = new PasetoTokenValidationParameters
{
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
ValidAudience = "https://paseto.io",
ValidIssuer = "https://github.com/daviddesmet/paseto-dotnet"
};
var result = new PasetoBuilder().Use(version, purpose)
.WithKey(key)
.Decode(token, valParams);
PASERK
The library also provides the PASERK extension for encoding and decoding a key.
A serialized key in PASERK has the format:
k[version].[type].[data]
Encoding a Key
var paserk = Paserk.Encode(pasetoKey, PaserkType.Local);
Decoding a Key
var key = Paserk.Decode(paserk);
Key identifiers (lid / sid / pid)
Identifier types produce a stable, one-way fingerprint of a key. They can only be encoded — Paserk.Decode intentionally throws for them, since an identifier is used to look up a key you already hold, not to recover one.
var kid = Paserk.Encode(pasetoKey, PaserkType.Lid); // sid for secret keys, pid for public keys
Key wrapping (local-wrap / secret-wrap)
Wraps a key with another symmetric wrapping key using the "pie" key-wrapping protocol (AES-256-CTR + HMAC-SHA384 for v1/v3, XChaCha20 + BLAKE2b for v2/v4):
// wk is a PasetoSymmetricKey used to wrap/unwrap
var paserk = Paserk.Encode(localKey, PaserkType.LocalWrap, wrappingKey);
var key = Paserk.Decode(paserk, wrappingKey);
// or via the builder
var paserk = new PasetoBuilder().Use(ProtocolVersion.V4, Purpose.Local)
.WithKey(localKey)
.GenerateSerializedKey(PaserkType.LocalWrap, wrappingKey);
Password-based key wrapping (local-pw / secret-pw)
Wraps a key with a password using PBKW (PBKDF2-SHA384 + AES-256-CTR for v1/v3, Argon2id + XChaCha20 for v2/v4). Tune the work factors via PbkwOptions:
var password = Encoding.UTF8.GetBytes("correct horse battery staple");
var options = new PbkwOptions
{
MemoryLimitBytes = 67_108_864, // Argon2id (v2/v4)
OpsLimit = 2,
Iterations = 100_000, // PBKDF2 (v1/v3)
};
var paserk = Paserk.Encode(localKey, PaserkType.LocalPassword, password, options);
var key = Paserk.Decode(paserk, password);
The PbkwOptions defaults are interactive-grade. For keys stored at rest, raise the work factors (higher MemoryLimitBytes/OpsLimit for Argon2id, more Iterations for PBKDF2) to match your threat model and hardware.
Roadmap
- Add support for the
sealPASERK type (the only remaining operation). - Add support for version/purpose detection when decoding a PASETO token (currently required via
Use(); PASERK already detects the version from the header). - Add support for custom payload validation rules.
- Improve documentation.
Test Coverage
- Includes the mandatory test vectors for PASETO and PASERK.
Cryptography
- Ed25519 (EdDSA over Curve25519) — bundled managed implementation (originally derived from CodesInChaos Chaos.NaCl).
- BLAKE2b — bundled managed implementation, plus Bouncy Castle for key identifiers.
- AES-256-CTR, ECDSA over P-384, Argon2id — Bouncy Castle.
- XChaCha20 — NaCl.Core.
- HMAC-SHA384, HKDF-SHA384, PBKDF2-SHA384, SHA-384 — .NET base class library.
Dependency Lock Files
The repository uses NuGet lock files (packages.lock.json, committed per project) to pin the full dependency graph, including transitive packages. CI restores with locked mode enabled, so a build fails if the resolved packages differ from the lock files — protecting against floating transitive versions and dependency-confusion attacks.
Upgrading packages therefore changes slightly:
- Edit the package version in the
.csproj(or let Dependabot do it), then rundotnet restore --force-evaluatefrom the repository root and commit the updatedpackages.lock.jsonfiles together with the.csprojchange. - Dependabot PRs update the lock files automatically.
- A plain
dotnet restorelocally never floats versions; it follows the lock files. If it reportsNU1004, the lock files are out of date — rundotnet restore --force-evaluate.
Learn More
- PASETO (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.
- PASERK (Platform-Agnostic SERialized Keys) is an extension to PASETO that provides key-wrapping and serialization.
| Product | Versions 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 was computed. 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. |
-
net10.0
- BouncyCastle.Cryptography (>= 2.6.2)
- NaCl.Core (>= 2.2.0)
-
net8.0
- BouncyCastle.Cryptography (>= 2.6.2)
- NaCl.Core (>= 2.2.0)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Paseto.Core:
| Package | Downloads |
|---|---|
|
TGL.Backend.Core
TGL Solutions Backend Core |
|
|
Linbik.Core
Core library providing shared dependencies and models for Linbik. Recommended for advanced manual integration; otherwise included by default in other Linbik packages. |
|
|
PasetoBearer.Authentication
A simple implementation for securing the API by public PASETO access tokens. |
|
|
FAPIServer
Core logic for FAPI Server |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Paseto.Core:
| Repository | Stars |
|---|---|
|
EpinelPS/EpinelPS
A private server for some anime game
|
| Version | Downloads | Last Updated |
|---|---|---|
| 1.6.0 | 52 | 7/4/2026 |
| 1.5.2 | 43 | 7/3/2026 |
| 1.5.1 | 46 | 7/3/2026 |
| 1.5.0 | 46,650 | 12/4/2025 |
| 1.4.1 | 163,924 | 3/22/2025 |
| 1.4.0 | 36,455 | 1/27/2025 |
| 1.3.0 | 66,591 | 7/15/2024 |
| 1.2.1 | 11,961 | 6/23/2024 |
| 1.1.1 | 12,081 | 5/16/2024 |
| 1.1.0 | 31,286 | 4/20/2023 |
| 1.0.7 | 72,986 | 8/24/2022 |
| 1.0.6 | 18,690 | 5/24/2022 |
| 1.0.5 | 208 | 5/11/2022 |
| 1.0.4 | 2,573 | 4/28/2022 |
| 1.0.3 | 283 | 4/16/2022 |
| 0.7.2 | 108,146 | 7/9/2019 |
| 0.7.1 | 1,144 | 2/5/2019 |
| 0.7.0 | 2,627 | 11/27/2018 |