codesoap/atto

Private Key Confusion

zQueal opened this issue · 7 comments

Atto only works with seeds. To test something I threw a private key for a specific address at it, and instead of errors, it generates a random address (which is not the one to the private key). I'm concerned this behavior will cause people to lose funds eventually.

Any way to fix this, or to get it working with private keys properly?

Oh, that's not good, thanks for the report. Right now atto just takes anything hexadecimal and uses it as the seed. I could at least verify that the length of the seed is correct.

How did the private key look? Was it also just 64 hexadecimal digits? In that case I'm afraid we would be out of luck; it's impossible to distinguish a seed from a private key, if both are represented as 64 hexadecimal digits. A seed is completely random and a private key is a hash, which would also look random to atto - there is no "magic byte" I could check for to see if it's a seed or key.

  • Account private key
    This is also a 32 byte value, usually represented as a 64 character, uppercase hexadecimal string(0-9A-F). It can either be random (an ad-hoc key) or derived from a seed, as described above. This is what represents control of a specific account on the ledger. If you know or can know the private key of someone's account, you can transact as if you own that account.

Looks like it was done this way for ease of use. You can input a private key into a wallet application as a normal seed, and have access to that index id within the seed as you would if you had the entire seed. But it seems to work outside of Atto for whatever reason.

Seed: 527B2633F87459B167BAF460526884FD0814990D00F5606AAE7CDA2E754700B6

[
  {
    "index": 0,
    "privKey": "102d80c52e9c4fe0a066e1e9b960d18dffdd0a4efa6328f04644d3cc066f60d9",
    "pubKey": "28952596a85b89288501592413b63aa28c66dd34c1f407a903340af50340683b",
    "address": "nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr"
  }
]

So using the seed like normal;

> echo 527B2633F87459B167BAF460526884FD0814990D00F5606AAE7CDA2E754700B6 | atto -a 0 a
nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr

And then using the private key;

> echo 102d80c52e9c4fe0a066e1e9b960d18dffdd0a4efa6328f04644d3cc066f60d9 | atto a
nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6

But if I take the private key and put it into nault.cc as a seed I get the same address as atto. But if I take the private key and import it to nault.cc as a private key I get the correct address.

So I think this is still possible with atto. There seems to be a different process to using private keys vs seeds. So perhaps we can lean on the users knowledge of it being a private key to process the input differently based on if its a seed or private key;

echo %SEED% | atto -a 0 b // seed
echo %KEY% | atto -k b // key

But if I take the private key and put it into nault.cc as a seed I get the same address as atto.

I cannot reproduce this. If I go to https://nault.cc/configure-wallet > "Import Seed" and enter 102d80c52e9c4fe0a066e1e9b960d18dffdd0a4efa6328f04644d3cc066f60d9 as the seed I end up with an account (index 0) which has the address nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6.

The same thing happens with https://nanoo.tools/key-address-seed-converter.

Thus atto behaves exactly like the other wallets. None of them recognize that the private key is not a normal seed. I think this is because it's technically impossible to differentiate a seed and a private key.

If I go to https://nault.cc/configure-wallet > "Import Seed" and enter 102d80c52e9c4fe0a066e1e9b960d18dffdd0a4efa6328f04644d3cc066f60d9 as the seed I end up with an account (index 0) which has the address nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6.

This is the error, though. This private key is not a seed however nault is treating it as one (because as you said there's no way to differentiate between them), and importing it as a seed is very confusing. To get to the funds, you wouldn't use your own seed to access the funds, as you would expect. You would need to extract that specific private key from the account index you did before and use it as a seed like you would opening a new wallet with a new seed. Using your main seed there would be no way for you to know under which account index the funds are. However, if you import the key, as a private key using nault.cc, it works as intended. You have access to only 1 wallet address--which is the intended behavior.

To put this another way, importing the private key as a private key under nault, produces an address of nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr which is intended. Importing the private key as a seed produces an address of nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6 which is a perfectly valid NANO address, but it will NOT be an address contained in the original seed where the private key came from. You're essentially using an accounts private key from SEED1 as a new seed (SEED2) which will give you 4.2 billion more addresses instead of just the 1, as intended.

Perplexing issue and it seems to be a fault with NANO, not atto. However, considering the differences, and it's possible to import the private key as a private key, I was wondering if you were interested in adding this functionality to atto. It would be highly useful.

Pass the key as you would a seed and notify atto that it's a key, and not a seed;

> echo %key% | atto -k a
> nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr

The reason why this is important is because the address nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr is account index 0 for our seed 527B2633F87459B167BAF460526884FD0814990D00F5606AAE7CDA2E754700B6. But the address nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6 is NOT contained in that seed. The seed is technically the private key of nano_1c6o6pdcipwb744i4pb64gu5oaneeugmbihn1yni8f1cyn3n1t3untgthsdr. So if you add NANO to nano_3wf47wd6unwughm4xui1ohaqegaws6azyucsu6uc4rxd7saesnwizjtebuw6 and open your seed 527B2633F87459B167BAF460526884FD0814990D00F5606AAE7CDA2E754700B6 you're going to have a bad time, because there will be no NANO there.

[...] import the private key as a private key, I was wondering if you were interested in adding this functionality to atto. It would be highly useful.

Could you elaborate a little bit? In which scenarios would this be useful to you? What could you achieve with a private key export/import, that you couldn't achieve with a seed export/import?

When designing atto I had explicitly decided not to show private keys to the user to keep things simpler. It seems to me like a seed is more useful (because it can have multiple accounts). It also seems to me like seeds are what most wallets use when exporting and importing.

I'm currently not inclined to add private key support to atto, but if you can show me some compelling use case for this feature, I might ponder the idea a little more.

Nothing incredibly compelling, unfortunately. I had several ideas which would allow a user (or business) to compartmentalize transactions and funds to create microservices using Go and atto to watch specific private keys for new transactions. Then, if anything is compromised it's going to be a single private key for a single index within a seed, instead of the entire seed.

I am going to close this ticket for now. I don't want to change atto for some use case that no one is actually invested in right now.

Besides that: It's true that I tried to design atto in a way that it could be used for different kinds of scenarios and even in small scripts, but my goal is not to provide a tool for implementing advanced business logic. My intention is to provide a simple wallet for people who like the command line. If someone wants to do something "unusual", I think it's better to take a little time and write a custom wallet/tool for that. For some scenarios the atto library might even help with that.