How do I check the checksum of a Bitcoin address?

9

4

I'm working on a Bitcoin ATM. We want to detect addresses that are entered incorrectly.

There's a checksum on Bitcoin addresses - but how can we check it?

Willipm

Posted 2014-11-06T03:22:51.073

Reputation: 283

1ah.found it if(!validateAddress(rcp.address)) { return InvalidAddress; }Willipm 2014-11-06T03:32:33.280

If you can choose the option of answering your own question for future queries that'd help!Wizard Of Ozzie 2014-11-06T08:51:33.897

@WizardOfOzzie: Right on. Also, if you know that the information is correct, feel free to use any "comment answer" as a starting point to create a full answer. It might be nice to quote the original commenter, but anyone has my blessing to the reputation for the answer if he does that.Murch 2014-11-07T01:07:46.487

Answers

9

The way Bitcoin checks a public address is using what is called Base58Check. While the Bitcoin Wiki covers Base58Check, I'll outline how it works in both abstract and technical terms.

Diagram of Base58Check

The whole idea of Base58Check is to prevent invalid addresses. This is done by adding digits to the start (00) and end of the Base58 value (4 bytes of double SHA256 hash).

  1. Add 00 to the start of Base58 value ie 00 + BASE58 ==> 00BASE58
  2. Checksum = 1st 8 digits from SHA256(SHA256(00BASE58))

BASE58Check = (00)(BASE58_SHA256RIPEMD160_HEXADECIMAL_VALUE)(CHECKSUM) (parenthesis for visualisation only, all other data is correct in size, ie CHECKSUM = 8 chars)

The best way to visualize all this is with The Piachu's App

Wizard Of Ozzie

Posted 2014-11-06T03:22:51.073

Reputation: 4 535

Excellent answer and infographic!Nick ODell 2014-11-07T03:05:55.503

6

Rosetta Code has several example implementations in multiple languages.

Python 2 & 3

import codecs
from hashlib import sha256

digits58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def to_bytes(n, length):
    s = '%x' % n
    s = s.rjust(length*2, '0')
    s = codecs.decode(s.encode("UTF-8"), 'hex_codec')
    return s

def decode_base58(bc, length):
    n = 0
    for char in bc:
        n = n * 58 + digits58.index(char)
    return to_bytes(n, length)

def check_bc(bc):
    bcbytes = decode_base58(bc, 25)

    if bcbytes[0] not in [0x00, 0x05]:
        return False

    return bcbytes[-4:] == sha256(sha256(bcbytes[:-4]).digest()).digest()[:4]

if __name__ == '__main__':
    print(check_bc('1111111111111111111114oLvT2'))

Nick ODell

Posted 2014-11-06T03:22:51.073

Reputation: 26 536

This cannot be used to validate bitcoin addresses. Returns True for the following strings:DPPGKttReEyzL5iQJExKvmS68QWTFvaecJ, MfwMaegJ8qB4QMvtFqgfaD8o2FrYse7LU, mtcrV4Wux9xPapqHz13eAEmynVhyfNTY7uMax Malysh 2017-08-19T00:29:58.437

If you wish to check the version byte, check that too.Nick ODell 2017-08-19T00:31:51.390