9

Using monero-wallet-cli --restore-deterministic-wallet with the following seeds can restore the same wallet:

First seed: lawsuit artistic jeans lair plus village potato cedar certain sizes ruthless ingested girth films pegs cage exult zombie wade pumpkins candy wetsuit utopia claim potato

Second seed: guarded sake aisle kidneys mayor session vastness wiggle arsenic camp sixteen doing girth films pegs cage exult zombie wade pumpkins candy obnoxious wayside abyss sixteen

Why? Is it safe to keep using the old (first seed) years from today?

More info from this: Using old 0.9.4 wallet

2 Answers2

10

TL;DR first is completely random seed, 2nd is the "normalized" seed, and they're both valid and resolve to the same wallet. As long as you know the method to go from mnemonic to the actual private key, you're safe to keep it as it is.

The first is a just some random 256 bits, probably generated by other means and the second is the "normalized" seed, meaning it's a number smaller than l (a parameter specific to the elliptic curve used in monero cryptography scheme). Both seeds resolve to the same private spend key and are equally valid. The private spend key is the important piece of data which is used on the protocol level. You could even use your own, custom, mnemonic scheme to get from mnemonic/seed to private spend key. The protocol doesn't care about the mnemonic/seed, only about the 4 keys (spend keypair and view keypair)

If you restore the wallet with the first seed, and after restoring use the "seed" command, the wallet will print the second seed. This is because it automatically normalizes the seed. Let me elaborate.

First of all, your mnemonic is a representation of a 256 bit integer, ie a very very big number. This number is your seed, and from it the keys are derived and those are actually used in cryptography on the protocol level. There is a function which converts between the number (seed) and the mnemonic. How the conversion works, is explained here.

To get the private spend key, the seed is passed through sc_reduce32 function:

privSpend = sc_reduce32(seed)

if the seed is a random 256bit integer, then it can happen that:

seed != sc_reduce32(seed)

however, if your seed has already been passed through sc_reduce32 function, then it's what we call a "normalized seed" and both the seed and privSpend will be the same, i.e. passing a normalized seed through sc_reduce32 results in the exact same number.

n_seed = privSpend = sc_reduce32(seed)
n_seed == sc_reduce32(n_seed)

Since n_seed != seed, the mnemonic corresponding to each of them will also be different.

You could easily produce the normalized seed yourself, by playing with this page:

  1. Type in your first seed into box 1.
  2. Click "Gen 2." and "Gen 3. & 4.", notice that 2. & 3. are different.
  3. Copy the value from box 3. into box 2.
  4. Click "Gen 1." and "Gen 3. & 4.", you will notice 3. and 4. didn't change and 2. & 3. are now the same.
JollyMort
  • 19,934
  • 3
  • 46
  • 105
  • 3
    it's a point on the elliptic curve It's really a scalar < l; public keys are curve points. – Luigi Sep 30 '16 at 22:16
  • 1
    care to elaborate what a "scalar" means in EC context? I'd like to expand it a bit, would also like to understand what sc_reduce32 actually does – JollyMort Oct 01 '16 at 02:49
  • 2
    @JollyMort: Let P be a point on the EC, which is closed under addition. Then if denote 2P := P+P, that will still be a point on the curve. Similarly, so will 3P := P+P+P, 4P := P+P+P+P etc. So that nP just means "add P to itself n times". We call that integer n a scalar. // The point about the order l* of the base point G is that lG will be the identity, in other words: nG will be all different points on the curve for n in {1,2,...,l} but beyond that you will just repeat the list of points. – user141 Oct 01 '16 at 16:02
  • I understood that, thanx. So why, in the below example, is the reduced integer "larger" than the original (n=6d32... n_red=938a...) if the requirement is n < l and our n_red > n which implies n_red > l if we started with n > l. – JollyMort Oct 02 '16 at 05:12
  • @JollyMort: I don't understand sc_reduce32 well, so right now I can't help understanding whether n_red > n is a problem or not, sorry. Note however that n < l and n_red > n does not imply n_red > l; it could be that n < n_red < l. // On the other hand, looking at Luigi's comment and your reply to it, I think his point was just that in EC cryptography the private key is simply a random secret number r, unlike the public key P which is actually a point on the curve (such that P = r*G, for a fixed base point G in the curve). – user141 Oct 03 '16 at 00:23
  • I've been looking at it wrong. The keys seem to be little-endian, and then n_red < l < n holds true for the below example. Looking at the code of sc_reduce32 I couldn't understand because it seems to be a optimized C function which I believe performs a n mod l operation, resulting in our n_red < l, as implemented here. – JollyMort Oct 03 '16 at 07:49
  • 1
    Yes that's all sc_reduce32 does. Private keys are indeed little endian. – Luigi Oct 03 '16 at 17:06
6

This answer just reiterates the point Jolly Mort made above with a reference example. The answer to your question concerns the Monero normalization function sc_reduce32() plays when it operates on a seed to create the effective private spend key. Normalized numbers fed to the sc_reduce32() function won't be modified. (Note the example key below is not a secure one.)

% echo "The girl has gone Monero!" | bx base16-encode | bx sha256 6d325642de6bd6aaae6a54ed1d9db564c4081793e3adad171f979058de535627

% ./sc_reduce32 6d325642de6bd6aaae6a54ed1d9db564c4081793e3adad171f979058de535627 938a6a88a9a5b1fa013165a760a9f73ac4081793e3adad171f979058de535607

Experiment with https://xmr.llcoins.net/addresstests.html.

  1. Insert the first hexadecimal number above into the Hexadecimal Seed field, and click on the Gen 1. button.

    The following words result:

    dating buying hover rudely suitcase lemon younger addicted vigilant anvil bovine lyrics simplest copy rugged eldest locker nylon roles rover avoid yellow oncoming semifinal younger

    After clicking Gen 3 & 4., Gen 5., Gen 6., and Gen 7. the following should be the stealth address:

    49Dw3cqJycuEtQvAr3kPiYjX1yiHMDrwr5fqiMr5hCf3MvDGgFjwdXSNCDRpb7N195C81V9wXLZgHWsuEYVwtaNGN9JERGc

  2. Insert the second hexadecimal number into the Hexadecimal Seed field and repeat the process above. Notice how the the Hexadecimal Seed and Private Spend Key fields are the same and the stealth address is the same, but the 25 Electrum words are now:

    mesh deepest rhino tadpoles picked oyster river wept optical fictional lectures remedy simplest copy rugged eldest locker nylon roles rover avoid august paddles pizza simplest

JollyMort
  • 19,934
  • 3
  • 46
  • 105
skaht
  • 1,576
  • 11
  • 19