#42 assigned enhancement

python hkdf

Reported by: dragonxue Owned by: zooko
Priority: major Milestone: 0.7.0
Version: 0.5.19 Keywords: hkdf
Cc: zooko@…, lloyd@… Launchpad Bug:

Description

python hkdf which will be used as key derivation function

Attachments (7)

hkdf.py (1.7 KB) - added by dragonxue at 2010-07-03T01:53:07Z.
test_hkdf.py (2.0 KB) - added by dragonxue at 2010-07-03T01:53:27Z.
hkdf_bench.py (1.9 KB) - added by dragonxue at 2010-07-03T01:53:49Z.
HKDFMsg.txt (2.7 KB) - added by dragonxue at 2010-07-03T02:52:57Z.
part1.dpatch (1.4 KB) - added by dragonxue at 2010-07-03T02:53:42Z.
hkdf.dpatch (64.6 KB) - added by dragonxue at 2010-07-04T04:50:09Z.
test_hkdf_new.py (2.1 KB) - added by xueyucoder at 2011-12-22T15:59:58Z.
add comment about where the test vectors come from

Download all attachments as: .zip

Change History (14)

Changed at 2010-07-03T01:53:07Z by dragonxue

Changed at 2010-07-03T01:53:27Z by dragonxue

Changed at 2010-07-03T01:53:49Z by dragonxue

Changed at 2010-07-03T02:52:57Z by dragonxue

Changed at 2010-07-03T02:53:42Z by dragonxue

Changed at 2010-07-04T04:50:09Z by dragonxue

comment:1 Changed at 2011-12-09T22:49:49Z by zooko

  • Milestone set to 0.6.0

Changed at 2011-12-22T15:59:58Z by xueyucoder

add comment about where the test vectors come from

comment:2 Changed at 2012-01-09T18:09:27Z by zooko

It looks like to me that Xue Yu attached the complete text as simple files in addition to the same text in the darcs patches. So, if you don't want to use darcs to apply them, then just inspect the darcs patches visually and compare them to the .py files, please, to make sure you're not missing anything.

comment:3 Changed at 2012-01-09T18:32:58Z by zooko

The new Python hmac needs the hash function to have a DIGEST_SIZE attribute.

diff -rN -u old-darcsworld-hmac/pycryptopp/hash/sha256module.cpp new-darcsworld-hmac/pycryptopp/hash/sha256module.cpp
--- old-darcsworld-hmac/pycryptopp/hash/sha256module.cpp	2012-01-09 11:32:19.570933575 -0700
+++ new-darcsworld-hmac/pycryptopp/hash/sha256module.cpp	2012-01-09 11:32:19.612933575 -0700
@@ -28,6 +28,8 @@
 typedef struct {
     PyObject_HEAD
 
+	Py_ssize_t digest_size;
+
     /* internal */
     CryptoPP::SHA256* h;
     PyStringObject* digest;
@@ -59,7 +61,7 @@
 SHA256_digest(SHA256* self, PyObject* dummy) {
     if (!self->digest) {
         assert (self->h);
-        self->digest = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, self->h->DigestSize()));
+        self->digest = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, self->digest_size));
         if (!self->digest)
             return NULL;
         self->h->Final(reinterpret_cast<byte*>(PyString_AS_STRING(self->digest)));
@@ -100,6 +102,12 @@
     {NULL},
 };
 
+static PyMemberDef SHA256_members[] = {
+    {"number", T_PYSSIZET, offsetof(SHA256, digest_Size), READONLY,
+     "digest size"},
+    {NULL}  /* Sentinel */
+};
+
 static PyObject *
 SHA256_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) {
     SHA256* self = reinterpret_cast<SHA256*>(type->tp_alloc(type, 0));
@@ -108,6 +116,7 @@
     self->h = new CryptoPP::SHA256();
     if (!self->h)
         return PyErr_NoMemory();
+	self->digest_size = self->h->DigestSize();
     self->digest = NULL;
     return reinterpret_cast<PyObject*>(self);
 }
@@ -162,7 +171,7 @@
     0,		               /* tp_iter */
     0,		               /* tp_iternext */
     SHA256_methods,      /* tp_methods */
-    0,                         /* tp_members */
+    SHA256_members,                         /* tp_members */
     0,                         /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
diff -rN -u old-darcsworld-hmac/pycryptopp/test/test_sha256.py new-darcsworld-hmac/pycryptopp/test/test_sha256.py
--- old-darcsworld-hmac/pycryptopp/test/test_sha256.py	2012-01-09 11:32:19.574933575 -0700
+++ new-darcsworld-hmac/pycryptopp/test/test_sha256.py	2012-01-09 11:32:19.613933575 -0700
@@ -35,6 +35,11 @@
 h_5fd4 = a2b_hex("7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788")
 
 class SHA256(unittest.TestCase):
+    def test_digest_size(self):
+        self.failUnless(hasattr(sha256.SHA256, 'digest_size'))
+        self.failUnless(isinstance(sha256.SHA256.digest_size, int))
+        self.failUnlessEqual(sha256.SHA256.digest_size, 32)
+
     def test_digest(self):
         empty_digest = sha256.SHA256().digest()
         self.failUnless(isinstance(empty_digest, str))

comment:4 Changed at 2012-02-06T01:27:44Z by warner

I've got a cleaned up branch at https://github.com/warner/pycryptopp/tree/42-hkdf . It incorporates all these patches (including the .digest_size one), plus some necessary fixes. The result almost works: the (only?) remaining problem is that pycryptopp's SHA256 objects do not have a .copy() method (unlike hashlib.SHA256), and the stdlib HMAC code depends upon one. Not sure how to add this, it might need some C++ object-copying that's beyond my current comfort level.

comment:5 Changed at 2012-02-06T23:08:53Z by zooko

  • Owner changed from xue yu to zooko
  • Status changed from new to assigned

I'll have a go at that. Thanks!

comment:6 Changed at 2012-03-11T01:04:04Z by zooko

It looks like Crypto++'s sha256 is an IteratedHashWithStaticTransform, which is a Clonable, and so the way to implement the .copy() method is probably to invoke .Clone() on the Crypto++ sha256 object.

comment:7 Changed at 2012-03-11T01:04:47Z by zooko

  • Milestone changed from 0.6.0 to 0.7.0

We're going to go ahead and release pycryptopp v0.6.0 without this feature and then finish this feature for the next release.

Note: See TracTickets for help on using tickets.