Pebble Coding

ソフトウェアエンジニアによるIT技術、数学の備忘録

base58をpythonで試す

base58は大まかに言ってbase64を改良したものです。
base64は64個の文字とパディングに=(イコール)を使うものです。WEBプログラマなら説明は不要でしょう。

base58はbase64から小文字のl(エル),大文字のI(アイ),大文字のO(オー),0(数字のゼロ),+(プラス),/(スラッシュ)の6つの文字を取り除き,
さらに=(イコール)でパディングするのもやめたものです。

base58エンコードはバイト列をBigEndianの整数にしてから、58進数として、58個の文字でBigEndianで表現したものですが、
桁が少ない場合は先頭を0パディングします。
ただし、16進の場合とはパディングする桁数が違いますので、ご注意ください。

ここでは、pythonのbase58ライブラリを使って計算した場合と、
直に計算したもの2種類で値が一致しているか試しています。

$ pip install base58

#!/usr/bin/env python

# use library
import base58
r1 = base58.b58encode(b'\x00\x01\x02')
print(r1)

# not use library
alphabet = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def b58encode(v):
    # パディング桁数を算出する
    nPad = len(v)
    v = v.lstrip(b'\0')
    nPad -= len(v)
    # バイト配列をBigEndianの数値と見なす
    p = 1
    s = 0
    # 右端から可算していく
    for c in reversed(v):
        s += p * c
        p = p << 8

    #   0 * 256 * 256 + 1 * 256 + 2
    # = 258
    print(s)

    output_ba = b''
    while s:
        # s に商, idx に余りが入る
        s, idx = divmod(s, 58)
        output_ba = alphabet[idx:idx+1] + output_ba

    # 先頭の0x0 の nPad バイト分ある場合は0(base58では1)を nPad バイト分パディングする
    return alphabet[0:1] * nPad + output_ba

r2 = b58encode(b'\x00\x01\x02')
print(r2)
b'15T'
258
b'15T'

参考
Base58Check encoding - Bitcoin Wiki