Crate bech32

source ·
Expand description

Encoding and decoding of the Bech32 format.

Bech32 is an encoding scheme that is easy to use for humans and efficient to encode in QR codes.

A Bech32 string consists of a human-readable part (HRP), a separator (the character '1'), and a data part. A checksum at the end of the string provides error detection to prevent mistakes when the string is written off or read out loud.


  • If you are doing segwit stuff you likely want to use the segwit API.
  • Non-segwit stuff and you have an allocator, use the top level API. For normal usage the encode and decode functions should suffice. There are also various other functions for explicit control of the checksum algorithm and the case used when encoding.
  • Non-segwit stuff and you do not have an allocator, use the CheckedHrpstring type for decoding. For encoding we provide various top level functions of the form encode*_to_fmt.
  • To define your own checksum algorithm implement Checksum (see example below).

The original description in BIP-173 has more details. See also BIP-350.

§Deviation from spec

We do not enforce the 90 character limit specified by BIP-173, instead we enforce the code length for the respective checksum algorithm (see Checksum::CODE_LENGTH). We do however enforce the 90 character limit within the segwit modules and types.



use bech32::{hrp, segwit, Hrp, Bech32m};

const DATA: [u8; 20] = [0xab; 20]; // Arbitrary data to be encoded.
const STRING: &str = "abc14w46h2at4w46h2at4w46h2at4w46h2at958ngu";
const TAP_ADDR: &str = "bc1p4w46h2at4w46h2at4w46h2at4w46h2at5kreae";

// Encode arbitrary data using "abc" as the human-readable part and append a bech32m checksum.
let hrp = Hrp::parse("abc").expect("valid hrp");
let string = bech32::encode::<Bech32m>(hrp, &DATA).expect("failed to encode string");
assert_eq!(string, STRING);

// Encode arbitrary data as a Bitcoin taproot address.
let taproot_address = segwit::encode(hrp::BC, segwit::VERSION_1, &DATA).expect("valid witness version and program");
assert_eq!(taproot_address, TAP_ADDR);

// No-alloc: Encode without allocating (ignoring that String::new() allocates :).
let mut buf = String::new();
bech32::encode_to_fmt::<Bech32m, String>(&mut buf, hrp, &DATA).expect("failed to encode to buffer");
assert_eq!(buf, STRING);


use bech32::primitives::decode::{CheckedHrpstring, SegwitHrpstring};
use bech32::{hrp, segwit, Hrp, Bech32m};

const DATA: [u8; 20] = [0xab; 20]; // Arbitrary data to be encoded.
const STRING: &str = "abc14w46h2at4w46h2at4w46h2at4w46h2at958ngu";
const TAP_ADDR: &str = "bc1p4w46h2at4w46h2at4w46h2at4w46h2at5kreae";

// Decode a bech32 encoded string that includes a bech32/bech32m checksum.
// The input address MUST include a valid bech32 or bech32m checksum, for individual specific
// checksum algorithms see [`decode_bech32`], [`decode_bech32m`], [`decode_no_checksum`] or use
// the [`primitives::decode::CheckedHrpstring`] type directly.
let (hrp, data) = bech32::decode(&STRING).expect("failed to decode");
assert_eq!(hrp, Hrp::parse("abc").unwrap());
assert_eq!(data, DATA);

// Decode a Bitcoin taproot address.
let (_hrp, _version, program) = segwit::decode(&TAP_ADDR).expect("valid address");
assert_eq!(program, DATA);

// No-alloc: Decode a bech32m checksummed address without allocating.
let p = CheckedHrpstring::new::<Bech32m>(&STRING).expect("failed to parse string");
assert_eq!(hrp, p.hrp());
assert!(p.byte_iter().eq(DATA.iter().map(|&b| b))); // We yield bytes not references.

// No-alloc: Decode a taproot address without allocating.
let taproot = SegwitHrpstring::new(&TAP_ADDR).expect("valid address");
// Do something with the encoded data.
let _ = taproot.byte_iter();

§Custom Checksum

use bech32::Checksum;

/// The codex32 checksum algorithm, defined in BIP-93.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Codex32 {}

impl Checksum for Codex32 {
    type MidstateRepr = u128;
    const CHECKSUM_LENGTH: usize = 13;
    const CODE_LENGTH: usize = 93;
    // Copied from BIP-93
    const GENERATOR_SH: [u128; 5] = [
    const TARGET_RESIDUE: u128 = 0x10ce0795c2fd1e62a;


  • Re-exports the hrp types from primitives::hrp to make importing ergonomic for the top level APIs.
  • Provides the internal nuts and bolts that enable bech32 encoding/decoding.
  • Segregated Witness API - enables typical usage for encoding and decoding segwit addresses.


  • An element in GF(32), the finite field containing elements [0,31] inclusive.
  • The human-readable part (human readable prefix before the ‘1’ separator).


  • The bech32 checksum algorithm, defined in BIP-173.
  • The bech32m checksum algorithm, defined in BIP-350.
  • An error while decoding a bech32 string.
  • An error while encoding a bech32 string.
  • An error while encoding a bech32 string.
  • The “null checksum” used on bech32 strings for which we want to do no checksum checking.


  • Extension trait for byte iterators which provides an adaptor to GF32 elements.
  • Trait defining a particular checksum.
  • Extension trait for field element iterators.