<p>Just for fun, here is some code I threw together that will try substituting up to <code>n</code> characters to try to make a valid address.</p>

<p>As a disclaimer, there's no guarantee that any address it finds is actually the "right" one; it could be a different address that is valid but doesn't belong to anyone, in which case any coins sent there would be lost forever.  Use at your own risk.</p>

<p>Running it with <code>n=3</code> found the address</p>

<blockquote>
  <p><a href="https://blockchain.info/address/1a8LDh3qtCdMFAgRXzMrdvB8w1EG4h1Xi" rel="nofollow noreferrer"><code>1a8LDh3qtCdMFAgRXzMrdvB8w1EG4h1Xi</code></a></p>
</blockquote>

<p>which has a balance of BTC 29658.80268195.  It appears to be the current resting place of the <a href="https://bitcoin.stackexchange.com/a/21031/5757">Bitcoins seized from Silk Road</a> that were <a href="http://dealbook.nytimes.com/2014/07/01/single-winner-of-all-bitcoins-in-u-s-auction/" rel="nofollow noreferrer">auctioned today</a>.</p>

<hr>

<p>To compile (on Linux):</p>

<pre><code>gcc -O3 -o subst subst.c -lssl -lcrypto
</code></pre>

<p>You will need the OpenSSL headers and libraries installed.</p>

<p>To run:</p>

<pre><code> ./subst 2 1a8LDh3qtCdMSAgRXzMr4zB8w1EG4h1Xi
</code></pre>

<p>Will try to replace up to any <code>2</code> characters to make a valid address.  You can replace <code>2</code> by <code>1</code> if you are impatient, or by a larger number if you are very patient.</p>

<p>Here is subst.c.  There is an unused function to try transposing characters from the address, but it is redundant with <code>n &gt;= 2</code>.  The validation code is from <a href="http://rosettacode.org/wiki/Bitcoin/address_validation#C" rel="nofollow noreferrer">Rosetta Code</a>.</p>



<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;openssl/sha.h&gt;

const char *coin_err;
#define bail(s) { coin_err = s; return 0; }

static const char *tmpl = "123456789"
        "ABCDEFGHJKLMNPQRSTUVWXYZ"
        "abcdefghijkmnopqrstuvwxyz";

char *xstrdup(const char *s) {
    char *p;
    p = strdup(s);
    if (!p) {
        fprintf(stderr, "How can you be out of memory?\n");
        exit(1);
    }
    return p;
}

int unbase58(const char *s, unsigned char *out) {
    int i, j, c;
    const char *p;

    memset(out, 0, 25);
    for (i = 0; s[i]; i++) {
        if (!(p = strchr(tmpl, s[i])))
            bail("bad char");

        c = p - tmpl;
        for (j = 25; j--; ) {
            c += 58 * out[j];
            out[j] = c % 256;
            c /= 256;
        }

        if (c) bail("address too long");
    }

    return 1;
}

int valid(const char *s) {
    unsigned char dec[32], d1[SHA256_DIGEST_LENGTH], 
        d2[SHA256_DIGEST_LENGTH];

    coin_err = "";
    if (!unbase58(s, dec)) return 0;

    SHA256(SHA256(dec, 21, d1), SHA256_DIGEST_LENGTH, d2);

    if (memcmp(dec + 21, d2, 4))
        bail("bad digest");

    return 1;
}

inline void try(const char *s) {
    if (valid(s)) {
        printf("Valid:\t%s\n", s);
    }
}

void subst_int(char *s, char *p0, int n) {
    if (n == 0)
        return;
    char *p;
    for (p = p0; *p; p++) {
        char orig = *p;
        const char *q;
        for (q = tmpl; *q; q++) {
            if (*q != orig) {
                *p = *q;
                try(s);
                subst_int(s, p+1, n-1);
            }
        }
        *p = orig;
    }
}

void subst(const char *s, int n) {
    char *buf = xstrdup(s);
    subst_int(buf, buf, n);
    free(buf);
}

inline void swap(char *p, char *q) {
    char tmp;
    tmp = *p;
    *p = *q;
    *q = tmp;
}

