1
# -*- coding: utf-8 -*-
6
from collections import namedtuple
9
__all__ = ['crypto_sign', 'crypto_sign_open', 'crypto_sign_keypair', 'Keypair',
10
'PUBLICKEYBYTES', 'SECRETKEYBYTES', 'SIGNATUREBYTES']
16
Keypair = namedtuple('Keypair', ('vk', 'sk')) # verifying key, secret key
18
def crypto_sign_keypair(seed=None):
19
"""Return (verifying, secret) key from a given seed, or os.urandom(32)"""
21
seed = os.urandom(PUBLICKEYBYTES)
23
warnings.warn("ed25519ll should choose random seed.",
26
raise ValueError("seed must be 32 random bytes or None.")
28
vkbytes = djbec.publickey(skbytes)
29
return Keypair(vkbytes, skbytes+vkbytes)
32
def crypto_sign(msg, sk):
33
"""Return signature+message given message and secret key.
34
The signature is the first SIGNATUREBYTES bytes of the return value.
35
A copy of msg is in the remainder."""
36
if len(sk) != SECRETKEYBYTES:
37
raise ValueError("Bad signing key length %d" % len(sk))
38
vkbytes = sk[PUBLICKEYBYTES:]
39
skbytes = sk[:PUBLICKEYBYTES]
40
sig = djbec.signature(msg, skbytes, vkbytes)
44
def crypto_sign_open(signed, vk):
45
"""Return message given signature+message and the verifying key."""
46
if len(vk) != PUBLICKEYBYTES:
47
raise ValueError("Bad verifying key length %d" % len(vk))
48
rc = djbec.checkvalid(signed[:SIGNATUREBYTES], signed[SIGNATUREBYTES:], vk)
50
raise ValueError("rc != True", rc)
51
return signed[SIGNATUREBYTES:]