ed25519py.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import os
  2. import warnings
  3. from collections import namedtuple
  4. from . import djbec
  5. __all__ = ['crypto_sign', 'crypto_sign_open', 'crypto_sign_keypair', 'Keypair',
  6. 'PUBLICKEYBYTES', 'SECRETKEYBYTES', 'SIGNATUREBYTES']
  7. PUBLICKEYBYTES = 32
  8. SECRETKEYBYTES = 64
  9. SIGNATUREBYTES = 64
  10. Keypair = namedtuple('Keypair', ('vk', 'sk')) # verifying key, secret key
  11. def crypto_sign_keypair(seed=None):
  12. """Return (verifying, secret) key from a given seed, or os.urandom(32)"""
  13. if seed is None:
  14. seed = os.urandom(PUBLICKEYBYTES)
  15. else:
  16. warnings.warn("ed25519ll should choose random seed.",
  17. RuntimeWarning)
  18. if len(seed) != 32:
  19. raise ValueError("seed must be 32 random bytes or None.")
  20. skbytes = seed
  21. vkbytes = djbec.publickey(skbytes)
  22. return Keypair(vkbytes, skbytes+vkbytes)
  23. def crypto_sign(msg, sk):
  24. """Return signature+message given message and secret key.
  25. The signature is the first SIGNATUREBYTES bytes of the return value.
  26. A copy of msg is in the remainder."""
  27. if len(sk) != SECRETKEYBYTES:
  28. raise ValueError("Bad signing key length %d" % len(sk))
  29. vkbytes = sk[PUBLICKEYBYTES:]
  30. skbytes = sk[:PUBLICKEYBYTES]
  31. sig = djbec.signature(msg, skbytes, vkbytes)
  32. return sig + msg
  33. def crypto_sign_open(signed, vk):
  34. """Return message given signature+message and the verifying key."""
  35. if len(vk) != PUBLICKEYBYTES:
  36. raise ValueError("Bad verifying key length %d" % len(vk))
  37. rc = djbec.checkvalid(signed[:SIGNATUREBYTES], signed[SIGNATUREBYTES:], vk)
  38. if not rc:
  39. raise ValueError("rc != True", rc)
  40. return signed[SIGNATUREBYTES:]