-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Storing keyset on disk encrypted with password #347
Comments
Hi there, If you use Android, you can store the keys wrapped with a master key in Android. The master key is just an alias, doesn't actually contain any key material. If you want something equivalent to GnuPG, I guess you'd have to develop it yourself atm. You take the password, scrypt/argon2 it, and use it as a key for AesGcm which in turn is use to encrypt the keyset using |
Please reopen this if you want to discuss more. Thanks! |
Hi and thank you for your pointers on where to start, now I had some time to think over and experiment with this. I am not targeting Android with my project. I have been experimenting but I can not see how to go from the password to some secret hash or code that can be used to write the private key and then read it back. Below is one of my attempts: // create new keys
Argon2 argon2 = Argon2Factory.create();
String argonHash = argon2.hash(15, 65536, 1, askForPassword().toCharArray());
AesGcmJce aesKey = new AesGcmJce(argonHash);
KeysetHandle privateKeyset = KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256);
File privateKeyFile = new File(Paths.get("key-" + args[1]).toUri()); // name/location of the new key
privateKeyset.write(JsonKeysetWriter.withFile(privateKeyFile), aesKey); First the argon hash is over 700 bits and AesGcmJce expects 128 or 256 bits. I could just take the last 256 bits of the digest value but argon2 adds a salt so one password gives new hash values every time. Salt is something good so its the wrong solution to try to work around it. That means I must save the hash and then use argon-verify to check the password. If I save the hash I can not use anything in the hash to access the key because then someone can just check the code and use the right section of the saved hash without needing the password. If I pass the password directly to AesGcmJce then it needs to be 16 or 32 characters long (128/256 bits), but then argon does not do anything required. I could also do the old SHA256 on the password so it does not need to have a specific length and plain SHA256 does not add a salt so I can run it again to get the same result and read the key back, but the entire purpose of argon is a more secure hash and not use SHA... The AesGcm documentation that @thaidn linked shows encrypt/decrypt methods that can take an additional data argument of any length but I have the same problem there, what to input ...And then that key needs to be saved somewhere (or regenerated?) first before using it to encrypt/decrypt anything. |
I guess you'd have to use an Argon2 library that allows you to pick the salt yourself. You then store the salt and can recompute the hash from the password.
KeysetHandle.write(keysetWriter, aead) currently doesn't use this associated data field. |
Saving the salt... An easy answer, yet I could not figure it out my self! That should be the secure way to do it. The library I found do allow me to set the salt manually.
One of my thoughts, then trying to find a solution, was around calling A first version that allows creating password-protected keys and using them to create/verify signatures is now up on my GitHub https:/Stekeblad/Password-based-TinkTool. Thank you thaidn for your help! |
Glad that it works for you. I briefly skimmed https:/Stekeblad/Password-based-TinkTool and it looks good to me. Note that users usually pick very weak passwords. Argon helps, but doesn't completely stop determined adversary from cracking most passwords. I suggest adding a warning or something about that. |
From "Tink for Java HOW-TO":
Is there a way to not save a key in cleartext that does not depend on a on a remote keyserver or another key (that needs to be saved in cleartext or depend on a remote keyserver)?
With GnuPG you can set a password on the private key when its generated and you need to enter it every time you need to use it, can something similar be done with Tink? I do not want to write the private key to disk in cleartext and I do not want to configure and depend on a keyserver somewhere.
I have looked at Tink for Java HOW-TO and the Tinkey documentation but I can only see cleartext and remote keyserver examples.
The text was updated successfully, but these errors were encountered: