1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
/* Use this file as a template to start implementing a module that
also declares object types. All occurrences of 'FOOOBJ' should be changed
to something reasonable for your objects. After that, all other
occurrences of 'ed25519' should be changed to something reasonable for your
module. If your module is named foo your sourcefile should be named
foomodule.c.
You will probably want to delete all references to 'x_attr' and add
your own types of attributes instead. Maybe you want to name your
local variables other than 'self'. If your object type is needed in
other files, you'll have to create a file "foobarobject.h"; see
intobject.h for an example. */
// this makes "s#" use Py_ssize_t instead of int
#define PY_SSIZE_T_CLEAN 1
#include "Python.h"
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
typedef int Py_ssize_t;
#define PY_SSIZE_T_MAX INT_MAX
#define PY_SSIZE_T_MIN INT_MIN
#endif
static PyObject *BadSignatureError,
*SECRETKEYBYTESObject, *PUBLICKEYBYTESObject, *SIGNATUREBYTESObject;
/* --------------------------------------------------------------------- */
#include "crypto_sign.h"
PyDoc_STRVAR(ed25519_publickey_doc,
"publickey(signkey_seed)\n\
\n\
Accepts a 32-byte seed. Return a tuple of (verfkey, signkey), with the\n\
64-byte private signing key and the corresponding 32-byte public\n\
verfiying key.");
#include <stdio.h>
static PyObject *
ed25519_publickey(PyObject *self, PyObject *args)
{
unsigned char verfkey[PUBLICKEYBYTES];
unsigned char signkey[SECRETKEYBYTES];
unsigned char *seed;
Py_ssize_t seed_len;
if (!PyArg_ParseTuple(args, "s#", &seed, &seed_len))
return NULL;
crypto_sign_publickey(verfkey, signkey, seed);
return Py_BuildValue("(s#s#)",
verfkey, PUBLICKEYBYTES,
signkey, SECRETKEYBYTES);
}
PyDoc_STRVAR(ed25519_sign_doc,
"sign(message, signing_key)\n\
\n\
Return the concatenation of three parts: the 32-byte R signature value,\n\
the original message, and the 32-byte S signature value.");
static PyObject *
ed25519_sign(PyObject *self, PyObject *args)
{
const unsigned char *msg; Py_ssize_t msg_len;
const unsigned char *signkey; Py_ssize_t signkey_len;
unsigned char *sig_and_msg; unsigned long long sig_and_msg_len1;
Py_ssize_t sig_and_msg_len2;
PyObject *ret;
// NOTE: using s# copies the message. It'd be nicer to use it in-place.
// Consider s* and using a Py_buffer. Don't forget PyBuffer_Release.
// Py_buffer is available in py2.6 and later.
//// on the other hand, the funky NaCl API means we're already doing 3
//// copies anyway, so a 4th isn't a big deal.
if (!PyArg_ParseTuple(args, "s#s#:signature",
&msg, &msg_len,
&signkey, &signkey_len))
return NULL;
if (signkey_len != SECRETKEYBYTES) { // 64
PyErr_SetString(PyExc_TypeError,
"Private signing keys are 64 byte strings");
return NULL;
}
sig_and_msg = PyMem_Malloc(msg_len + SIGNATUREBYTES);
if (!sig_and_msg)
return PyErr_NoMemory();
crypto_sign(sig_and_msg, &sig_and_msg_len1, msg, msg_len, signkey);
sig_and_msg_len2 = sig_and_msg_len1;
ret = Py_BuildValue("s#", sig_and_msg, sig_and_msg_len2);
PyMem_Free(sig_and_msg);
return ret;
}
PyDoc_STRVAR(ed25519_open_doc,
"open(message+signature, verifying_key)\n\
\n\
Check the signature for validity. Returns the message if valid, raises\n\
ed25519.error if not.");
static PyObject *
ed25519_open(PyObject *self, PyObject *args)
{
const unsigned char *sig_and_msg; Py_ssize_t sig_and_msg_len;
const unsigned char *verfkey; Py_ssize_t verfkey_len;
unsigned char *msg; unsigned long long msg_len1;
Py_ssize_t msg_len2;
PyObject *ret;
int result;
if (!PyArg_ParseTuple(args, "s#s#:checkvalid",
&sig_and_msg, &sig_and_msg_len,
&verfkey, &verfkey_len ))
return NULL;
if (sig_and_msg_len < SIGNATUREBYTES) { // 64
PyErr_SetString(PyExc_TypeError,
"signature-and-message must be at least 64 bytes long");
return NULL;
}
if (verfkey_len != PUBLICKEYBYTES) { // 32
PyErr_SetString(PyExc_TypeError,
"Public verifying keys are 32 byte strings");
return NULL;
}
// crypto_sign_open() uses the output buffer as a scratchpad, and thus
// requires an extra 64 bytes beyond the expected message. So allocate
// sig_and_msg_len, not sig_and_msg_len-SIGNATUREBYTES
msg = PyMem_Malloc(sig_and_msg_len);
if (!msg)
return PyErr_NoMemory();
result = crypto_sign_open(msg, &msg_len1, sig_and_msg, sig_and_msg_len,
verfkey);
// be faithful to the NaCl interface and return the message, even though
// it's a waste.
if (result == 0) {
// good signature
msg_len2 = msg_len1;
ret = Py_BuildValue("s#", msg, msg_len2);
PyMem_Free(msg);
return ret;
}
// bad signature. We do throw an exception when the signature is bad, so
// it can't be silently ignored
PyMem_Free(msg);
PyErr_SetString(BadSignatureError, "Bad Signature");
return NULL;
}
/* List of functions defined in the module */
static PyMethodDef ed25519_methods[] = {
{"publickey", ed25519_publickey, METH_VARARGS, ed25519_publickey_doc},
{"sign", ed25519_sign, METH_VARARGS, ed25519_sign_doc},
{"open", ed25519_open, METH_VARARGS, ed25519_open_doc},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(module_doc,
"Low-level Ed25519 signature/verification functions.");
/* Initialization function for the module (*must* be called init_ed25519) */
PyMODINIT_FUNC
init_ed25519(void)
{
PyObject *m;
/* Create the module and add the functions */
m = Py_InitModule3("_ed25519", ed25519_methods, module_doc);
if (m == NULL)
return;
/* Add some symbolic constants to the module */
if (BadSignatureError == NULL) {
BadSignatureError = PyErr_NewException("ed25519.BadSignatureError",
NULL, NULL);
if (BadSignatureError == NULL)
return;
}
if (SECRETKEYBYTESObject == NULL) {
SECRETKEYBYTESObject = PyInt_FromLong(SECRETKEYBYTES);
if (SECRETKEYBYTESObject == NULL)
return;
}
if (PUBLICKEYBYTESObject == NULL) {
PUBLICKEYBYTESObject = PyInt_FromLong(PUBLICKEYBYTES);
if (PUBLICKEYBYTESObject == NULL)
return;
}
if (SIGNATUREBYTESObject == NULL) {
SIGNATUREBYTESObject = PyInt_FromLong(SIGNATUREBYTES);
if (SIGNATUREBYTESObject == NULL)
return;
}
Py_INCREF(BadSignatureError);
PyModule_AddObject(m, "BadSignatureError", BadSignatureError);
PyModule_AddObject(m, "SECRETKEYBYTES", SECRETKEYBYTESObject);
PyModule_AddObject(m, "PUBLICKEYBYTES", PUBLICKEYBYTESObject);
PyModule_AddObject(m, "SIGNATUREKEYBYTES", SIGNATUREBYTESObject);
}
|