By all sources I can find, onion / hidden service "domains" are generated by this process:
Generate a 1024-bit RSA keypair Take the SHA-1 of the public key Base32 encode the first 80 bytes of the hash
I have tried to replicate it, by first generating a memorable vanity URL with Scallion, "zzzzzzycizaamf47.onion". I then wrote a PHP script to derive the public key from that private key, strip the formatting, hash it, truncate to 10 chars, and base32 encode it. First of all I found three different "encode as base32" functions, all which give different results. This is the code, with results commented after the three functions:
$privKey = 'MIIEpAIBAAKC ~snip~ azScNv5A'; $rsa = new Crypt_RSA(); $rsa->loadKey($privKey); $pubKey = $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); $pubKey = str_replace(array("\r", "\n", ' ', '=', '-----BEGINRSAPUBLICKEY-----', '-----ENDRSAPUBLICKEY-----'), '', $pubKey); // $pubKey = sha1($pubKey); $pubKey = substr($pubKey, 0, 10); echo base_convert($pubKey, 16, 32).PHP_EOL; //Result: 68s3ii2 echo crockford32_encode($pubKey).PHP_EOL; //Result: 60rkjcb365hp2d1j $base32 = new Base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', FALSE, TRUE, TRUE); echo $base32->encode($pubKey).PHP_EOL; //Result: GAYTSMLDGFRWCNBS
What's going wrong here? Why do the three "base32" functions give different results? Here is the code for crockford32_encode, and here is the code for Base2n. I have tried nearly all combinations of formatting / whitespace stripping and character truncation, and have never gotten close to the desired "zzzzzzycizaamf47". I previously posted this question on StackOverflow and got no answers, only a comment suggesting I ask here.