Steem bug: Private key format(wif) errors in steem-js library

in #utopian-io6 years ago (edited)

Edit: it seems @drakos(right?) already opened the issue : https://github.com/steemit/steem-js/issues/383. Well now we know exactly where the bug came from with my post.

This bug is about implementation mistake of the WIF. No funds should have been lost because of it. What might have happened is a user saving an incorrect private key (as explain below) but the correct key is easily retrievable.

Project Information

Expected behavior

Wif private keys have features to stop users errors when dealing with private keys:

  • base 58 to not write incorrect letters,
  • a checksum to know the key is properly formatted and valid.

So changing one character in the private key has (very) low chances to give you another valid private key. Also you should get a different corresponding public address.

Actual behaviour

Below an example with a random key:

Private key and corresponding Public key
5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtRCPFTThMPsLDuCQUVSD5a      STM5yabD4ScbVKc8EAjSaf9TMtasePQ6pwufMCQY8hnXvvWK8Gpue 

Starting Key iteration
5J9GqSAGHtH8Yf8JWuWnWaGedB5bUtRCPFTThMPsLDuCQUVSD5a      STM4uyNzGHyfE8Vcs4oNUnn3ehjRHzL8aUHnovghP8xGzixMzMLn3
5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtECPFTThMPsLDuCQUVSD5a      STM7osWuir46FamHZBbhQmniD1TVSV3uWEFNUtf1rtfVrsLraumuK
5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtRCPFTThMPsLDuCQUVSE5a      STM5yabD4ScbVKc8EAjSaf9TMtasePQ6pwufMCQY8hnXvvWK8Gpue
5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtRCPFTThMPsLDuCQUVSF5a      STM5yabD4ScbVKc8EAjSaf9TMtasePQ6pwufMCQY8hnXvvWK8Gpue
5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtRCPFTThMPsLDuCQUVSG5a      STM5yabD4ScbVKc8EAjSaf9TMtasePQ6pwufMCQY8hnXvvWK8Gpue
...

There are much more hits. You can see in the beginning a real collision: we find another valid WIF but the public key is, as expected different. The other cases should not happen.

You can test it with the following JS functions:


function trial(){
  const base58="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  const private_key="5J9GqSAGHtH8Yf8JWuWnWaGedB5WUtRCPFTThMPsLDuCQUVSD5a";
  console.log("Private key and corresponding Public key");
  console.log(private_key,"\t",steem.auth.wifToPublic(private_key),"\n");
  console.log("Starting Key iteration");
  var key;
  for (var i = 0; i < private_key.length; i++) {
    for (var j = 0; j < base58.length; j++) {
      key = setCharAt(private_key,i,base58[j]);
      if(steem.auth.isWif(key) && key !== private_key){
            console.log(key,"\t",steem.auth.wifToPublic(key));//," ",steem.auth.Signature);
      }
    }
  }
}

function setCharAt(str,index,chr) {
    if(index > str.length-1) return str;
    return str.substr(0,index) + chr + str.substr(index+1);
}

This code finds all the valid wif which differ from one base58 character from the starting key.

The problems

I found two problems while investigating this bug.
First of all, there were no need to have two function doing the same:

Second, comparing two buffers, when the value don't necessarily fit in ascii is a bad idea. Look at the the very detailed accepted explanation on Buffer comparison. In summary, the values unrecognised for ascii will become the Unicode Replacement Character thus become equal.

Small addition: from how base systems work, it makes sense most of the invalid keys will have the difference at the end.

Fix

Make a buffer comparison directly and clean up a bit the functions. Also add a recovery code (my bruteforce search) in case someone saved the wrong wif.

GitHub Account

https://github.com/cryptohazard/

Merci to the witness @evildido to make me work on that. It was a pretty intriguing case and I had to methodically look at each step of the algorithm until I got the intuition.

Sort:  

I hope they fix that. It's not critical because bruteforcing is still extremely difficult, but nevertheless it's a flaw that shouldn't exist.

Yeah I really freaked out the first time I saw it. Which is why I wanted to know exactly where it was from.
If they take forever I may do an ugly fix so that they actually start working.

Thank you for the report! While this is not as major as it may initially seem, it's still a threat to the usability of the library and should definitely be addressed! As such, I've scored your contribution according to the questionnaire.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thanks for the thorough review!! I am just trying to help where I can.

Have you been able to reproduce/test this with dsteem as well?

@drakos tested on python and it is not affected. I cannot try on steemd right now and I think it should not reproduce. but I can let you know as soon as I try.

Hey @cryptohazard
Thanks for contributing on Utopian.
Congratulations! Your contribution was Staff Picked to receive a maximum vote for the bug-hunting category on Utopian for being of significant value to the project and the open source community.

We’re already looking forward to your next contribution!

Contributing on Utopian
Learn how to contribute on our website or by watching this tutorial on Youtube.

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.27
TRX 0.13
JST 0.032
BTC 60805.28
ETH 2912.27
USDT 1.00
SBD 3.59