From dafb2da44bb35c7057744ca820833cde6d43c534 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Thu, 26 May 2016 09:26:09 +0100 Subject: [PATCH] pubkey.c, ...: Support Bernstein's `Ed25519' signature scheme. Organization: Straylight/Edgeware From: Mark Wooding --- catacomb-python.h | 1 + catacomb.c | 1 + catacomb/__init__.py | 16 +++++++++++++ pubkey.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/catacomb-python.h b/catacomb-python.h index 679920f..41c5292 100644 --- a/catacomb-python.h +++ b/catacomb-python.h @@ -88,6 +88,7 @@ #include #include #include +#include #include #include diff --git a/catacomb.c b/catacomb.c index 1d6f7f6..d64a16e 100644 --- a/catacomb.c +++ b/catacomb.c @@ -46,6 +46,7 @@ static const struct nameval consts[] = { C(KF_BURN), C(KF_OPT), C(EC_XONLY), C(EC_YBIT), C(EC_LSB), C(EC_CMPR), C(EC_EXPLY), C(EC_SORT), C(X25519_KEYSZ), C(X25519_PUBSZ), C(X25519_OUTSZ), + C(ED25519_KEYSZ), C(ED25519_PUBSZ), C(ED25519_SIGSZ), #define ENTRY(tag, val, str) C(KERR_##tag), KEY_ERRORS(ENTRY) #undef ENTRY diff --git a/catacomb/__init__.py b/catacomb/__init__.py index 115e8fe..9522528 100644 --- a/catacomb/__init__.py +++ b/catacomb/__init__.py @@ -495,6 +495,22 @@ class X25519Priv (_BoxyPriv, X25519Pub): def _op(me, k, X): return x25519(k, X) def _hashkey(me, z): return hsalsa20_prf(z, Z128) +class Ed25519Pub (object): + def __init__(me, pub): + me.pub = pub + def verify(me, msg, sig): + return ed25519_verify(me.pub, msg, sig) + +class Ed25519Priv (Ed25519Pub): + def __init__(me, priv): + me.priv = priv + Ed25519Pub.__init__(me, ed25519_pubkey(priv)) + def sign(me, msg): + return ed25519_sign(me.priv, msg, pub = me.pub) + @classmethod + def generate(cls, rng = rand): + return cls(rng.block(ED25519_KEYSZ)) + ###-------------------------------------------------------------------------- ### Built-in named curves and prime groups. diff --git a/pubkey.c b/pubkey.c index 50fa78c..391db31 100644 --- a/pubkey.c +++ b/pubkey.c @@ -1136,6 +1136,57 @@ end: return (0); } +/*----- Ed25519 -----------------------------------------------------------*/ + +static PyObject *meth_ed25519_pubkey(PyObject *me, PyObject *arg) +{ + const char *k; + Py_ssize_t ksz; + PyObject *rc = 0; + if (!PyArg_ParseTuple(arg, "s#:ed25519_pubkey", &k, &ksz)) goto end; + rc = bytestring_pywrap(0, ED25519_PUBSZ); + ed25519_pubkey((octet *)PyString_AS_STRING(rc), k, ksz); + return (rc); +end: + return (0); +} + +static PyObject *meth_ed25519_sign(PyObject *me, PyObject *arg, PyObject *kw) +{ + const char *k, *p = 0, *m; + Py_ssize_t ksz, psz, msz; + PyObject *rc = 0; + octet pp[ED25519_PUBSZ]; + char *kwlist[] = { "key", "msg", "pub", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|s#:ed25519_sign", kwlist, + &k, &ksz, &m, &msz, &p, &psz)) + goto end; + if (p && psz != ED25519_PUBSZ) VALERR("bad public length"); + if (!p) { p = (const char *)pp; ed25519_pubkey(pp, k, ksz); } + rc = bytestring_pywrap(0, ED25519_SIGSZ); + ed25519_sign((octet *)PyString_AS_STRING(rc), k, ksz, + (const octet *)p, m, msz); + return (rc); +end: + return (0); +} + +static PyObject *meth_ed25519_verify(PyObject *me, PyObject *arg) +{ + const char *p, *m, *s; + Py_ssize_t psz, msz, ssz; + PyObject *rc = 0; + if (!PyArg_ParseTuple(arg, "s#s#s#:ed25519_verify", + &p, &psz, &m, &msz, &s, &ssz)) + goto end; + if (psz != ED25519_PUBSZ) VALERR("bad public length"); + if (ssz != ED25519_SIGSZ) VALERR("bad signature length"); + rc = getbool(!ed25519_verify((const octet *)p, m, msz, (const octet *)s)); + return (rc); +end: + return (0); +} + /*----- Global stuff ------------------------------------------------------*/ static PyMethodDef methods[] = { @@ -1152,6 +1203,12 @@ static PyMethodDef methods[] = { generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0]) -> R") METH (x25519, "\ x25519(KEY, PUBLIC) -> SHARED") + METH (ed25519_pubkey, "\ +ed25519_pubkey(KEY) -> PUBLIC") + KWMETH(ed25519_sign, "\ +ed25519_sign(KEY, MSG, [PUBLIC]) -> SIG") + METH (ed25519_verify, "\ +ed25519_verify(PUBLIC, MSG, SIG) -> BOOL") #undef METHNAME { 0 } }; -- [mdw]