X509Name.hash
diff --git a/src/crypto/x509name.c b/src/crypto/x509name.c
index b81b912..93a440e 100644
--- a/src/crypto/x509name.c
+++ b/src/crypto/x509name.c
@@ -13,6 +13,8 @@
#define crypto_MODULE
#include "crypto.h"
+static PyMethodDef crypto_X509Name_methods[];
+
/*
* Constructor for X509Name, never called by Python code directly
*
@@ -129,8 +131,7 @@
if ((nid = OBJ_txt2nid(name)) == NID_undef)
{
- PyErr_SetString(PyExc_AttributeError, "No such attribute");
- return NULL;
+ return Py_FindMethod(crypto_X509Name_methods, (PyObject *)self, name);
}
len = get_name_by_nid(self->x509_name, nid, &utf8string);
@@ -222,6 +223,33 @@
}
}
+static char crypto_X509Name_hash_doc[] = "\n\
+Return the has value of this name\n\
+\n\
+Arguments: self - The X509 object\n\
+ args - The Python argument tuple, should be empty\n\
+Returns: None\n\
+";
+
+/*
+ * First four bytes of the MD5 digest of the DER form of an X509Name.
+ *
+ * Arguments: self - The X509Name object
+ * Returns: An integer giving the hash.
+ */
+static PyObject *
+crypto_X509Name_hash(crypto_X509NameObj *self, PyObject* args)
+{
+ unsigned long hash;
+
+ if (!PyArg_ParseTuple(args, ":hash")) {
+ return NULL;
+ }
+ hash = X509_NAME_hash(self->x509_name);
+ return PyInt_FromLong(hash);
+}
+
+
/*
* Call the visitproc on all contained objects.
*
@@ -274,6 +302,20 @@
PyObject_GC_Del(self);
}
+/*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
+ * for convenience
+ */
+#define ADD_METHOD(name) \
+ { #name, (PyCFunction)crypto_X509Name_##name, METH_VARARGS, crypto_X509Name_##name##_doc }
+static PyMethodDef crypto_X509Name_methods[] =
+{
+ ADD_METHOD(hash),
+ { NULL, NULL }
+};
+#undef ADD_METHOD
+
PyTypeObject crypto_X509Name_Type = {
PyObject_HEAD_INIT(NULL)
0,
@@ -295,13 +337,12 @@
NULL, /* getattro */
NULL, /* setattro */
NULL, /* as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- NULL, /* doc */
- (traverseproc)crypto_X509Name_traverse,
- (inquiry)crypto_X509Name_clear,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ NULL, /* tp_doc */
+ (traverseproc)crypto_X509Name_traverse, /* tp_traverse */
+ (inquiry)crypto_X509Name_clear, /* tp_clear */
};
-
/*
* Initialize the X509Name part of the crypto module
*
diff --git a/test/test_crypto.py b/test/test_crypto.py
index 4c66c62..e853094 100644
--- a/test/test_crypto.py
+++ b/test/test_crypto.py
@@ -265,6 +265,19 @@
+ def test_hash(self):
+ """
+ L{X509Name.hash} returns an integer hash based on the value of the
+ name.
+ """
+ a = self._x509name(CN="foo")
+ b = self._x509name(CN="foo")
+ self.assertEqual(a.hash(), b.hash())
+ a.CN = "bar"
+ self.assertNotEqual(a.hash(), b.hash())
+
+
+
class _PKeyInteractionTestsMixin:
"""
Tests which involve another thing and a PKey.