Decoding the Code - Part 1

in #development8 years ago (edited)

As


I continue to work on the Sybil Workshop, I have been analysing the relevant code that I am replicating functions from, in order to write a javascript version that takes a master password and generates all of the public keys (starting with STM) for generating a create account query to an RPC endpoint.

I will continue to make entries about how I am working on this project, hence the part number in the title.

From source from the Steem blockchain node:

pair<public_key_type,string> wallet_api::get_private_key_from_password( string account, string role, string password )const {
   auto seed = account + role + password;
   FC_ASSERT( seed.size() );
   auto secret = fc::sha256::hash( seed.c_str(), seed.size() );
   auto priv = fc::ecc::private_key::regenerate( secret );
   return std::make_pair( public_key_type( priv.get_public_key() ), key_to_wif( priv ) );
}

First, you take the account name, role string and master password, and concatenate

"l0k1" + "posting" + "5blahblahblahpassword"
  • becomes ->

    "l0k1posting5blahblahblahpassword"

then you generate the SHA256 hash out of it, which is a 32 byte (256 bit) binary string (secret)

which would look like this:

0x4ed71c85f20e25e5ef661225feed773fe18d959abba1565dd58595fd55d780cf

from our example, this is 32 bytes.

Then using the elliptic curve - private key - regenerate function from ECDSA you
derive the private key for the role (priv)

I am working on the last line to find out what all those functions do, the second parameter of the return make_pair function requires the private key puts char 0x80 (128) in front of the secret (priv), and a 4 byte digest hash at the end (comments added by me):

std::string key_to_wif(const fc::sha256& secret )
{
  const size_t size_of_data_to_hash = sizeof(secret) + 1;
  const size_t size_of_hash_bytes = 4;
  char data[size_of_data_to_hash + size_of_hash_bytes];
  data[0] = (char)0x80; 
    //prepend character ascii 128 to hash of secret
  memcpy(&data[1], (char*)&secret, sizeof(secret)); 
    //copy secret to temp variable after char 0
  fc::sha256 digest = fc::sha256::hash(data, size_of_data_to_hash);
    // hash the secret
  digest = fc::sha256::hash(digest);
    // hash the hash of the secret
    - note, no length is given in this call of fc::256::hash, 
    I don't know what this means
  memcpy(data + size_of_data_to_hash, (char*)&digest, size_of_hash_bytes);
    // append the first 4 bytes digest to end of secret (is this correct?)
  return fc::to_base58(data, sizeof(data));
    //convert to base 58

I think I understand this correctly, out of this function, first character is 0x80 (ascii 128) then we have the elliptic curve of the secret, and then the first 4 bytes of the hash of the hash of the binary form of the secret with that extra 0x80 character at the front, and then we encode this giant number into base 58, representing it as a binary string in text form.

I assume that the .get_public_key function at the end of the first function is the second last ingredient in my puzzle, I am pretty sure then it's just taking the base58 code of public and private key, and to each appending an identifier, STM for the public key and 5 is added as a prefix to identify the secret keys.

So a function to convert binary strings into base58 is the very last bit and then it's just writing the copy of this first algorithm, and then outputting the set of public keys the create_account function works.

The intent is to write a javascript function for a html file a user can download, that has an input for a secret key (and maybe a generator) and then you click a button and it runs all that algorithm above, and places a comma separated list of key pairs in python variable format, which my webserver then uses to construct a 'create_account' RPC query, pending of course the receipt of the payment for it.

😎


We can't code here! This is Whale country!

Vote #1 l0k1

Go to steemit.com/~witnesses to cast your vote by typing l0k1 into the text entry at the bottom of the leaderboard.

Sort:  

no need to add a length after the first sha256 because the output, digest, has 256 bits :).

Coin Marketplace

STEEM 0.17
TRX 0.15
JST 0.029
BTC 61986.52
ETH 2406.81
USDT 1.00
SBD 2.65