Skip to content

Instantly share code, notes, and snippets.

@ianoxley
Created March 11, 2011 14:00
Show Gist options
  • Save ianoxley/865912 to your computer and use it in GitHub Desktop.
Save ianoxley/865912 to your computer and use it in GitHub Desktop.
base58 encoding in Python
""" base58 encoding / decoding functions """
import unittest
alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
base_count = len(alphabet)
def encode(num):
""" Returns num in a base58-encoded string """
encode = ''
if (num < 0):
return ''
while (num >= base_count):
mod = num % base_count
encode = alphabet[mod] + encode
num = num / base_count
if (num):
encode = alphabet[num] + encode
return encode
def decode(s):
""" Decodes the base58-encoded string s into an integer """
decoded = 0
multi = 1
s = s[::-1]
for char in s:
decoded += multi * alphabet.index(char)
multi = multi * base_count
return decoded
class Base58Tests(unittest.TestCase):
def test_alphabet_length(self):
self.assertEqual(58, len(alphabet))
def test_encode_10002343_returns_Tgmc(self):
result = encode(10002343)
self.assertEqual('Tgmc', result)
def test_decode_Tgmc_returns_10002343(self):
decoded = decode('Tgmc')
self.assertEqual(10002343, decoded)
def test_encode_1000_returns_if(self):
result = encode(1000)
self.assertEqual('if', result)
def test_decode_if_returns_1000(self):
decoded = decode('if')
self.assertEqual(1000, decoded)
def test_encode_zero_returns_empty_string(self):
self.assertEqual('', encode(0))
def test_encode_negative_number_returns_empty_string(self):
self.assertEqual('', encode(-100))
if __name__ == '__main__':
unittest.main()
@prerakmody
Copy link

prerakmody commented Jan 10, 2017

You may remove this content if you find it not in context of your gist. But if a user simply wants to convert a string into a base-58 encoded function, he could use the following:

def encode(num):
        alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
	####convert each digit into unicode
	buffer = [ord(each[0]) for each in str(num)]
	print 'Buffer:', buffer
	digits = [0]; i= 0; j = 0;
	while (i < len(buffer)):   #loop for as many digits are present
		j = 0
		while (j < len(digits)):
			digits[j] <<= 8
			j += 1
		digits[0] += buffer[i]
		carry = 0; j = 0;
		while(j < len(digits)):
			digits[j] += carry
			carry = (digits[j]/58) | 0
			digits[j] %= 58;
			j += 1
		while(carry):
			digits.append(carry%58)
			carry = (carry/58) | 0
		i += 1
	print 'Digits:', digits
	i = 0;
	while (buffer[i] == 0 and i < len(buffer) - 1):
		digits.push(0);
		i += 1;
	print digits
	print 'Result:', [alphabet[each] for each in digits][::-1]

Inspirations from this URL: https://www.browserling.com/tools/base58-encode

@BenGimli
Copy link

Just learning python
When running this program, I get this error

encode = alphabet[num] + encode
TypeError: string indices must be integers

I'm using version 3.6
What am I missing?

@acarmisc
Copy link

@BenGimli num must be a number

@rootux
Copy link

rootux commented Jan 1, 2018

Here is a library that does that https://github.com/keis/base58

@john-shine
Copy link

alphabet is "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" not "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" if in Bitcoin

@blakev
Copy link

blakev commented Jun 10, 2020

A slight variation on the original uses a List instead of rebuilding strings, as well as type hints for Cython + Mypy:

from typing import List

ALPHA = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'

def b58encode(num: int) -> str:
    """Converts a number into Base-58.
    """
    encoded: List[str] = []
    alpha_cnt: int = len(ALPHA)

    if num < 0:
        return ''

    while num >= alpha_cnt:
        mod = num % alpha_cnt
        num //= alpha_cnt
        encoded.append(ALPHA[mod])

    if num > 0:
        encoded.append(ALPHA[num])

    return ''.join(encoded[::-1])


def b58decode(ins: str) -> int:
    """Converts a Base-58 encoded integer, as string, back to a number.
    """
    multi: int = 1
    decoded: int = 0
    alpha_cnt: int = len(ALPHA)

    for char in ins[::-1]:
        decoded += multi * ALPHA.index(char)
        multi *= alpha_cnt
    return decoded

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment