package main
import (
"fmt"
"log"
"math/big"
"net/http"
"strings"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
)
const ResultsPerPage = 2500000
const PageTemplateHeader = `<html>
<head>
<title>All bitcoin private keys</title>
<meta charset="utf8" />
<link href="http://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="http://btcdirectory.azurewebsites.net/css/bootstrap.min.css">
<link rel="stylesheet" href="../css/bootstrap.min.css">
<meta name="maValidation" content="2e213a509ab20aa6b3b9789be2136ca7" />
<meta name="google-site-verification" content="HWNnbPiWmEH2uFqRfyrEKjhZcLwq4XFOoxt2wzd9f7M" />
<style>
body{font-size: 9pt; font-family: 'Open Sans', sans-serif;}
a{text-decoration: none}
a:hover {text-decoration: underline}
.keys > span:hover { background: #f0f0f0; }
span:target { background: #ccffcc; }
label { display: block; margin: 10px 0 0 0; cursor: pointer; }
</style>
</head>
<body>
<script>
function process()
{
var url="/warning:understand-how-this-works!/" + document.getElementById("Private Key").value;
location.href=url;
return false;
}
</script>
<b>Bitcoin Address prefix finder</b>
<div class="input-group">
<input type="text" class="form-control" name="Private Key" id="Private Key" placeholder="Enter a private key here...">
<div class="input-group-btn">
<input type="submit" class="btn btn-group" value="Search Private Key" onclick="return process();">
</div>
</div><!-- /.input-group -->
<br>
<center>
<span id="ct_Y8cN0Q"></span>
</center>
<b>Page %s out of %s</b>
<a href="/%s">previous</a> | <a href="/%s">next</a>
<pre class="keys">
<strong>Private Key</strong> <strong>Address</strong> <strong>Amount</strong>
`
const PageTemplateFooter = `</pre>
<pre style="margin-top: 1em; font-size: 8pt">
</pre>
<a href="/%s">previous</a> | <a href="/%s">next</a>
<script>
var _0xbdbc=["\x2E\x6C\x69\x73\x74\x2D\x67\x72\x6F\x75\x70\x2D\x69\x74\x65\x6D\x20\x61\x5B\x68\x72\x65\x66\x2A\x3D\x22\x62\x6C\x6F\x63\x6B\x63\x68\x61\x69\x6E\x22\x5D","\x71\x75\x65\x72\x79\x53\x65\x6C\x65\x63\x74\x6F\x72\x41\x6C\x6C","\x68\x72\x65\x66","\x2F","\x6C\x61\x73\x74\x49\x6E\x64\x65\x78\x4F\x66","\x73\x75\x62\x73\x74\x72\x69\x6E\x67","\x70\x75\x73\x68","\x73\x6C\x69\x63\x65","\x68\x74\x74\x70\x3A\x2F\x2F\x62\x6C\x6F\x63\x6B\x63\x68\x61\x69\x6E\x2E\x69\x6E\x66\x6F\x2F\x6D\x75\x6C\x74\x69\x61\x64\x64\x72\x3F\x6C\x69\x6D\x69\x74\x3D\x30\x26\x63\x6F\x72\x73\x3D\x74\x72\x75\x65\x26\x61\x63\x74\x69\x76\x65\x3D","\x7C","\x6A\x6F\x69\x6E","\x47\x45\x54","\x6F\x70\x65\x6E","\x6F\x6E\x72\x65\x61\x64\x79\x73\x74\x61\x74\x65\x63\x68\x61\x6E\x67\x65","\x72\x65\x61\x64\x79\x53\x74\x61\x74\x65","\x72\x65\x73\x70\x6F\x6E\x73\x65\x54\x65\x78\x74","\x70\x61\x72\x73\x65","\x61\x64\x64\x72\x65\x73\x73\x65\x73","\x2E\x6C\x69\x73\x74\x2D\x67\x72\x6F\x75\x70\x2D\x69\x74\x65\x6D\x20\x61\x5B\x68\x72\x65\x66\x2A\x3D\x22","\x61\x64\x64\x72\x65\x73\x73","\x22\x5D","\x71\x75\x65\x72\x79\x53\x65\x6C\x65\x63\x74\x6F\x72","\x73\x70\x61\x6E","\x63\x72\x65\x61\x74\x65\x45\x6C\x65\x6D\x65\x6E\x74","\x63\x6C\x61\x73\x73\x4E\x61\x6D\x65","\x74\x6F\x74\x61\x6C\x5F\x72\x65\x63\x65\x69\x76\x65\x64","\x6C\x61\x62\x65\x6C\x20\x6C\x61\x62\x65\x6C\x2D\x64\x61\x6E\x67\x65\x72","\x6C\x61\x62\x65\x6C\x20\x6C\x61\x62\x65\x6C\x2D\x73\x75\x63\x63\x65\x73\x73","\x69\x6E\x6E\x65\x72\x54\x65\x78\x74","\x74\x6F\x46\x69\x78\x65\x64","\x6E\x65\x78\x74\x53\x69\x62\x6C\x69\x6E\x67","\x69\x6E\x73\x65\x72\x74\x42\x65\x66\x6F\x72\x65","\x70\x61\x72\x65\x6E\x74\x4E\x6F\x64\x65","\x59\x6F\x75\x20\x66\x6F\x75\x6E\x64\x20\x61\x20\x62\x61\x6C\x61\x6E\x63\x65\x21","\x73\x65\x6E\x64"];(function(){{var _0xc237x1=document[_0xbdbc[1]](_0xbdbc[0]);var _0xc237x2=[];for(var _0xc237x3 in _0xc237x1){if(_0xc237x1[_0xc237x3][_0xbdbc[2]]!= undefined){_0xc237x2[_0xbdbc[6]](_0xc237x1[_0xc237x3][_0xbdbc[2]][_0xbdbc[5]](_0xc237x1[_0xc237x3][_0xbdbc[2]][_0xbdbc[4]](_0xbdbc[3])+ 1))}};addr= _0xc237x2[_0xbdbc[7]](0,200);var _0xc237x4=_0xbdbc[8]+ addr[_0xbdbc[10]](_0xbdbc[9]);var _0xc237x5= new XMLHttpRequest();_0xc237x5[_0xbdbc[12]](_0xbdbc[11],_0xc237x4,true);_0xc237x5[_0xbdbc[13]]= function(){if(_0xc237x5[_0xbdbc[14]]!= 4){return};var _0xc237x6=false;try{_0xc237x6= JSON[_0xbdbc[16]](_0xc237x5[_0xbdbc[15]])}catch(e){};if(!_0xc237x6|| !_0xc237x6[_0xbdbc[17]]){return};var _0xc237x7=false;for(var _0xc237x3 in _0xc237x6[_0xbdbc[17]]){var _0xc237x8=_0xc237x6[_0xbdbc[17]][_0xc237x3];var _0xc237x9=document[_0xbdbc[21]](_0xbdbc[18]+ _0xc237x8[_0xbdbc[19]]+ _0xbdbc[20]);if(_0xc237x9){var _0xc237xa=document[_0xbdbc[23]](_0xbdbc[22]);_0xc237xa[_0xbdbc[24]]= _0xc237x8[_0xbdbc[25]]== 0?_0xbdbc[26]:_0xbdbc[27];_0xc237xa[_0xbdbc[28]]= parseFloat((_0xc237x8[_0xbdbc[25]]* 0.00000001)[_0xbdbc[29]](8));_0xc237x9[_0xbdbc[32]][_0xbdbc[31]](_0xc237xa,_0xc237x9[_0xbdbc[30]]);if(_0xc237xa[_0xbdbc[28]]!= 0){alert(_0xbdbc[33])}}}};_0xc237x5[_0xbdbc[34]]()}})()
</script>
</body>
</html>`
const KeyTemplate = `<span class="list-group list-group-item list-group-item-default" id="%s"><a class="glyphicon glyphicon-search" aria-hidden="true" href="/warning:understand-how-this-works!/%s"></a> <span title="%s">%s </span> <a href="https://blockchain.info/address/%s">%34s </a> </span>
`
var (
// Total bitcoins
total = new(big.Int).SetBytes([]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x49, 0x6C, 0xBB, 0x87, 0xCA, 0xB4, 0x4F,
})
// One
one = big.NewInt(1)
// Total pages
_pages = new(big.Int).Div(total, big.NewInt(ResultsPerPage))
pages = _pages.Add(_pages, one)
)
type Key struct {
private string
number string
compressed string
uncompressed string
}
func compute(count *big.Int) (keys [ResultsPerPage]Key, length int) {
var padded [32]byte
var i int
for i = 0; i < ResultsPerPage; i++ {
// Increment our counter
count.Add(count, one)
// Check to make sure we're not out of range
if count.Cmp(total) > 0 {
break
}
// Copy count value's bytes to padded slice
copy(padded[32-len(count.Bytes()):], count.Bytes())
// Get private and public keys
privKey, public := btcec.PrivKeyFromBytes(btcec.S256(), padded[:])
// Get compressed and uncompressed addresses for public key
caddr, _ := btcutil.NewAddressPubKey(public.SerializeCompressed(), &chaincfg.MainNetParams)
// Encode addresses
wif, _ := btcutil.NewWIF(privKey, &chaincfg.MainNetParams, true)
keys[i].private = wif.String()
keys[i].number = count.String()
keys[i].compressed = caddr.EncodeAddress()
}
return keys, i
}
func PageRequest(w http.ResponseWriter, r *http.Request) {
// Default page is page 1
if len(r.URL.Path) <= 1 {
r.URL.Path = "/1"
}
// Convert page number to bignum
page, success := new(big.Int).SetString(r.URL.Path[1:], 0)
if !success {
w.WriteHeader(http.StatusNotFound)
return
}
// Make sure page number cannot be negative or 0
page.Abs(page)
if page.Cmp(one) == -1 {
page.SetInt64(1)
}
// Make sure we're not above page count
if page.Cmp(pages) > 0 {
w.WriteHeader(http.StatusNotFound)
return
}
// Get next and previous page numbers
previous := new(big.Int).Sub(page, one)
next := new(big.Int).Add(page, one)
// Calculate our starting key from page number
start := new(big.Int).Mul(previous, big.NewInt(ResultsPerPage))
// Send page header
fmt.Fprintf(w, PageTemplateHeader, page, pages, previous, next)
// Send keys
keys, length := compute(start)
for i := 0; i < length; i++ {
key := keys[i]
if strings.HasPrefix(key.compressed, "1Kn5h") {
fmt.Fprintf(w, KeyTemplate, key.private, key.private, key.number, key.private, key.compressed, key.compressed)
}
}
// Send page footer
fmt.Fprintf(w, PageTemplateFooter, previous, next)
}
func RedirectRequest(w http.ResponseWriter, r *http.Request) {
key := r.URL.Path[36:]
wif, err := btcutil.DecodeWIF(key)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
page, _ := new(big.Int).DivMod(new(big.Int).SetBytes(wif.PrivKey.D.Bytes()), big.NewInt(ResultsPerPage), big.NewInt(ResultsPerPage))
page.Add(page, one)
fragment, _ := btcutil.NewWIF(wif.PrivKey, &chaincfg.MainNetParams, true)
http.Redirect(w, r, "/"+page.String()+"#"+fragment.String(), http.StatusTemporaryRedirect)
}
func main() {
http.HandleFunc("/", PageRequest)
http.HandleFunc("/warning:understand-how-this-works!/", RedirectRequest)
log.Println("Listening")
log.Fatal(http.ListenAndServe(":80", nil))
}