ProtectedNumbers 0.1.1
dotnet add package ProtectedNumbers --version 0.1.1
NuGet\Install-Package ProtectedNumbers -Version 0.1.1
<PackageReference Include="ProtectedNumbers" Version="0.1.1" />
<PackageVersion Include="ProtectedNumbers" Version="0.1.1" />
<PackageReference Include="ProtectedNumbers" />
paket add ProtectedNumbers --version 0.1.1
#r "nuget: ProtectedNumbers, 0.1.1"
#:package ProtectedNumbers@0.1.1
#addin nuget:?package=ProtectedNumbers&version=0.1.1
#tool nuget:?package=ProtectedNumbers&version=0.1.1
<div align="center">
<img src="PackageIcon.png" alt="ProtectedNumbers" width="150px"/>
ProtectedNumbers
A .NET library for safe, opaque numeric identifiers you can pass through URLs, JSON, and model binding </div>
What problem it solved
When working with a legacy database, most often primary keys are sequential numbers like this:
{
"id": "4018378694012108869",
"name": "some data row"
}
And if you expose the data as is on a public endpoint, an attacker can guess easily other identifiers:
{
"id": "4018378694012108868",
"name": "oops some other row"
}
There are ways to mitigate this problem. One of them is to make identifiers unguessable:
{
"id": "CfDJ8K3W-Fa_koRAlAI935b9MJjgVrkgEMGZ5bvAPECdKZvgMpUPsvhVru9een2MVC0P8e4N4ehwgKgueAGjZlEP4s7gu3AsBLRoQrnUZr8hw4qZYAr-StAlQWCfx2FHTs1EGgEpB3T9YPSGxAxm0XVP7Mc",
"name": "some data row"
}
What is ProtectedNumbers
- ProtectedNumbers provides a lightweight struct, ProtectedNumber, that carries either a raw numeric value (long) or a protected string representation (for example for URLs or JSON), and can safely round-trip between the two with application-provided protection.
- First-class ASP.NET Core integration is included:
- Dependency injection helpers via services.AddProtectedNumbers().
- MVC model binding for ProtectedNumber and ProtectedNumber? parameters.
- System.Text.Json support.
- Supported target frameworks: net6.0, net8.0, net9.0.
Key semantics of ProtectedNumber:
- Dual representation: Value (long) and ProtectedValue (string). Either side can be present independently.
- Empty sentinel: ProtectedNumber.Empty is initialized but HasValue == false and HasProtectedValue == false. Accessing Value or ProtectedValue on an empty instance throws InvalidOperationException.
- Utility helpers: ProtectedNumber.IsNullOrEmpty(ProtectedNumber?) and initialization helpers to ensure safe usage.
Where can I get it?
First, install NuGet. Then, install ProtectedNumbers from the package manager console:
PM> Install-Package ProtectedNumbers
Or from the .NET CLI as:
dotnet add package ProtectedNumbers
How do I get started?
- Add ProtectedNumbers services:
// ...
IServiceCollection services;
// ...
services.AddProtectedNumbers();
- Replace the property type from int/long to ProtectedNumber:
// Before
public class SomeViewModel
{
// ...
public long? Id { get; set; }
// ...
}
// After
public class SomeViewModel
{
// ...
public ProtectedNumbers? Id { get;set; }
// ...
}
- Example of json output from an api endpoint:
Before:
GET http://localhost:5000/minimal-api/samples-objects/4018378694012108869
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"id": "4018378694012108869",
"name": "some data row"
}
After:
GET http://localhost:5000/minimal-api/samples-objects/CfDJ8K3W-Fa_koRAlAI935b9MJiwgpOlgJ5oj2hPOyJZZFqlHZB7JZKF5ccvazbH8_u4rtp1Ek-orXITi05_0MFOGj0Erm77rxFfpBQcfHVk04M-eaTiWkTNm54PwtmSdEZY5Iy9pGCCo_fYsFj2K54T89c
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"id": "CfDJ8K3W-Fa_koRAlAI935b9MJjgVrkgEMGZ5bvAPECdKZvgMpUPsvhVru9een2MVC0P8e4N4ehwgKgueAGjZlEP4s7gu3AsBLRoQrnUZr8hw4qZYAr-StAlQWCfx2FHTs1EGgEpB3T9YPSGxAxm0XVP7Mc",
"name": "some data row"
}
Do you have an issue?
If you're still running into problems, file an issue above.
License, etc.
ProtectedNumbers is Copyright © 2025 Grégory Célet under the MIT license.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 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. |
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
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.1 | 118 | 8/31/2025 |
• Fixed bugs