SimpleBase 5.3.0

dotnet add package SimpleBase --version 5.3.0
                    
NuGet\Install-Package SimpleBase -Version 5.3.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="SimpleBase" Version="5.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SimpleBase" Version="5.3.0" />
                    
Directory.Packages.props
<PackageReference Include="SimpleBase" />
                    
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 SimpleBase --version 5.3.0
                    
#r "nuget: SimpleBase, 5.3.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.
#addin nuget:?package=SimpleBase&version=5.3.0
                    
Install SimpleBase as a Cake Addin
#tool nuget:?package=SimpleBase&version=5.3.0
                    
Install SimpleBase as a Cake Tool

SimpleBase

NuGet Version Build Status

This is my own take for exotic base encodings like Base32, Base58 and Base85. I started to write it in 2013 as coding practice and kept it as a small pet project. I suggest anyone who wants to brush up their coding skills to give those encoding problems a shot. They turned out to be more challenging than I expected. To grasp the algorithms I had to get a pen and paper to see how the math worked.

Features

  • Multibase support. All formats covered by SimpleBase including a few Base64 variants are supported. Base2, Base8, and Base10 are also supported.
  • Base32: RFC 4648, BECH32, Crockford, z-base-32, Geohash, FileCoin and Extended Hex (BASE32-HEX) flavors with Crockford character substitution, or any other custom flavors.
  • Base36: Both lowercase and uppercase alphabets are supported.
  • Base45: RFC 9285 is supported.
  • Base58: All the standard (Bitcoin (BTC), Ripple (XRP), Monero (XMR)) and custom Base58 encoding methods are supported. Also provides Base58Check and Avalanche (AVAX) CB58 encoding/decoding helpers.
  • Base62: The standard Base62 encoding/decoding supported along with a custom alphabet.
  • Base85: Ascii85, Z85 and custom flavors. IPv6 encoding/decoding support.
  • Base16: UpperCase, LowerCase and ModHex flavors. An experimental hexadecimal encoder/decoder just to see how far I can take the optimizations compared to .NET's implementations. It's quite fast now, but .NET has Convert.FromHexString() method since .NET 5. This is mostly a baseline implementation now (except for when you need ModHex).
  • Base256 Emoji🚀: Supported by Multibase, and can also be used individually.
  • One-shot memory buffer based APIs for simple use cases.
  • Stream-based async APIs for more advanced scenarios.
  • Lightweight: No dependencies.
  • Support for big-endian CPUs like IBM s390x (zArchitecture).
  • Thread-safe.
  • Simple to use.

NuGet

To install it from NuGet:

Install-Package SimpleBase

Usage

The basic usage for encoding a buffer into, say, Base32, is as simple as:

using SimpleBase;

byte[] myBuffer;
string result = Base32.Crockford.Encode(myBuffer, padding: true);
// you can also use "ExtendedHex" or "Rfc4648" as encoder flavors

Decoding is also similar:

using SimpleBase;

string myText = ...
byte[] result = Base32.Crockford.Decode(myText);

See the wiki for more types of examples and full documentation.

Benchmark Results

Small buffer sizes are used (64 characters). They are closer to real life applications. Base58 performs really bad in decoding of larger buffer sizes, due to polynomial complexity of numeric base conversions.

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.4061) AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores .NET SDK 9.0.300 [Host] : .NET 8.0.16 (8.0.1625.21506), X64 RyuJIT AVX2 DefaultJob : .NET 8.0.16 (8.0.1625.21506), X64 RyuJIT AVX2

Encoding (64 byte buffer)

Method Mean Error StdDev Gen0 Allocated
DotNet_Base64 29.82 ns 0.644 ns 0.924 ns 0.0119 200 B
Base2_Default 235.29 ns 4.472 ns 6.413 ns 0.0625 1048 B
Base8_Default 126.04 ns 2.556 ns 3.903 ns 0.0224 376 B
Base16_UpperCase 82.37 ns 1.667 ns 1.920 ns 0.0167 280 B
Multibase_Base16_UpperCase 107.22 ns 2.102 ns 4.197 ns 0.0334 560 B
Base32_CrockfordWithPadding 156.90 ns 1.599 ns 1.335 ns 0.0138 232 B
Base36_LowerCase 47.26 ns 0.874 ns 0.898 ns 0.0091 152 B
Base45_Default 123.42 ns 1.853 ns 1.642 ns 0.0129 216 B
Base58_Bitcoin 47.16 ns 0.989 ns 1.177 ns 0.0091 152 B
Base58_Monero 207.06 ns 1.920 ns 1.796 ns 0.0119 200 B
Base62_Default 46.39 ns 0.509 ns 0.476 ns 0.0091 152 B
Base85_Z85 163.01 ns 1.226 ns 1.024 ns 0.0110 184 B
Base256Emoji_Default 230.50 ns 4.505 ns 4.214 ns 0.0167 280 B

Decoding (80 character string, except Base45 which must use an 81 character string)

Method Mean Error StdDev Gen0 Gen1 Allocated
DotNet_Base64 102.24 ns 0.234 ns 0.219 ns 0.0052 - 88 B
Base2_Default 102.95 ns 0.074 ns 0.070 ns 0.0024 - 40 B
Base8_Default 103.41 ns 0.199 ns 0.176 ns 0.0024 - 40 B
Base16_UpperCase 50.60 ns 0.931 ns 0.777 ns 0.0038 - 64 B
Base16_UpperCase_TextReader 275.90 ns 2.852 ns 2.381 ns 0.5007 0.0153 8376 B
Multibase_Base16_UpperCase 51.73 ns 0.254 ns 0.238 ns 0.0038 - 64 B
Multibase_TryDecode_Base16_UpperCase 46.95 ns 0.265 ns 0.235 ns - - -
Base32_Crockford 126.78 ns 1.751 ns 1.552 ns 0.0048 - 80 B
Base36_LowerCase 4,160.01 ns 65.532 ns 54.722 ns - - 80 B
Base45_Default 73.56 ns 1.248 ns 1.167 ns 0.0048 - 80 B
Base58_Bitcoin 4,544.46 ns 89.449 ns 133.882 ns - - 88 B
Base58_Monero 107.88 ns 0.408 ns 0.341 ns 0.0052 - 88 B
Base62_Default 4,500.24 ns 7.457 ns 6.610 ns - - 88 B
Base85_Z85 256.92 ns 0.580 ns 0.514 ns 0.0052 - 88 B
Base256Emoji_Default 287.68 ns 1.634 ns 1.528 ns 0.0062 - 104 B

Notes

I'm sure there are areas for improvement. I didn't want to go further in optimizations which would hurt readability and extensibility. I might experiment on them in the future.

Test suite for Base32 isn't complete, I took most of it from RFC4648. Base58 really lacks a good spec or test vectors needed. I had to resort to using online converters to generate preliminary test vectors.

Base85 tests are also makseshift tests based on what output Cryptii produces. Contribution to missing test cases are greatly appreciated.

It's interesting that I wasn't able to reach .NET Base64's performance with Base16 with a straightforward managed code despite that it's much simpler. I was only able to match it after I converted Base16 to unsafe code with good independent interleaving so CPU pipeline optimizations could take place. Still not satisfied though. Is .NET's Base64 implementation native? Perhaps.

Thanks

Thanks to all contributors who provided patches, and reported bugs.

Chatting about this pet project with my friends @detaybey, @vhallac, @alkimake and @Utopians at one of our friend's birthday encouraged me to finish this. Thanks guys.

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 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 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.

NuGet packages (53)

Showing the top 5 NuGet packages that depend on SimpleBase:

Package Downloads
Makaretu.Dns

DNS data model with serializer/deserializer for the wire and master file format.

KubeOps

This is an operator sdk written in c#. It enables a developer to create a custom controller for CRDs (CustomResourceDefinitions) that runs on kubernetes.

Ipfs.Core

Core objects and interfaces for IPFS. The InterPlanetary File System is the permanent web. It is a new hypermedia distribution protocol, addressed by content and identities. IPFS enables the creation of completely distributed applications. It aims to make the web faster, safer, and more open.

SubstrateNetApi

Just another Substrate .NET API, written in NETStandard2.0 to provide maximum compatibility for Unity3D.

Nethermind.Libp2p.Core

A libp2p implementation for .NET

GitHub repositories (8)

Showing the top 8 popular GitHub repositories that depend on SimpleBase:

Repository Stars
stratumauth/app
📱 Two-Factor Authentication (2FA) client for Android + Wear OS
unosquare/passcore
A self-service password management tool for Active Directory
TeslaFly01/SmartSqlT
🔥🔥🔥 SmartSQL 是一款方便、快捷的数据库文档查询、导出工具!该工具从最初支持CHM文档格式开始,通过不断地探索开发、集思广益和不断改进,又陆续支持Word、Excel、PDF、Html、Xml、Json、MarkDown等文档格式的导出。同时支持SqlServer、MySql、PostgreSQL、SQLite等多种数据库的文档查询和导出功能。
slowscript/warpinator-windows
An unofficial implementation of Warpinator for Windows
BasisVR/Basis
Basis is an open-source social framework for VR and Desktop usage.
richardschneider/net-ipfs-mount
Mount the InterPlanetary File System as a mapped drive on Windows
bizanc/Bizanc.io.Core
Bizanc Blockchain
richardschneider/net-ipfs-core
The core objects and interfaces of the interplanetary file system (IPFS)
Version Downloads Last updated
5.3.0 0 14 hours ago
5.2.0 2,195 7 days ago
5.1.0 167 7 days ago
5.0.0 556 10 days ago
4.3.0 4,930 14 days ago
4.2.0 3,712 20 days ago
4.0.2 280,143 8 months ago
4.0.1 13,192 8 months ago
4.0.0 1,179,724 11/10/2022
3.1.0 709,872 5/24/2021
3.0.3 1,413 5/24/2021
3.0.2 121,004 12/11/2020
3.0.1 94,739 2/14/2020
3.0.0 19,390 12/24/2019
2.1.0 537,438 1/21/2020
2.0.0 26,490 10/12/2019
1.8.0 101,733 3/20/2019
1.7.1 52,480 12/4/2018
1.6.1 15,596 7/13/2018
1.4.1 5,343 5/30/2018
1.3.1 856,769 7/27/2017
1.3.0 1,767 7/26/2017
1.2.0 40,381 5/19/2016
1.1.1 79,130 5/18/2016
1.1.0 2,336 5/16/2016

## New features
- AOT and trimming compatibility
- Base2, Base8, and Base10 support

## Improvements
- `Base58` now uses `DividingCoder` under the hood for less code duplication
- Several implementations now take bytesWritten into account when returning buffers, reducing the possibility of returning a buffer larger than necessary.