ProtectedNumbers 0.1.1

dotnet add package ProtectedNumbers --version 0.1.1
                    
NuGet\Install-Package ProtectedNumbers -Version 0.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ProtectedNumbers" Version="0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ProtectedNumbers" Version="0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="ProtectedNumbers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ProtectedNumbers --version 0.1.1
                    
#r "nuget: ProtectedNumbers, 0.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ProtectedNumbers@0.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ProtectedNumbers&version=0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=ProtectedNumbers&version=0.1.1
                    
Install as a Cake Tool

<div align="center">

<img src="PackageIcon.png" alt="ProtectedNumbers" width="150px"/>

ProtectedNumbers

alternate text is missing from this package README image Coverage alternate text is missing from this package README image alternate text is missing from this package README image alternate text is missing from this package README image GitHub Repo stars GitHub contributors GitHub last commit GitHub commit activity open issues .NET PRs Welcome alternate text is missing from this package README image

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • 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