cosmjs
cosmjs copied to clipboard
Generate and store salt
Hello. It there any way to make salt configurable?
https://github.com/cosmos/cosmjs/blob/f198f0acc425051f0ebd71489d993d7851b48475/packages/proto-signing/src/wallet.ts#L15
I found a way to replace that file. And put salt to the env variable:
new webpack.NormalModuleReplacementPlugin(
new RegExp('@cosmjs/proto-signing/build/wallet.js'),
path.resolve(
__dirname,
'replaced/wallet.js'
)
)
Of course someone can find the value in a builded js, but it looks harder.
Hello. It there any way to make salt configurable?
Heyho! Why do you want to do that? I'd be curious about a detailed motivation and usecase description. If it makes sense to do, it should be trivial to make it configurable through proper APIs.
Of course someone can find the value in a builded js, but it looks harder.
Are you sure you're on the right path here? The salt is not a secret value. It's public and that's perfectly fine. It just makes rainbow attacks harder.
While wallet development, I decided that If It just makes rainbow attacks harder, why not make it a bit more harder with "hidden" salt from env variable.
Okay, so one scenario could be this: All CosmJS users use the same salt. One can come up with a rainbow table of passwords that are all hashed with one salt in order to attack CosmJS users. Now what you can do is override the salt in each application. Still no need for env variables and hiding. Then you need application specific tables instead of lib specific tables, making them much harder to generate or less attractive.
I'm unsure if this is worth it. Changing the argon 2 parameters should be enough to get unique hashes and at the same time tune the difficulty of the KDF. Then if you push this computation to a WebWorker to not freeze the UI you can go really high with your params. Development effort is much more worth there. Also this heavily reduces the risk that an encrypted wallet cannot be decrypted anymore because you remain compatible with standard CosmJS tooling.
Then you need application specific tables instead of lib specific tables, making them much harder to generate or less attractive.
That was the goal. Instead of lib specific tables has different application specific tables so one table can't be used to any app.
Yeah. This can be done and there is nothing wrong with it. But I highly recommend not making this a priority and don't implement costy and risky hacks for it.
I leave this ticket open to make the salt configurable. This is easy to implement.
I wonder if we could just store the salt together with all other argon2 options. The options need to be read anyways before the decryption. Then we can automatically generate a new salt for every encryption.
Agree, it could be an option with default value "The CosmJS salt.".
@webmaster128 I don't have problems to provide a new PR. But not right now or today. Maybe tomorrow's evening.
@webmaster128 maybe it will be ready even at tomorrows daytime. Looks easy to do. But next should be carefully rechecked at review.
Alright, go ahead. No rush. I'll look at it then.
will try to add *.spec.ts if my PR will not include it, feel free to add yours.
Looking at the new title, I just want to make sure we are on the same page:
- Salt is randomly generated, not configured at encryption time
- It is stored together with the other Argon2 options in a field
salt?: string(hex or base64 encoded) - When decrypting, the salt is used. When non-existent, the default salt is used.
This means we don't have any additional work for the user of the library – just upgrade.
@webmaster128 so with random generated salt we will get not an app specific salt, but encryption specific salt and it should be a part of encrypted result. Right?
we will get
not an app specificsalt, butencryption specific salt
Exactly. Better salting with no configuration.
and it should be a part of encrypted result
It would be stored next to the encrypted data in the config that stores the Argon2 options. The salt is unencrypted (can be public) but unique then.
Thanks. Got that. To create random salt for each encryption and store it next to a cipher.
@webmaster128 it should be just serialized.salt?
here is the example:
const serialized = {
type: "directsecp256k1hdwallet-v1",
kdf: {
algorithm: "argon2id",
params: {
outputLength: 32,
opsLimit: 24,
memLimitKib: 12 * 1024,
},
},
encryption: {
algorithm: "xchacha20poly1305-ietf",
},
data: "",
salt: "",
}
Here is tests. Will improve them and change it('') titles to lowercased, as all spec.
The steps are done as follows:
- User provides password string, possibly low entropy
- The KDF turns this string into a byte series using a hard to bruteforce algorithm that is configurable. This KDF may or may not have a salt. A output length for the encryption key is configured.
- The encryption is performed using the encryption key from 2.
Step 3 does not know where the encryption key comes from. It does not know which KDF is used and what a KDF even is. It does not know what a salt is because encryption has no salt.
So the salt clearly belongs to the KDF step. And it is algorithm specific. For this reason I would pout it in kdf.params and Argon2idOptions.
What do you think about to code that? Does't looks like I have a lot of time for that. In any case will back to it this week, please mark this issue in a commit #903
What do you think about to code that? Does't looks like I have a lot of time for that.
So far I only see two tests. Without a (draft) PR it's hard to see what you did.
But if you don't make it, I'll implement this at some point.
@webmaster128 I got emergency things to do. In any case I'm glad of the participation, feel free to implement. Tests are not so good, at least the second one.
@webmaster128 I removed second test, and change the first one.
@webmaster128 please, have a check my PR: added backward compatibility test: serialize with current DirectSecp256k1HdWallet version, and deserialize with the updated one. Please, review it. Maybe I need to add some other cases for other packages?
@webmaster128 link https://github.com/cosmos/cosmjs/pull/906/
Nice start, but no implementation in #906.
I started working on this myself now. It's a bit tricky becasue of the API design that allows KDF execution on a different thread (e.g. WebWorker). Will keep you updated on progress.
@webmaster128 I appreciate that, thanks. I can't find any time for that.
@webmaster128 hello, can you please closer describe the problem? I will try to find some time for the help.
@webmaster128 hello I will try to prepare the PR. I guess that I can just use something like:
import { Random } from '@cosmjs/crypto'
const salt = Random.getBytes(sodium.crypto_pwhash_SALTBYTES);
@webmaster128 it may be like that
But next I should return the salt itself with
https://github.com/cosmos/cosmjs/blob/663d39c7bb645a8a420ef8e2c7444ccf68e8d718/packages/crypto/src/libsodium.ts#L46 and it use libsodium-wrappers package
@webmaster128 hello. random salt is already used in the wallet module
https://github.com/cosmos/cosmjs/blob/486ab65ed9d0d935c3f15760e64cbf707a85a1b4/packages/proto-signing/src/wallet.ts#L55-L72, but not in the directsecp256k1hdwallet https://github.com/cosmos/cosmjs/blob/fcf01d4b09ed2cda3edff5e5d75f3670d22ddd77/packages/proto-signing/src/directsecp256k1hdwallet.ts#L294-L298
https://github.com/cosmos/cosmjs/blob/fcf01d4b09ed2cda3edff5e5d75f3670d22ddd77/packages/proto-signing/src/wallet.ts#L26-L36
@webmaster128 hello. I finally found time to make that contribution better. xchacha20poly1305Ietf salt also gets type Uint8Array right now.