All Projects → ssg → Simplebase

ssg / Simplebase

Licence: apache-2.0
.NET library for encoding/decoding Base16, Base32, Base58 and Base85.

Projects that are alternatives of or similar to Simplebase

Appdepends Ios
🔍 搜集热门APP,列举其所依赖和使用的开源库。
Stars: ✭ 27 (-57.81%)
Mutual labels:  libraries
Django Icekit
GLAMkit is a next-generation Python CMS by the Interaction Consortium, designed especially for the cultural sector.
Stars: ✭ 42 (-34.37%)
Mutual labels:  libraries
Qs
Go module for encoding structs into URL query parameters
Stars: ✭ 55 (-14.06%)
Mutual labels:  encoding
X509
A PHP library for X.509 public key certificates, attribute certificates, certification requests and certification path validation.
Stars: ✭ 27 (-57.81%)
Mutual labels:  encoding
Iocane
An odorless, tasteless NodeJS crypto library that dissolves instantly in liquid
Stars: ✭ 35 (-45.31%)
Mutual labels:  encoding
Inqlude Data
Library meta data for independent Qt library archive
Stars: ✭ 44 (-31.25%)
Mutual labels:  libraries
Netbeans Encoding Plugin
Encoding Support
Stars: ✭ 20 (-68.75%)
Mutual labels:  encoding
Bincode
A binary encoder / decoder implementation in Rust.
Stars: ✭ 1,100 (+1618.75%)
Mutual labels:  encoding
Rxdownloader
- Reactive Extension Library for Android to download files
Stars: ✭ 40 (-37.5%)
Mutual labels:  libraries
Ffmpeg Encoding Course
An introduction to FFmpeg and its tools
Stars: ✭ 53 (-17.19%)
Mutual labels:  encoding
Rust Multibase
Multibase in rust
Stars: ✭ 30 (-53.12%)
Mutual labels:  encoding
Cryptii
Web app and framework offering modular conversion, encoding and encryption
Stars: ✭ 971 (+1417.19%)
Mutual labels:  encoding
Turkishid
Validator/generator for Turkish Republic Citizen ID numbers (TC Kimlik No)
Stars: ✭ 49 (-23.44%)
Mutual labels:  libraries
Bcnencoder.net
Cross-platform texture encoding libary for .NET. With support for BC1-3/DXT, BC4-5/RGTC and BC7/BPTC compression. Outputs files in ktx or dds formats.
Stars: ✭ 28 (-56.25%)
Mutual labels:  encoding
Php Sdk
Transloadit's official PHP SDK
Stars: ✭ 55 (-14.06%)
Mutual labels:  encoding
Awesome Cpp
A curated list of awesome C++ (or C) frameworks, libraries, resources, and shiny things. Inspired by awesome-... stuff.
Stars: ✭ 35,136 (+54800%)
Mutual labels:  libraries
Vsad
this is the code release for ''Weakly Supervised PatchNets: Describing and Aggregating Local Patches for Scene Recognition''
Stars: ✭ 44 (-31.25%)
Mutual labels:  encoding
Yacr
Yet another CSV Reader
Stars: ✭ 62 (-3.12%)
Mutual labels:  encoding
Idna Convert
Pure PHP IDNA Converter
Stars: ✭ 58 (-9.37%)
Mutual labels:  encoding
Fast ber
A C++11 ASN.1 BER Encoding and Decoding Library
Stars: ✭ 54 (-15.62%)
Mutual labels:  encoding

SimpleBase

NuGet Version Build Status 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

  • Base32: RFC 4648, Crockford, z-base-32, Geohash and Extended Hex (BASE32-HEX) flavors with Crockford character substitution, or any other custom flavors.
  • Base58: Bitcoin, Ripple, Flickr and custom flavors.
  • Base85: Ascii85, Z85 and custom flavors.
  • 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. It can also be used as a replacement for SoapHexBinary.Parse method since it's missing from .NET Core.
  • One-shot memory buffer based APIs for simple use cases.
  • Stream-based async APIs for more advanced scenarios.
  • Lightweight: No third-party dependencies (depends only on System.Memory package)
  • Thread-safe.
  • Simple to use.

NuGet

To install it from NuGet:

Install-Package SimpleBase

Usage

Base32

Encode a byte array:

using SimpleBase;

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

Decode a Base32-encoded string:

using SimpleBase;

string myText = ...
Span<byte> result = Base32.Crockford.Decode(myText);
// Span<byte> is analogous to byte[] in usage but allows the library
// to avoid unnecessary memory copy operations unless needed.
// you can also use "ExtendedHex" or "Rfc4648" as decoder flavors

