Skip to content
Inkeliz edited this page May 1, 2018 · 11 revisions

The SEEDFY is very similar to one common SEED, which you probably have one noted in some place. The SEEDFY, unlike the common SEED, doesn’t guarantees immediately access to your funds. It’s have one new secure goal, which if someone stole your SEEDFY him can’t access your funds without the correct password, choose by the user. The SEEDFY needs only 5 bytes more than common SEED, the space used is closely the same.

At one high level description the SEEDFY can be considered as one SALT for the Argon2id, the KDF algorithm. Though, the SEEDFY also keeps the computation cost used in the KDF, like the how much memory used, the number of threads and so on.

But, the SEEDFY isn’t consumed directly, since we have one Blake2 Keyed Hashing before, this hashing creates the real SALT used in the KDF. This step makes possible to have multiples keys together, it can be used for some sort of 2FA.

Goals:

The main goal of the SEEDFY are described below.

  • Create random keys:

    The SEEDFY should result in one random-looking data, which can’t be distinguishable from one true random data and can’t be predictable by adversary.

  • No unauthorized user, that know the SEEDFY, can gain access to the funds:

    The SEEDFY shouldn’t be one key itself, the SEEDFY should be one random-looking value with cost parameters that will be combined with one password in order to create the SEED. The SEEDY should have higher computational cost for each attempt, that’s will make one exhaustive-search, against the non-random user supplied-input, more expensive at level to be negligible chance of success.

  • No malicious processes can gain the information about the SEEDFY:

    The SEEDFY should have marginally defense against side-channel attacks, avoid lookup-tables and branches with the secret-data. If one software have unrestricted access to the all memory it can not be protected.

Flaws and Cons:

Due to the construction of the SEEDFY, one honest user can type one wrong password, consequently that user gets one completely distinct key. The user have no clue if the password is correct or not, only if him remember the address itself. This problem should be mitigated in the version 2, at a cost of more bytes to store.

If the user lost the password, or even lost the SEEDFY itself (or any additional keys), the funds can’t be recovered by any other means, maybe only by an expensive exaustive-search.


Construction:

The construction of the SEEDFY is spliced into fourphases, which leads us into:

  1. SEEDFY

    The SEEDFY is the cost parameters and the salt, which will be consumed by the KDF.

  2. SEED

    The SEED is the result of the KDF, it’s the result of the derivation with the Password and SEEDFY.

  3. COINSEED

    The COINSEED is the result of the derivation of two values, the SEED and the COIN, which is the uint32 number of the currency (i.e. NANO = 1).

  4. SK

    The SK is the private-key used in Nano, or in any other currency compatible. The private-key allow the user to have access to the funds, also creates the public-key and address associated with.


SEEDFY:

The SEEDFY is exactly:

HEX(VERSION || TYPE || TIME || MEMORY || THREAD || SALT)

All parameters, except for SALT, is just one byte. The definitions are the follow:

Parameter Default Usage in KDF
version 0x00 -
type 0x00 -
time 0x0F time
memory 0x15 (1 << memory) & 0x1F
thread (max available) thread
salt (random) -

Derivation:

The derivation, the process to gets the SEED from the SEEDFY will wok as follow:

The cost parameter need to be extracted from the SEEDFY, it works as follows:

SEEDFY = HexDecode(SEEDFY)
TIME   = SEEDFY[2]                // Second byte
MEMORY = 1 << (SEEDFY[3] & 0x1F)  // 1 shift by the six least significant bits of the second byte
THREAD = SEEDFY[4]                // Third byte
SALT   = SEEDFY[5:37]             // 32 bytes from 5 to 37

First, creates the Salt, the Salt is construct using the Blake2b Keyed Hash, with size of 32 bytes. The additionaldata should be nil if it user is not using any features like 2FA:

SALT = Blake2b(size = 32, key = SALT, message = additionaldata)

After the computation of the salt, and the extraction of the parameters, we need to use this salt with the ArgonID, the password is an user-input value, which at least should have eight-byte size.

SEED = ARGON2id(password = ?,  salt = SALT, ttime = TIME, memory = MEMORY, thead = THEAD)

The password should have at least 8 bytes.

Testing:

If you are developing one implementation make some tests with:

SEEDFY = "00000A0510F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"
PASSWORD = "myamazingpasswordthatisverygoodenough"

EXPECTSEED = "15AC010515107C4AD61E4527CD8E43A9F6B4BD4FA6F1536361F3DA686B0A88BC"
//-----
SEEDFY = "00000A0510F0F0F0F0F0F0F0F0F0F0"
PASSWORD = ""myamazingpasswordthatisverygoodenough"

EXPECTSEED = {ERROR} // SEEED is too short
//-----
SEEDFY = "00000A0510F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"
PASSWORD = "abc"

EXPECTSEED = "{ERROR}" // PASSWORD is too short

COINSEED:

The COINSEED is generate using the Blake2X, instead of the Blake2b. The COINSEED need two inputs, the secret-key and also the public-identifier of the coin, listed below.

Parameter Identifier Size
Base 0x00000000 32
Nano 0x01000000 32
Banano 0x02000000 32

Derivation:

The identifier itself is one uint32 in Little-Endian. The creation of the SEEDCOIN requeres the SEED, created in already the previous topic.

COINSEED = Blake2X(size = SIZE, key = SEED, message = IDENTIIER)

Testing:

SEED = "15AC010515107C4AD61E4527CD8E43A9F6B4BD4FA6F1536361F3DA686B0A88BC"
SIZE = "32"
COIN = "01000000"

EXPECTEDCOINSEED = "171B41B89B92790BDFB302273BC43277A302D1F9D31AF09F967AFE9CDFC524CF"

ADDRESS:

The address of wallet is created based one the priva-key.

Derivation

We follow the same structure from COINSEED, but instead of use the COIN IDENTIFIER, we use the sequencial index. This index is needed to generate many address with one seed. This uses the COINSEED and the INDEX.

SK =  Blake2X(size = SIZE, key = COINSEED, message = INDEX)

This must be your Ed25519 key, remember that the Ed25519 need to lower some bits, it's not in topic here.


Q&A

  • Why use the BLAKE2X instead of Blake2b?

    It's was one problematic topic, the Blake2X is capable to generate more data than just 512 bits, but is uncommon. The Nanollet is built to support more than just Nano, because of that the Blake2X was chosen, since it is capable to generate more than 1GB of SEED. If some other currency use one key with more than 512bits, we can support without changes.

  • Why choose the Argon2id?

    The Argon2 itself is the winner of PHC, this is computational hard and prevents the exhaustive search. The official wallet already uses the same algorithm for derivation.

  • Why uses the Blake2b Keyed Hashing to create the salt?

    Well, he might want to have multiples keys or even split theses keys, for instance the 2FA. If we don't use the hash the adversary could have a little advantage, because him can holds the first block of the hash already compressed, if the message and the block have the same size.

  • Why don't use the standard SEED?

    They don’t fit in the defined goal.

  • Why don't concatenate the SALT and the SEED, as the original wallet does?

    Because the Blake2 have built-in the KDF function, so the Nanollet uses the functions as they supposed to be used. The authors of the Blake2 described the uses of the Keyed Hashing, one of those is the KDF. So, it more probable to be secure than the concatenation.

Clone this wiki locally