void transposition(const char *s) {
    char *buf = xstrdup(s);
    char *p, *q;
    for (p = buf; *p; p++) {
        for (q = p + 1; *q; q++) {
            if (*p != *q) {
                swap(p, q);
                try(buf);
                swap(p, q);
            }
        }
    }
}

int main(int argc, char *argv[]) {
    int i;
    int n;

    if (argc &lt; 3 || (n = atoi(argv[1])) &lt;= 0) {
        fprintf(stderr, "Usage: %s n addr...\n", argv[0]);
        fprintf(stderr, "Substitute up to n characters\n");
        exit(2);
    }


    for (i = 2; i &lt; argc; i++) {
        char *s = argv[i];
        printf("%s:\t%s\n", valid(s) ? "Valid" : "Orig", s);
        subst(s, n);
#if 0 /* redundant with n &gt;= 2 */
        transposition(s);
#endif
        if (i+1 &lt; argc)
            printf("\n");
    }
    return 0;
}
</code></pre>

CC BY-SA 3.0
2014-07-04T15:49:59.030Z
Thanks! The correct address seems to have only 2 characters different than the one I posted, so your code would work for n=2 as well, correct?
lurf jurv
CC BY-SA 3.0
2014-07-04T17:47:44.873Z
@lurfjurv: Nope, look again.  Characters 13, 21 and 22.
Nate Eldredge
CC BY-SA 3.0
2014-07-02T04:49:18.250Z
2014-07-02T04:57:24.473Z
2017-04-13T12:47:36.647Z
Nate Eldredge
<p>I just got this address: 1a8LDh3qtCdMSAgRXzMr4zB8w1EG4h1Xi, but the checksum doesn't validate. Can someone help me fix it by changing some characters that look/sound similar? </p>

CC BY-SA 3.0
2014-07-01T16:04:46.650Z
This is risky. There might be more than one way to "fix" the address, and you might get the wrong one. In that case, you might send coins to the wrong address, and if you do they are lost forever. You should instead talk to whoever gave you the address and ask them to correct it.
Nate Eldredge
CC BY-SA 3.0
2014-07-01T19:54:36.113Z
If only one character is different, there's a ((58*33)/2^32~=) 0.000045% probability you'll "fix" it to the wrong address. Lower if you throw out substitutions that seem unlikely. Two or more characters would increase this quickly. Still, Bitcoin addresses are not designed to recover lost data. It'd be safer if you could just get the correct address from the source.
Tim S.
CC BY-SA 3.0
2014-07-02T08:48:12.010Z
This question appears to be off-topic because it is about doing something impossible and have most likely the wrong outcome
Mathias711
<address>
Can you help me fix this address?
lurf jurv
# Can you help me fix this address?

(Asked by: username_0 on 2014-07-01)

I just got this address: 1a8LDh3qtCdMSAgRXzMr4zB8w1EG4h1Xi, but the checksum doesn't validate. Can someone help me fix it by changing some characters that look/sound similar?

**Tags:** address

> **Comments:**
> **username_1**: This is risky. There might be more than one way to "fix" the address, and you might get the wrong one. In that case, you might send coins to the wrong address, and if you do they are lost forever. You should instead talk to whoever gave you the address and ask them to correct it.  
> **username_2**: If only one character is different, there's a ((58*33)/2^32~=) 0.000045% probability you'll "fix" it to the wrong address. Lower if you throw out substitutions that seem unlikely. Two or more characters would increase this quickly. Still, Bitcoin addresses are not designed to recover lost data. It'd be safer if you could just get the correct address from the source.  
> **username_3**: This question appears to be off-topic because it is about doing something impossible and have most likely the wrong outcome  

---

## 1 answers

### Answer by username_1 on 2014-07-02. Score: 5 | Accepted answer

Just for fun, here is some code I threw together that will try substituting up to `n` characters to try to make a valid address.

As a disclaimer, there's no guarantee that any address it finds is actually the "right" one; it could be a different address that is valid but doesn't belong to anyone, in which case any coins sent there would be lost forever. Use at your own risk.

Running it with `n=3` found the address