Base58

Encode a byte array:

byte[] myBuffer = ...
string result = Base58.Bitcoin.Encode(myBuffer);
// you can also use "Ripple" or "Flickr" as encoder flavors

Decode a Base58-encoded string:

string myText = ...
Span<byte> result = Base58.Bitcoin.Decode(myText);
// Span<byte> is analogous to byte[] in usage but allows the library
// to avoid unnecessary memory copy operations unless needed.
// you can also use "Ripple" or "Flickr" as decoder flavors

Base85

Encode a byte array to Ascii85 string:

byte[] myBuffer = ...
string result = Base85.Ascii85.Encode(myBuffer);
// you can also use Z85 as a flavor

Decode an encoded Ascii85 string:

string encodedString = ...
Span<byte> result = Base85.Ascii85.Decode(encodedString);
// Span<byte> is analogous to byte[] in usage but allows the library
// to avoid unnecessary memory copy operations unless needed.
// you can also use Z85 as a flavor

Both "zero" and "space" shortcuts are supported for Ascii85. Z85 is still vanilla.

Base16

Encode a byte array to hex string:

byte[] myBuffer = ...
string result = Base16.EncodeUpper(myBuffer); // encode to uppercase
// or 
string result = Base16.EncodeLower(myBuffer); // encode to lowercase

To decode a valid hex string:

string text = ...
Span<byte> result = Base16.Decode(text); // decodes both upper and lowercase
// Span<byte> is analogous to byte[] in usage but allows the library
// to avoid unnecessary memory copy operations unless needed.

Stream Mode

Most encoding classes also support a stream mode that can work on streams, be it a network connection, a file or whatever you want. They are ideal for handling arbitrarily large data as they don't consume memory other than a small buffer when encoding or decoding. Their syntaxes are mostly identical. Text encoding decoding is done through a TextReader/TextWriter and the rest is read through a Stream interface. Here is a simple code that encodes a file to another file using Base85 encoding:

using (var input = File.Open("somefile.bin"))
using (var output = File.Create("somefile.ascii85"))
using (var writer = new TextWriter(output)) // you can specify encoding here
{
  Base85.Ascii85.Encode(input, writer);
}

Decode works similarly. Here is a Base32 file decoder:

using (var input = File.Open("somefile.b32"))
using (var output = File.Create("somefile.bin"))
using (var reader = new TextReader(input)) // specify encoding here
{
	Base32.Crockford.Decode(reader, output);
}

Asynchronous Stream Mode

You can also encode/decode streams in asynchronous fashion:

using (var input = File.Open("somefile.bin"))
using (var output = File.Create("somefile.ascii85"))
using (var writer = new TextWriter(output)) // you can specify encoding here
{
  await Base85.Ascii85.EncodeAsync(input, writer);
}

And the decode:

using (var input = File.Open("somefile.b32"))
using (var output = File.Create("somefile.bin"))
using (var reader = new TextReader(input)) // specify encoding here
{
	await Base32.Crockford.DecodeAsync(reader, output);
}

TryEncode/TryDecode

If you want to use an existing pre-allocated buffer to encode or decode without causing a GC allocation every time, you can make use of TryEncode/TryDecode methods which receive input, output buffers as parameters.

Encoding is like this:

byte[] input = new byte[] { 1, 2, 3, 4, 5 };
int outputBufferSize = Base58.Bitcoin.GetSafeCharCountForEncoding(input);
var output = new char[outputBufferSize];

if (Base58.Bitcoin.TryEncode(input, output, out int numCharsWritten))
{
   // there you go
}

and decoding:

string input = "... some bitcoin address ...";
int outputBufferSize = Base58.Bitcoin.GetSafeByteCountForDecoding(output);
var output = new byte[outputBufferSize];

if (Base58.Bitcoin.TryDecode(input, output, out int numBytesWritten))
{
    // et voila!
}

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.

64 byte buffer for encoding 80 character string for decoding

Implementation Growth Encode Decode
.NET Framework Base64 1.33x 0.44µs 0.71µs
SimpleBase Base16 2x 0.59µs (1.4x slower) 0.43µs (1.7x faster! YAY!)
SimpleBase Base32 Crockford 1.6x 1.35µs (3.1x slower) 1.07µs (1.5x slower)
SimpleBase Base85 Z85 1.25x 1.00µs (2.3x slower) 1.86µs (2.6x slower)
SimpleBase Base58 1.38x 29.99µs (68.6x slower) 31.36µs (44.1x slower)

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

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. Special thanks to my wife Günyüz for unlimited tea and love.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].