diff --git a/lib/hash.c b/lib/hash.c
index bdf11507bc..8081b429d5 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -48,6 +48,7 @@ hash_table *construct_hash_table(hash_table *table, size_t size, int use_mpool)
 	  fatal("construct_hash_table called without a size", EC_TEMPFAIL);
 
       table->size  = size;
+      table->seed = rand(); /* might be zero, that's okay */
 
       /* Allocate the table -- different for using memory pools and not */
       if(use_mpool) {
@@ -76,7 +77,7 @@ hash_table *construct_hash_table(hash_table *table, size_t size, int use_mpool)
 
 void *hash_insert(const char *key, void *data, hash_table *table)
 {
-      unsigned val = strhash(key) % table->size;
+      unsigned val = strhash_seeded(table->seed, key) % table->size;
       bucket *ptr, *newptr;
       bucket **prev;
 
@@ -157,9 +158,14 @@ void *hash_insert(const char *key, void *data, hash_table *table)
 
 void *hash_lookup(const char *key, hash_table *table)
 {
-      unsigned val = strhash(key) % table->size;
+      unsigned val;
       bucket *ptr;
 
+      if (!table->size)
+          return NULL;
+
+      val = strhash_seeded(table->seed, key) % table->size;
+
       if (!(table->table)[val])
             return NULL;
 
@@ -182,8 +188,7 @@ void *hash_lookup(const char *key, hash_table *table)
  * since it will leak memory until you get rid of the entire hash table */
 void *hash_del(char *key, hash_table *table)
 {
-      unsigned val = strhash(key) % table->size;
-      void *data;
+      unsigned val = strhash_seeded(table->seed, key) % table->size;
       bucket *ptr, *last = NULL;
 
       if (!(table->table)[val])
@@ -204,15 +209,10 @@ void *hash_del(char *key, hash_table *table)
 	  int cmpresult = strcmp(key, ptr->key);
 	  if (!cmpresult)
 	  {
+              void *data = ptr->data;
 	      if (last != NULL )
 	      {
-		  data = ptr -> data;
 		  last -> next = ptr -> next;
-		  if(!table->pool) {
-		      free(ptr->key);
-		      free(ptr);
-		  }
-		  return data;
 	      }
 	      
 	      /*
@@ -225,15 +225,15 @@ void *hash_del(char *key, hash_table *table)
 	      
 	      else
 	      {
-		  data = ptr->data;
 		  (table->table)[val] = ptr->next;
+              }
 		  if(!table->pool) {
 		      free(ptr->key);
 		      free(ptr);
 		  }
 		  return data;
 	      }
-	  } else if (cmpresult < 0) {
+          if (cmpresult < 0) {
 	      /* its not here! */
 	      return NULL;
 	  }
diff --git a/lib/hash.h b/lib/hash.h
index 77d0dc8a33..c3bc1dc2f5 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -5,9 +5,13 @@
 #define HASH__H
 
 #include <stddef.h>           /* For size_t     */
+#include <stdint.h>
+
 #include "strhash.h"
 #include "mpool.h"
 
+#define HASH_TABLE_INITIALIZER {0, 0, NULL, NULL}
+
 /*
 ** A hash table consists of an array of these buckets.  Each bucket
 ** holds a copy of the key, a pointer to the data associated with the
@@ -32,6 +36,7 @@ typedef struct bucket {
 
 typedef struct hash_table {
     size_t size;
+    uint32_t seed;
     bucket **table;
     struct mpool *pool;
 } hash_table;
diff --git a/lib/strhash.c b/lib/strhash.c
index 3457abab27..8f68d13867 100644
--- a/lib/strhash.c
+++ b/lib/strhash.c
@@ -57,17 +57,32 @@
 #include "assert.h"
 #include "strhash.h"
 
-unsigned strhash(const char *string)
+#include "lib/strhash.h"
+
+/* The well-known djb2 algorithm (e.g. http://www.cse.yorku.ca/~oz/hash.html),
+ * with the addition of an optional seed to limit predictability.
+ *
+ * XXX return type 'unsigned' for back-compat to previous version, but
+ * XXX ought to be 'uint32_t'
+ */
+unsigned strhash_seeded_djb2(uint32_t seed, const char *string)
 {
-      unsigned ret_val = 0;
-      int i;
+    const unsigned char *ustr = (const unsigned char *) string;
+    unsigned hash = 5381;
+    int c;
 
-      while (*string)
-      {
-            i = (int) *string;
-            ret_val ^= i;
-            ret_val <<= 1;
-            string ++;
-      }
-      return ret_val;
+    if (seed) {
+        /* treat the bytes of the seed as a prefix to the string */
+        unsigned i;
+        for (i = 0; i < sizeof seed; i++) {
+            c = seed & 0xff;
+            hash = ((hash << 5) + hash) ^ c;
+            seed >>= 8;
+        }
+    }
+
+    while ((c = *ustr++))
+        hash = ((hash << 5) + hash) ^ c;
+
+    return hash;
 }
diff --git a/lib/strhash.h b/lib/strhash.h
index 3ecb432a34..dc6f6b759f 100644
--- a/lib/strhash.h
+++ b/lib/strhash.h
@@ -43,6 +43,7 @@
  */
 
 #ifndef _STRHASH_H_
+#include <stdint.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -57,6 +58,9 @@
 #include <syslog.h>
 #include <errno.h>
 
-unsigned strhash(const char *string);
+unsigned strhash_seeded_djb2(uint32_t seed, const char *string);
+
+#define strhash(in)             strhash_seeded_djb2((0),  (in))
+#define strhash_seeded(sd, in)  strhash_seeded_djb2((sd), (in))
 
 #endif /* _STRHASH_H_ */