> [`1a8LDh3qtCdMFAgRXzMrdvB8w1EG4h1Xi`](https://blockchain.info/address/1a8LDh3qtCdMFAgRXzMrdvB8w1EG4h1Xi)

which has a balance of BTC 29658.80268195. It appears to be the current resting place of the [Bitcoins seized from Silk Road](https://bitcoin.stackexchange.com/a/21031/5757) that were [auctioned today](http://dealbook.nytimes.com/2014/07/01/single-winner-of-all-bitcoins-in-u-s-auction/).

---

To compile (on Linux):

```
gcc -O3 -o subst subst.c -lssl -lcrypto

```

You will need the OpenSSL headers and libraries installed.

To run:

```
 ./subst 2 1a8LDh3qtCdMSAgRXzMr4zB8w1EG4h1Xi

```

Will try to replace up to any `2` characters to make a valid address. You can replace `2` by `1` if you are impatient, or by a larger number if you are very patient.

Here is subst.c. There is an unused function to try transposing characters from the address, but it is redundant with `n >= 2`. The validation code is from [Rosetta Code](http://rosettacode.org/wiki/Bitcoin/address_validation#C).

```
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/sha.h>

const char *coin_err;
#define bail(s) { coin_err = s; return 0; }

static const char *tmpl = "123456789"
        "ABCDEFGHJKLMNPQRSTUVWXYZ"
        "abcdefghijkmnopqrstuvwxyz";

char *xstrdup(const char *s) {
    char *p;
    p = strdup(s);
    if (!p) {
        fprintf(stderr, "How can you be out of memory?\n");
        exit(1);
    }
    return p;
}

int unbase58(const char *s, unsigned char *out) {
    int i, j, c;
    const char *p;

    memset(out, 0, 25);
    for (i = 0; s[i]; i++) {
        if (!(p = strchr(tmpl, s[i])))
            bail("bad char");

        c = p - tmpl;
        for (j = 25; j--; ) {
            c += 58 * out[j];
            out[j] = c % 256;
            c /= 256;
        }

        if (c) bail("address too long");
    }

    return 1;
}

int valid(const char *s) {
    unsigned char dec[32], d1[SHA256_DIGEST_LENGTH], 
        d2[SHA256_DIGEST_LENGTH];

    coin_err = "";
    if (!unbase58(s, dec)) return 0;

    SHA256(SHA256(dec, 21, d1), SHA256_DIGEST_LENGTH, d2);

    if (memcmp(dec + 21, d2, 4))
        bail("bad digest");

    return 1;
}

inline void try(const char *s) {
    if (valid(s)) {
        printf("Valid:\t%s\n", s);
    }
}

void subst_int(char *s, char *p0, int n) {
    if (n == 0)
        return;
    char *p;
    for (p = p0; *p; p++) {
        char orig = *p;
        const char *q;
        for (q = tmpl; *q; q++) {
            if (*q != orig) {
                *p = *q;
                try(s);
                subst_int(s, p+1, n-1);
            }
        }
        *p = orig;
    }
}

void subst(const char *s, int n) {
    char *buf = xstrdup(s);
    subst_int(buf, buf, n);
    free(buf);
}

inline void swap(char *p, char *q) {
    char tmp;
    tmp = *p;
    *p = *q;
    *q = tmp;
}

void transposition(const char *s) {
    char *buf = xstrdup(s);
    char *p, *q;
    for (p = buf; *p; p++) {
        for (q = p + 1; *q; q++) {
            if (*p != *q) {
                swap(p, q);
                try(buf);
                swap(p, q);
            }
        }
    }
}

int main(int argc, char *argv[]) {
    int i;
    int n;

    if (argc < 3 || (n = atoi(argv[1])) <= 0) {
        fprintf(stderr, "Usage: %s n addr...\n", argv[0]);
        fprintf(stderr, "Substitute up to n characters\n");
        exit(2);
    }

    for (i = 2; i < argc; i++) {
        char *s = argv[i];
        printf("%s:\t%s\n", valid(s) ? "Valid" : "Orig", s);
        subst(s, n);
#if 0 /* redundant with n >= 2 */
        transposition(s);
#endif
        if (i+1 < argc)
            printf("\n");
    }
    return 0;
}

```

> **Comments:**
> **username_0**: Thanks! The correct address seems to have only 2 characters different than the one I posted, so your code would work for n=2 as well, correct?  
> **username_1**: @username_0: Nope, look again.  Characters 13, 21 and 22.  

---

