pynacl icon indicating copy to clipboard operation
pynacl copied to clipboard

Add utility for loading a secret key from a defined format

Open kevinburke opened this issue 7 years ago • 7 comments

The secret key for use with e.g. secretbox should be 32 random bytes. A common mistake is to use only bytes that can be easily typed on a keyboard, like "secret password change me [padded to 32 bytes]" or E%m"lBVK=9&m6GRkm9n'c17C6Csd9?0C.

Part of the reason people do this is that E%m"lBVK=9&m6GRkm9n'c17C6Csd?0C is easier to store in e.g. a YAML file or environment variable than b'\xbf\x9e\x0e\xe6J\xe0T,\xc6\xa5\x81i\xc9\xf2\xb1#?\xf1\xa8\x96Q\xc9\x84\xe9\x8f\xe5\xec\x921\x06\xb2\xef'.

It might be good to define a standardized format in nacl.utils for loading printable, config-safe keys, into 32 bytes of random. One would be to load 64 hex bytes, like a20fbda2e9143075aa2a919c941eaad86652b17eacc4bc816fe399ce2b78c11d, into 32 random bytes.

Then you would put SECRET_KEY=a20fbda2e9143... in the environment and write:

key = nacl.utils.load('a20fbda2e9143075aa2a919c941eaad86652b17eacc4bc816fe399ce2b78c11d')
# or
key = nacl.utils.load(os.environ['SECRET_KEY'])

or load_32 etc. I maintain a Go nacl client and this is the strategy I use for letting users load keys. https://godoc.org/github.com/kevinburke/nacl#Load

Alternatively, you could have load_from_password('hunter2'), which could derive 32 bytes of random from a string using a suitable key derivation function like scrypt.

kevinburke avatar Aug 14 '18 16:08 kevinburke

I think this is mostly a documentation problem, and I'd reccomend against any kind of direct secret key [de-]serialization. Instead, we should point users to generate and serialize a random salt and then derive secrets via a good password-based key derivation functions like the pynacl provided argon2d scrypt, or pbkdf

lmctv avatar Aug 17 '18 07:08 lmctv

I want to argue that this is a needed functionality as well: Unless you're arguing that users shouldn't have any secrets with a lifetime longer than one run of the program, there needs to be some kind of support for saving and loading them in well-defined formats.

ewa avatar Nov 29 '18 23:11 ewa

(I'm sure this is a documentation question, but it's still and important one. Whether I'm serializing and saving a private key as such, or I'm saving an initial salt value and re-deriving the key, I still need a process for turning the results of that process into a PyNACL SigningKey (or PrivateKey) object. I'm positive it's possible, and I'm even pretty sure I've done it before, but I don't see how to do it now.) Any input would be welcome.

ewa avatar Nov 30 '18 17:11 ewa

any progress on this issue? the lib is kinda unusable without this no?

shriphani avatar Feb 14 '19 01:02 shriphani

I ended up writing a helper myself... you can still pass raw bytes directly to pynacl

kevinburke avatar Feb 14 '19 04:02 kevinburke

Do you have a snippet somewhere ? Would appreciate a link.

shriphani avatar Feb 14 '19 04:02 shriphani

There is now a draft standard for serializing Ed25519 keys in ASN.1 format: RFC 8410.

blag avatar Apr 12 '19 08:04 blag