pyca / pyca/pynacl

It is awkward to instantiate a SigningKey from its value.

Open
#419 4 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
1.2k
Forks
267
Avg merge
42m
Merged PRs (30d)
2

Description

Use case:

We have a signing keypair that has been generated by an other program in a different language, and we need to sign and verify messages with them.

The naive way does not work:

message = b'this is a message'
raw_signing_key = b'....' # a bunch of bytes of length 64
signing_key = SigningKey(raw_signing_key, encoder=RawEncoder)
signing_key.sign(message)

That's because the SigningKey constructor expects a seed, not the value:

# in src/nacl/signing.py
class SigningKey(...):

    def __init__(self, seed, encoder=encoding.RawEncoder):
        ...
        public_key, secret_key = nacl.bindings.crypto_sign_seed_keypair(seed)

We have a workaround, though:

We assing the _signing_key variable directly:

message = b'this is a message'
raw_signing_key = b'....' # a bunch of bytes of length 64
fake_seed = b"\0" * 32
signing_key = nacl.signing.SigningKey(fake_seed)
signing_key._signing_key = raw_signing_key
signing_key.sign(message)

And then we can verify the signature by instantiating a VerifyKey directly:

raw_verify_key = b'....' # bunch of bytes of length 32
verify_key = nacl.signing.VerifyKey(public_key, encoder=RawEncoder)

Of course, this is a bad idea because if you use signing_key.verify_key you get the wrong key ...

Proposed fix

Maybe we could have something like this instead ?

class SigningKey:
    @classmethod
    def from_value(signing_key):
           res = cls()
           res._signing_key = signing_key
           res.verify_key = VerifyKey(bindings.crypto_sign_ed25519_sk_to_pk(signing_key))

And then:

signing_key = SigningKey.from_value(raw_signing_key)

Thoughts ?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/nacl/signing.py with SigningKey.init and its verify_key behavior. Review the proposed raw-key construction and crypto_sign_ed25519_sk_to_pk entry point, then define the API and validation needed so a 64-byte signing value produces the matching public key; done means signing and verification use the imported keypair correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cryptography, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.