-
Notifications
You must be signed in to change notification settings - Fork 231
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
Allow initializing SigningKey from a raw key #648
base: main
Are you sure you want to change the base?
Conversation
Looks good to me - thanks |
There is no difference between string and bytes in Python 2.7
An alternative would be to just check the length of the argument -- if it's 32 bytes, assume it's a seed, and if it's 64 bytes assume it's a full Ed25519 secret key (including the public key). That would also be backwards compatible, and may be a bit more intuitive. The version implemented in this PR requires reading the docs. |
I think calling it key is misleading since the 32-byte value is called a key basically everywhere that isn't Other than that I'm okay with this approach. |
@reaperhulk OK. So should I change the argument from (Aside from that, I realised that I used the term "private key" in the docs. I guess I should probably replace that with "secret key".) |
Let’s do secret_key |
OK, I've changed the argument name from I didn't change the term "Private Key" in the docs to "Secret Key" since "Private Key" is used everywhere in the docs. |
Looks like this needs a black format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two final requests: instead of an assertion error I’d prefer a value error when the values are both None (you can do this with raising=exc.ValueError) and also please add a changelog entry. Thanks for working on this!
Should also accept 32 byte plain keys. This 64-byte combined key format of libsodium is quite annoying, and too often I end up doing hacks like |
@covert-encryption Can you be more specific what you mean with "32 byte plain keys"? It sounds like you are talking about the value that PyNaCl and libsodium call "seed", so you could just create a What this PR adds is allowing to create a SigningKey from the 64 byte value that libsodium calls a secret key (which is just the 32 byte seed and the 32 byte precomputed public key concatenated). |
OK, but does this have anything to do with this PR? |
@jakob I can approve and merge this once the two small comments in the review are fixed! |
The documentation in this PR is quite misleading:
This seems to be implying that the seed "generates" something, but neither of these are used to "generate" anything, nor are they actually any different as the description is implying. The starting point everywhere in libsodium is the seed and is really the only thing that ever should be stored. The only difference is that, for computational convenience, libsodium wants to have a precomputed public key so that it doesn't have to be computed in many different functions. I'm also pretty skeptical of the claim that
How does Perhaps, rather than adding two separate arguments for almost identical purposes, the |
Neither libsodium nor pynacl mention in the docs that this is possible. You have to read the source code to know that. I didn't know that when I started on this PR. It seems that libsodium tries to hide the fact that a secret key is just the concatenation of seed and publickey. Why else would they have functions like crypto_sign_ed25519_sk_to_seed? |
That's fair. I'd suggest at least a change to "secret key" instead of "private key" for the args/documentation then. Private key immediately makes me think of the private key scalar, which is what a pynacl PrivateKey is (and, somewhat perversely, the PrivateKey that you get back from a |
Currently,
SigningKey
must be initialized from a 32 byte seed.However, sometimes you already have the 64 byte Ed25519 private key, and not the seed. Then it's very inconvenient to create a
SigningKey
object from the key bytes.This problem was initially reported by @dmerejkowsky in issue #419. Recently, @BlackTurtle123 opened issue #639, which is also about the same problem.
The problem is that most applications probably store the 64 byte Ed25519 key rather than the 32 byte seed, since that should be faster as you don't need to re-compute the public key every time.
This Pull Request adds an additional argument
key
to theSigningKey
initializer. You can use this argument to create aSigningKey
directly from the raw Ed25519 private key bytes.The new signature proposed in this PR is:
SigningKey(seed=None, encoder=encoding.RawEncoder, key=None)
key
is an optional 3rd argument in order to maintain backward compatibility with existing code.Example usage of the new code: