libcnpj 1.0.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package libcnpj --version 1.0.0
                    
NuGet\Install-Package libcnpj -Version 1.0.0
                    
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="libcnpj" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="libcnpj" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="libcnpj" />
                    
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 libcnpj --version 1.0.0
                    
#r "nuget: libcnpj, 1.0.0"
                    
#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 libcnpj@1.0.0
                    
#: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=libcnpj&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=libcnpj&version=1.0.0
                    
Install as a Cake Tool

LibCnpj

LibCnpj, a simple library for generating and validating Brazil's CNPJ.
Copyright (C) 2026 Daniel Augusto
SPDX-License-Identifier: LGPL-2.0-only or BSD-3-Clause (at your choice)

Features

  • Flexibility, allows performing both Alphanumeric (newer rule, official) and Relaxed Alphanumeric (newer rule, non-official) document generation and validation, where the latter is provided as a convenience in order to avoid unnecessary string allocations with case conversions prior to knowing if a document is even valid (aka.: when using this mode, you can first validate and then, only if valid, convert the input string to uppercase).
  • Retrocompatibility, allows performing Numeric document generation and validation (older rule, official).
  • Economy, single string allocation during the generation process and zero regex matching and zero string allocation during the validation process (just plain character comparisons and digit calculations based on their respective weights).

Getting Started

Below a suggestion on how to use this library for a project that uses dependency injection.

  1. Configure and Register, using your favourite validation rule (or most often, the proper business rule).
// Example 1: When only alphanumeric generation or validation is needed, registered once.
public static class MyServices
{
    private static void AddMyServices(IServiceCollection services)
    {
        // Register only what you'll use.
        services.AddSingleton<ICnpjGenerator>(new CnpjGenerator(CnpjFormat.Alphanumeric));
        services.AddSingleton<ICnpjValidator>(new CnpjValidator(CnpjFormat.Alphanumeric));
    }
}

// Example 2: When both alphanumeric and numeric generation or validation is needed, registered as different keyed services.
public static class MyServices
{
    private static void AddMyServices(IServiceCollection services)
    {
        // Register only what you'll use.
        services.AddKeyedSingleton<ICnpjGenerator>(
            CnpjFormat.Alphanumeric,
            new CnpjGenerator(CnpjFormat.Alphanumeric));

        services.AddKeyedSingleton<ICnpjGenerator>(
            CnpjFormat.Numeric,
            new CnpjGenerator(CnpjFormat.Numeric));

        services.AddKeyedSingleton<ICnpjValidator>(
            CnpjFormat.Alphanumeric,
            new CnpjValidator(CnpjFormat.Alphanumeric));

        services.AddKeyedSingleton<ICnpjValidator>(
            CnpjFormat.Numeric,
            new CnpjValidator(CnpjFormat.Numeric));
    }
}
  1. Use, injecting it where appropriate.
// Example 1: When only alphanumeric generation or validation is needed, registered once.
public class MyClass(
    // Inject only what you'll use.
    ICnpjGenerator cnpjGenerator,
    ICnpjValidator cnpjValidator)
{
    public void MyGenerationMethod()
    {
        var document = cnpjGenerator.Generate();

        // Wow! Such generated.
    }

    public void MyValidationMethod(string document)
    {
        if (!cnpjValidator.IsValid(document))
        {
            // Wow! Very error, must handle.
        }

        // Wow! Much validated.
    }
}

// Example 2: When both alphanumeric and numeric generation or validation is needed, registered as different keyed services.
public class MyClass(
    // Inject only what you'll use.
    [FromKeyedServices(CnpjFormat.Alphanumeric)] ICnpjGenerator alphanumericCnpjGenerator,
    [FromKeyedServices(CnpjFormat.Numeric)] ICnpjGenerator numericCnpjGenerator,
    [FromKeyedServices(CnpjFormat.Alphanumeric)] ICnpjValidator alphanumericCnpjValidator,
    [FromKeyedServices(CnpjFormat.Numeric)] ICnpjValidator numericCnpjValidator))
{
    public void MyAlphanumericGenerationMethod()
    {
        var document = alphanumericCnpjGenerator.Generate();

        // Wow! Such generated.
    }

    public void MyNumericGenerationMethod()
    {
        var document = numericCnpjGenerator.Generate();

        // Wow! Such generated.
    }

    public void MyAlphanumericValidationMethod(string document)
    {
        if (!alphanumericCnpjValidator.IsValid(document))
        {
            // Wow! Very error. Must handle.
        }

        // Wow! Much validated.
    }

    public void MyNumericValidationMethod(string document)
    {
        if (!numericCnpjValidator.IsValid(document))
        {
            // Wow! Very error. Must handle.
        }

        // Wow! Much validated.
    }
}

Benchmark

Generator

Below a sample execution of the implemented benchmarks.

