Hi,
i'd like to access the OpenSSL PRNG, but neither RAND_bytes() nor
RAND_pseudo_bytes() have been implemented in OpenSSL.rand, so here
is a patch which adds them.
Index: src/rand/rand.c
===================================================================
RCS file: /u/cvs/pyopenssl/pyOpenSSL/src/rand/rand.c,v
retrieving revision 1.10
diff -u -U1 -r1.10 rand.c
--- src/rand/rand.c 8 Jul 2002 11:06:01 -0000 1.10
+++ src/rand/rand.c 11 Feb 2003 03:12:11 -0000
@@ -11,2 +11,14 @@
#include <Python.h>
+#include "../util.h"
+
+PyObject *rand_Error;
+
+#ifdef exception_from_error_queue
+# undef exception_from_error_queue
+#endif
+#define exception_from_error_queue() do { \
+ PyObject *errlist = error_queue_to_list(); \
+ PyErr_SetObject(rand_Error, errlist); \
+ Py_DECREF(errlist); \
+} while (0)
@@ -79,2 +91,88 @@
+/*
+ RAND_bytes() is available in all versions of SSLeay and
+ OpenSSL. It has a return value since OpenSSL 0.9.5.
+ RAND_pseudo_bytes() was added in OpenSSL 0.9.5.
+*/
+static char rand_bytes_doc[] = "\n\
+Produce cryptographically strong pseudo-random bytes.\n\
+An error occurs if the PRNG has not been seeded with enough\n\
+randomness to ensure an unpredictable byte sequence.\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ num - How many bytes to produce\n\
+Returns: A string of pseudo-random bytes. Throws a rand.Error\n\
+ exception if there wasn't enough randomness\n\
+";
+
+static PyObject *
+rand_bytes(PyObject *spam, PyObject *args)
+{
+ int num, rc;
+ PyObject *rv;
+ unsigned char *buf;
+
+ if (!PyArg_ParseTuple(args, "i:bytes", &num))
+ return NULL;
+
+ buf = (unsigned char *) PyMem_NEW(unsigned char *, num);
+ if (!buf) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ rc = RAND_bytes(buf, num);
+ if (rc != 1) {
+ exception_from_error_queue();
+ return NULL;
+ }
+ rv = Py_BuildValue("s#", buf, num);
+ PyMem_DEL(buf);
+ return rv;
+}
+
+static char rand_pseudo_bytes_doc[] = "\n\
+Produce pseudo-random bytes.\n\
+Pseudo-random byte sequences generated by pseudo_bytes()\n\
+will be unique if they are of sufficient length, but are not\n\
+necessarily unpredictable. They can be used for non-cryptographic\n\
+purposes and for certain purposes in cryptographic protocols, but\n\
+usually not for key generation etc.\n\
+\n\
+Arguments: spam - Always NULL\n\
+ args - The Python argument tuple, should be:\n\
+ num - How many bytes to produce\n\
+Returns: A string of pseudo-random bytes\n\
+";
+
+static PyObject *
+rand_pseudo_bytes(PyObject *spam, PyObject *args)
+{
+ int num, rc;
+ PyObject *rv;
+ unsigned char *buf;
+
+ if (!PyArg_ParseTuple(args, "i:pseudo_bytes", &num))
+ return NULL;
+
+ buf = (unsigned char *) PyMem_NEW(unsigned char *, num);
+ if (!buf) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ rc = RAND_pseudo_bytes(buf, num);
+ /*
+ RAND_pseudo_bytes() returns 1 if the bytes generated are
+ cryptographically strong, 0 otherwise.
+
+ Maybe this should return a list in order to pass the
+ RAND_pseudo_bytes() return value.
+ */
+ rv = Py_BuildValue("s#", buf, num);
+ PyMem_DEL(buf);
+ return rv;
+}
+
static char rand_status_doc[] = "\n\
@@ -211,2 +309,4 @@
{ "seed", (PyCFunction)rand_seed, METH_VARARGS, rand_seed_doc },
+ { "bytes", (PyCFunction)rand_bytes, METH_VARARGS, rand_bytes_doc },
+ { "pseudo_bytes", (PyCFunction)rand_pseudo_bytes, METH_VARARGS, rand_pseudo_bytes_doc },
{ "status", (PyCFunction)rand_status, METH_VARARGS, rand_status_doc },
@@ -238,2 +338,11 @@
return;
+
+ rand_Error = PyErr_NewException("rand.Error", NULL, NULL);
+ if (rand_Error == NULL)
+ goto error;
+ if (PyModule_AddObject(module, "Error", rand_Error) != 0)
+ goto error;
+
+error:
+ ;
}
--
Toni Andjelkovic
<to...@so...>
|