bitcoinjs / bip38

BIP38 is a standard process to encrypt Bitcoin and crypto currency private keys that is less susceptible to brute force attacks thus protecting the user.
http://cryptocoinjs.com/modules/currency/bip38/
MIT License
206 stars 100 forks source link

Is there a way to verify incorrect Encrypted key/passphrase pair? #60

Closed Overtorment closed 4 years ago

Overtorment commented 4 years ago

Im using 6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX from https://en.bitcoin.it/wiki/BIP_0038

minimal example with incorrect password aaa

var bip38 = require('bip38')
var wif = require('wif')

var encryptedKey = '6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX'
var decryptedKey = bip38.decrypt(encryptedKey, 'aaa', function (status) {
//        console.log(status.percent) // will print the percent every time current increases by 1000
})

console.log(wif.encode(0x80, decryptedKey.privateKey, decryptedKey.compressed))

produces 5JdGEnZHRWpGRijtAeZ1pUcgKQhn7bSQcBqjcMZUN3pxKjHPYR6 without throwing exception or returning false or anything.

correct password TestingOneTwoThree produces correct output

This might be EC multiply, no compression, no lot/sequence numbers specific, as on other examples lib does throws an exception.

junderw commented 4 years ago

The whole point of EC multiply is to allow you to oursource vanity address generation.

So similar to the way a passphrase added to a BIP39 phrase works, every passphrase generates a valid private key.

Only YOUR password will generate YOUR private key.

junderw commented 4 years ago

If you'd like an error, do not use EC multiply.

Overtorment commented 4 years ago

Question tho: how are they doing it?

https://bitcoinpaperwallet.com/bitcoinpaperwallet/generate-wallet.html# image

Overtorment commented 4 years ago

and they

https://www.bitaddress.org/bitaddress.org-v3.3.0-SHA256-dec17c07685e1870960903d8f58090475b25af946fe95a734f88408cef4aa194.html image

junderw commented 4 years ago

ahhh, sorry I forgot about the salt.

In BIP38 the 4 byte salt (which you can get by doing the following)

const salt = bs58check.decode('6PfQu....').slice(3, 7);

Is the result of hash256(address).slice(0, 4) so you should generate the address from your result wif and hash to see if the salt matches.

hmm, it looks like we do it for non-EC but we don't do it for EC...:

  // verify salt matches address
  var d = BigInteger.fromBuffer(privateKey)
  var address = getAddress(d, compressed)
  var checksum = hash256(address).slice(0, 4)
  assert.deepStrictEqual(salt, checksum)
junderw commented 4 years ago

I'm not super versed in this... maybe there's a good reason we don't do this...

So for now at least you know how you can check.