BenchmarkDotNet v0.15.8, Linux Debian GNU/Linux 13 (trixie)
Intel Pentium Silver J5040 CPU 2.00GHz (Max: 3.00GHz), 1 CPU, 4 logical and 4 physical cores
.NET SDK 10.0.302
  [Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v2
  DefaultJob : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v2


| Method                              | Mean     | Error   | StdDev  | Gen0   | Allocated |
|------------------------------------ |---------:|--------:|--------:|-------:|----------:|
| AlphanumericRelaxedWithoutSeparator | 416.8 ns | 1.14 ns | 1.01 ns | 0.0267 |      56 B |
| AlphanumericRelaxedWithSeparator    | 483.0 ns | 1.85 ns | 1.73 ns | 0.0305 |      64 B |
| AlphanumericWithoutSeparator        | 374.3 ns | 1.74 ns | 1.62 ns | 0.0267 |      56 B |
| AlphanumericWithSeparator           | 411.2 ns | 1.21 ns | 1.13 ns | 0.0305 |      64 B |
| NumericWithoutSeparator             | 241.1 ns | 0.43 ns | 0.40 ns | 0.0267 |      56 B |
| NumericWithSeparator                | 296.9 ns | 0.93 ns | 0.87 ns | 0.0305 |      64 B |

Validator

Below a sample execution of the implemented benchmarks in order to compare both the published implementation and the transliterated version used as a baseline.

BenchmarkDotNet v0.15.8, Linux Debian GNU/Linux 13 (trixie)
Intel Pentium Silver J5040 CPU 2.00GHz (Max: 3.00GHz), 1 CPU, 4 logical and 4 physical cores
.NET SDK 10.0.302
  [Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v2
  DefaultJob : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v2

| Method                                     | value              | Mean       | Error    | StdDev   | Gen0   | Allocated |
|------------------------------------------- |------------------- |-----------:|---------:|---------:|-------:|----------:|
| AlphanumericRelaxedWithoutSeparator        | 285hw5pl000112     |   145.7 ns |  0.23 ns |  0.20 ns |      - |         - |
| AlphanumericRelaxedWithoutSeparator        | 285HW5PL000112     |   135.9 ns |  0.43 ns |  0.38 ns |      - |         - |
| AlphanumericRelaxedWithoutSeparator        | 40416464000106     |   150.8 ns |  1.47 ns |  1.37 ns |      - |         - |
| AlphanumericRelaxedWithSeparator           | 28.5hw.5pl/0001-12 |   195.2 ns |  2.13 ns |  2.00 ns |      - |         - |
| AlphanumericRelaxedWithSeparator           | 28.5HW.5PL/0001-12 |   174.7 ns |  0.82 ns |  0.72 ns |      - |         - |
| AlphanumericRelaxedWithSeparator           | 40.416.464/0001-06 |   193.5 ns |  2.36 ns |  2.09 ns |      - |         - |
| AlphanumericWithoutSeparator               | 285HW5PL000112     |   131.1 ns |  0.19 ns |  0.18 ns |      - |         - |
| AlphanumericWithoutSeparator               | 40416464000106     |   141.0 ns |  0.21 ns |  0.19 ns |      - |         - |
| AlphanumericWithSeparator                  | 28.5HW.5PL/0001-12 |   176.2 ns |  0.66 ns |  0.62 ns |      - |         - |
| AlphanumericWithSeparator                  | 40.416.464/0001-06 |   196.2 ns |  0.55 ns |  0.51 ns |      - |         - |
| NumericWithoutSeparator                    | 40416464000106     |   128.0 ns |  0.52 ns |  0.48 ns |      - |         - |
| NumericWithSeparator                       | 40.416.464/0001-06 |   171.8 ns |  0.30 ns |  0.27 ns |      - |         - |
| TransliteratedAlphanumericWithoutSeparator | 285HW5PL000112     | 1,867.9 ns |  4.28 ns |  4.00 ns | 0.5035 |    1056 B |
| TransliteratedAlphanumericWithoutSeparator | 40416464000106     | 1,883.9 ns |  5.69 ns |  5.05 ns | 0.5035 |    1056 B |
| TransliteratedAlphanumericWithSeparator    | 28.5HW.5PL/0001-12 | 2,451.7 ns |  6.71 ns |  5.24 ns | 0.5302 |    1112 B |
| TransliteratedAlphanumericWithSeparator    | 40.416.464/0001-06 | 2,477.5 ns | 18.97 ns | 17.74 ns | 0.5302 |    1112 B |
| TransliteratedNumericWithoutSeparator      | 40416464000106     | 1,874.6 ns |  5.37 ns |  5.02 ns | 0.5035 |    1056 B |
| TransliteratedNumericWithSeparator         | 40.416.464/0001-06 | 2,410.8 ns |  9.45 ns |  8.38 ns | 0.5302 |    1112 B |

Q&A

Even though nobody asked (as of now), I strongly suggest that you don't even waste your time reading it.

Q: Why did you do it?
A: I am working on another project and validating documents will be necessary, so why not.

Q: Why did you implement it the way you did?
A: I transliterated the reference implementation from Java to C# and, on doing that, noticed that it doesn't allow validating documents with separators, which would result in an allocation for their removal for validation and then, noticed that it doesn't allow validating documents whose alphabetic characters are lowercase, which would result in an allocation for their conversion.

I thought that it would be nice both if it was possible to ensure that the separators themselves are also valid and if one could avoid these allocations prior to even knowing that the document is valid since when working with systems that receive lots of information, this makes a difference. Then implemented in another way, measured both implementations and was satisfied enough with the results to publish it, maybe somehow it will be someday useful to someone, somewhere.

So basically scratching a personal itch.

Q: Why did you compare character ranges directly instead of using functions from System.Char?
A: While experimenting with the transliteration, I noticed that some functions that I would have to implement such as IsDot were considerably faster when invoked in comparison and decided to explore the source code. There are are additional calls involved reusing IsBetween, so I took a bet on skipping them, since in C# characters and strings are UTF-16, ASCII overlaps with it, and ASCII is all that is accepted in a CNPJ, checking by range seems reasonable instead of the more general purpose implementation provided there.

So basically scratching another personal itch (found a bug? report it!).

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