Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align passcode generation with kli salt #217

Closed

Conversation

kentbull
Copy link
Collaborator

@kentbull kentbull commented Feb 14, 2024

Using 32 bytes rather than 16 bytes aligns SignifyTS passcode generation with KERIpy's kli salt command.

The generatePasscode function from SignifyTS has generated some passcodes that don't end up working for me.

export function randomPasscode(): string {
    const raw = libsodium.randombytes_buf(16);
    const salter = new Salter({ raw: raw });

    return salter.qb64.substring(2);
}

From the kli salt command it is similar, though not quite the same:

print(coring.Salter(raw=pysodium.randombytes(pysodium.crypto_sign_SEEDBYTES)).qb64)

For whatever reason the libsodium.randombytes_buf(16) in Typescript doesn't produce the same results as pysodium.randombytes(pysodium.crypto_sign_SEEDBYTES)

I have seen problems with any random 21 character string which is why I started trying to constrain it with functions from Signify.

I found the following it in the Libsodium Github Repo here. In the C code

// in libsodium/src/libsodium/include/sodium
/crypto_sign.h
#define crypto_sign_SEEDBYTES crypto_sign_ed25519_SEEDBYTES

// which references the following in
// src/libsodium/include/sodium/crypto_sign_ed25519.h
#define crypto_sign_ed25519_SEEDBYTES 32U

Looks like the Python impl uses 32 bytes and SignifyTS is currently using 16 bytes.

Copy link

codecov bot commented Feb 14, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (cedee3a) 82.86% compared to head (1322013) 82.86%.

Additional details and impacted files
@@             Coverage Diff              @@
##           development     #217   +/-   ##
============================================
  Coverage        82.86%   82.86%           
============================================
  Files               47       47           
  Lines             4190     4190           
  Branches          1044     1044           
============================================
  Hits              3472     3472           
  Misses             689      689           
  Partials            29       29           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@SmithSamuelM
Copy link

SmithSamuelM commented Feb 14, 2024

There is some confusion here. A true random salt only needs 16 bytes of entropy to be cryptographically strong. The private keys for libsodium are called seeds in libsodium. They are used to generate public keys via a scalar (seed) multiplication of an ECC point. The strength of ECC scalar multiplication is only the square root of the size of the scalar (seed). So in order to have cryptographic strength of 128 bits of entropy the scalar multiplication must be 256 bits. Hence the reason for libsodium seeds being 256 bits (32 bytes). When a salt is not being used as a seed for scalar multiplication but is used to inject entropy into a hash then it only needs to be 16 bytes. The hash itself needs to be 32 bytes for the same reason. The cryptographic strength of the hash is only the square root of the size of the hash. So a 32 byte hash has only 16 bytes of cryptographic strength. So in the interest of economy, there is little to no benefit to using random Salts bigger than 16 bytes. When those Salts are used to generate hashes that that are 32 bytes or seeds that are 32 bytes. One can generate a 32 byte seed from a 16 byte SALT by taking a 32 byte hash of the 16 byte salt. For example the key management classes in keeping.py use Argon2 (which is repeated applications of Blake2b) to generate Seeds or private keys but the Salts for that key generation are all 16 byte. This is also called key stretching.

So I am careful to only use the term SALT to refer to Salty-Nonces are sources of entropy for other operations. I use the term seed to mean private key (because that is how libsodium uses seed). In general cryptogrphy salts and seeds can be synonyms, which is unfortunate. We also have shared secrets usually encryption keys whose length is usually set by the encryption algorithm. Salts are sources of entropy. In a hierchically deterministic key chain, the Salt is the source of entropy, it is the one secret that must be remembered out-of-band. So having longer Salts than absolutely necessary makes the managment of the HDM more fragile because there is more friction needed to remember and produce the Salt in order to regenerate the actual keys. So keeping the Salt at the minimum overall improves the usability of the HDK without materially affecting its security. (one something is computationally infeasible, multiplying that computational infeasibility is just wasted effort.

@kentbull
Copy link
Collaborator Author

Thank you for the detailed explanation with distinctions between the salt and seed. This makes sense to me now. I'll close this issue.
If I understand correctly what you've said then for consistency we may want to change the kli salt command in KERIpy to use only 16 bits of entropy.

@kentbull kentbull closed this Feb 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants