steemit / steem-js

Steem.js the official JavaScript library for Steem blockchain
https://www.npmjs.com/package/steem
MIT License
472 stars 225 forks source link

Modifying private keys results in many other valid keys #383

Open Jolly-Pirate opened 6 years ago

Jolly-Pirate commented 6 years ago

Changing one of the last 4 characters in a private key may result in a validation by the wifIsValid() function. This happens in steem-js but not in steem-python (can't import an invalid key with steempy addkey).

Tested with different accounts. Some keys are showing this behavior, while others aren't.

The modified keys are also able to broadcast transactions.

Using the latest steem-js v0.7.1

Here's a snippet to verify the combinations for a given key pair.

String.prototype.replaceAt = function (index, replacement) {
  return this.substr(0, index) + replacement + this.substr(index + replacement.length);
};

// account and password example that illustrate the problem
var account = "testuser123"; // edit this
var password = "P5JvGvqo8NWhnaEhqHNsd69g7TbiFy1WcZQ5HNq8qxvaVU1bXzmX"; // edit this

var steem = require('steem');
var base58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
var keys = steem.auth.getPrivateKeys(account, password, ['owner', 'active', 'posting', 'memo']);

//console.log(keys);

testKeys(keys.owner, keys.ownerPubkey, "owner");
testKeys(keys.active, keys.activePubkey, "active");
testKeys(keys.posting, keys.postingPubkey, "posting");
testKeys(keys.memo, keys.memoPubkey, "memo");

function testKeys(privatekey, publickey, keytype) {
  var validcount = 0;
  for (var testpos = 0; testpos <= privatekey.length; testpos++) {
    for (var i = 0; i < base58chars.length; i++) {
      var newchar = base58chars.slice(i, i + 1);
      var modifiedprivatekey = privatekey.replaceAt(testpos - 1, newchar);
      try {
        if (steem.auth.wifIsValid(modifiedprivatekey, publickey)) {
          if (privatekey !== modifiedprivatekey) {
            var slice1 = privatekey.slice(0, testpos - 1);
            var slice2 = privatekey.slice(testpos - 1, privatekey.length - 1);
            console.log(slice1 + "\x1b[36m" + newchar + "\x1b[0m" + slice2, "VALID");
            validcount++;
          }
        }
      } catch (e) {
        //console.log(e);
        //console.log(modifiedwif, newchar, "INVALID");
      }
    }
  }
  console.log("\x1b[32m" + privatekey, "ORIGINAL", keytype, "\x1b[0m");
  console.log("Found", validcount, "valid variations on the original", keytype, "key", "\r\n");
  validcount = 0;
}
cryptohazard commented 6 years ago

I did know someone find this bug :-(. Anyway I investigated it and here is the explanation: https://steemit.com/utopian-io/@cryptohazard/steem-bug-private-key-format-wif-errors-in-steem-js-library