ed25519py.py 1.7 KB

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