All Projects → paulmillr → scure-base

paulmillr / scure-base

Licence: MIT License
Secure, audited & 0-deps implementation of bech32, base64, base32, base16 & base58

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects
rust
11053 projects

Projects that are alternatives of or similar to scure-base

multibase
multi base encoding/decoding utility
Stars: ✭ 15 (-44.44%)
Mutual labels:  encoding, base64, decoding, base58
universal-base64
Small universal base64 functions for node.js and browsers
Stars: ✭ 25 (-7.41%)
Mutual labels:  encoding, base64, decoding
Decodify
Detect and decode encoded strings, recursively.
Stars: ✭ 670 (+2381.48%)
Mutual labels:  encoding, base64, decoding
BeFoR64
BeFoR64, Base64 encoding/decoding library for FoRtran poor men
Stars: ✭ 17 (-37.04%)
Mutual labels:  encoding, base64, decoding
js-multibase
JavaScript implementation of the multibase specification
Stars: ✭ 22 (-18.52%)
Mutual labels:  encoding, decoding, rfc4648
velvet-video
Java library for encoding / decoding / muxing / demuxing video and audio in various formats
Stars: ✭ 32 (+18.52%)
Mutual labels:  encoding, decoding
go-webp
Simple and fast webp library for golang
Stars: ✭ 91 (+237.04%)
Mutual labels:  encoding, decoding
btclib
btclib: a python3 library for 'bitcoin cryptography'
Stars: ✭ 60 (+122.22%)
Mutual labels:  base58, bech32
DjvuNet
DjvuNet is a cross platform fully managed .NET library for working with Djvu documents which can run on Linux, macOS and Windows. Library has been written in C# and targets .NET Core v3.0 and .NET Standard v2.1 or later. We intend to provide DjVu document processing capabilities on par with DjVuLibre reference library (or even better).
Stars: ✭ 54 (+100%)
Mutual labels:  encoding, decoding
tjson.js
JavaScript-compatible implementation of Tagged JSON (TJSON), written in TypeScript.
Stars: ✭ 53 (+96.3%)
Mutual labels:  base64, base16
cryptouri.rs
Rust implementation of CryptoURI: URN-like namespace for cryptographic objects with Bech32-based encoding
Stars: ✭ 33 (+22.22%)
Mutual labels:  encoding, bech32
vorbis aotuv
"aoTuV" is library for encoding and decoding of OggVorbis
Stars: ✭ 35 (+29.63%)
Mutual labels:  encoding, decoding
go-fixedwidth
Encoding and decoding for fixed-width formatted data
Stars: ✭ 64 (+137.04%)
Mutual labels:  encoding, decoding
d3coder
Chrome extension for encoding/decoding and hashing text on websites
Stars: ✭ 26 (-3.7%)
Mutual labels:  encoding, decoding
morton-nd
A header-only compile-time Morton encoding / decoding library for N dimensions.
Stars: ✭ 78 (+188.89%)
Mutual labels:  encoding, decoding
sms
A Go library for encoding and decoding SMSs
Stars: ✭ 37 (+37.04%)
Mutual labels:  encoding, decoding
cpp-bencoding
A C++ bencoding library supporting both decoding and encoding.
Stars: ✭ 20 (-25.93%)
Mutual labels:  encoding, decoding
sirdez
Glorious Binary Serialization and Deserialization for TypeScript.
Stars: ✭ 20 (-25.93%)
Mutual labels:  encoding, decoding
base58
Fast implementation of base58 encoding on golang.
Stars: ✭ 121 (+348.15%)
Mutual labels:  encoding, base58
BaseNcoding
Library for encoding of binary data into strings using base32, base85, base128 and other algorithms.
Stars: ✭ 42 (+55.56%)
Mutual labels:  encoding, base64

scure-base

Secure, audited and 0-dep implementation of bech32, base64, base58, base32 & base16.

Written in functional style, uses chaining, has unique tests which ensure correctness.

Matches following specs:

The library has been audited by Cure53 on Jan 5, 2022. Check out the audit PDF & URL. Before the audit, it was called micro-base.

This library belongs to scure

scure — secure audited packages for every use case.

  • Independent security audits
  • All releases are signed with PGP keys
  • Check out all libraries: base, bip32, bip39

Usage

npm install @scure/base

Or

yarn add @scure/base

const { base16, base32, base64, base58 } = require('@scure/base');
// Flavors
const { base58xmr, base58xrp, base32hex, base32crockford, base64url } = require('@scure/base');

const data = Uint8Array.from([1, 2, 3]);
base64.decode(base64.encode(data));

// Everything has the same API except for bech32 and base58check
base32.encode(data);
base16.encode(data);
base32hex.encode(data);

// bech32
const {bech32, bech32m} = require('@scure/base');
const words = bech32.toWords(data);
const be = bech32.encode('prefix', words);
const {prefix, words} = bech32.decode(be);
bech32m.encode('prefix', words);

// base58check is special-case
// you need to pass sha256() function that returns Uint8Array
const {base58check} = require('@scure/base');
base58check(sha256).encode(data);

// Alternative API
const {str, bytes} = require('@scure/base');
const encoded = str('base64', data);
const data = bytes('base64', encoded);

Design rationale

The code may feel unnecessarily complicated; but actually it's much easier to reason about. Any encoding library consists of two functions:

encode(A) -> B
decode(B) -> A
  where X = decode(encode(X))
  # encode(decode(X)) can be !== X!
  # because decoding can normalize input

e.g.
base58checksum = {
  encode(): {
    // checksum
    // radix conversion
    // alphabet
  },
  decode(): {
    // alphabet
    // radix conversion
    // checksum
  }
}

But instead of creating two big functions for each specific case, we create them from tiny composamble building blocks:

base58checksum = chain(checksum(), radix(), alphabet())

Which is the same as chain/pipe/sequence function in Functional Programming, but significantly more useful since it enforces same order of execution of encode/decode. Basically you only define encode (in declarative way) and get correct decode for free. So, instead of reasoning about two big functions you need only reason about primitives and encode chain. The design revealed obvious bug in older version of the lib, where xmr version of base58 had errors in decode's block processing.

Besides base-encodings, we can reuse the same approach with any encode/decode function (bytes2number, bytes2u32, etc). For example, you can easily encode entropy to mnemonic (BIP-39):

export function getCoder(wordlist: string[]) {
  if (!Array.isArray(wordlist) || wordlist.length !== 2 ** 11 || typeof wordlist[0] !== 'string') {
    throw new Error('Worlist: expected array of 2048 strings');
  }
  return mbc.chain(mbu.checksum(1, checksum), mbu.radix2(11, true), mbu.alphabet(wordlist));
}

base58 is O(n^2) and radixes

Uint8Array is represented as big-endian number:

[1, 2, 3, 4, 5] -> 1*(256**4) + 2*(256**3) 3*(256**2) + 4*(256**1) + 5*(256**0)
where 256 = 2**8 (8 bits per byte)

which is then converted to a number in another radix/base (16/32/58/64, etc).

However, generic conversion between bases has quadratic O(n^2) time complexity.

Which means base58 has quadratic time complexity too. Use base58 only when you have small constant sized input, because variable length sized input from user can cause DoS.

On the other hand, if both bases are power of same number (like 2**8 <-> 2**64), there is linear algorithm. For now we have implementation for power-of-two bases only (radix2).

License

MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.

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