diff --git a/CMakeLists.txt b/CMakeLists.txt
index 764db875d661e0d85c6df2a81c38c9b769948a93..2d0d17bad32def0837666bcd6f6ff90a27f43c2b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,7 @@ if (OPENDHT_TOOLS)
 endif ()
 
 list (APPEND opendht_SOURCES
+	src/utils.cpp
 	src/infohash.cpp
 	src/crypto.cpp
 	src/default_types.cpp
@@ -35,6 +36,7 @@ list (APPEND opendht_SOURCES
 )
 
 list (APPEND opendht_HEADERS
+	include/opendht/utils.h
 	include/opendht/rng.h
 	include/opendht/crypto.h
 	include/opendht/infohash.h
diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index e1daf2560d978a6b091b38cb875e7af487d82df0..16990f9ce7e3a95961906833cdde6955af5cf072 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -31,6 +31,7 @@
 #pragma once
 
 #include "infohash.h"
+#include "utils.h"
 
 extern "C" {
 #include <gnutls/gnutls.h>
@@ -41,8 +42,6 @@ extern "C" {
 #include <vector>
 #include <memory>
 
-typedef std::vector<uint8_t> Blob;
-
 namespace dht {
 namespace crypto {
 
diff --git a/include/opendht/infohash.h b/include/opendht/infohash.h
index 953d51f89e018c89edf5f6dd1fb9fb843135dbc7..01a2c306dbad8fc9b8556f17681f6bf9cb61808f 100644
--- a/include/opendht/infohash.h
+++ b/include/opendht/infohash.h
@@ -45,13 +45,6 @@
 
 namespace dht {
 
-class DhtException : public std::runtime_error {
-    public:
-        DhtException(const std::string &str = "") :
-            std::runtime_error("DhtException occured: " + str) {}
-};
-
-
 /**
  * Represents an InfoHash.
  * An InfoHash is a byte array of HASH_LEN bytes.
diff --git a/include/opendht/utils.h b/include/opendht/utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6ce5a993857b159b5dc8a83a9c4f4bd41918813
--- /dev/null
+++ b/include/opendht/utils.h
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (C) 2014-2015 Savoir-faire Linux Inc.
+ *  Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#pragma once
+
+#include <msgpack.hpp>
+
+#include <chrono>
+#include <random>
+#include <functional>
+
+#include <cstdarg>
+
+namespace dht {
+
+class DhtException : public std::runtime_error {
+    public:
+        DhtException(const std::string &str = "") :
+            std::runtime_error("DhtException occured: " + str) {}
+};
+
+
+// Time related definitions and utility functions
+
+using clock = std::chrono::steady_clock;
+using time_point = clock::time_point;
+using duration = clock::duration;
+
+time_point from_time_t(std::time_t t);
+std::time_t to_time_t(time_point t);
+
+static /*constexpr*/ const time_point TIME_INVALID = {time_point::min()};
+static /*constexpr*/ const time_point TIME_MAX {time_point::max()};
+
+template <typename Duration = duration>
+class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep> {
+    using Base = std::uniform_int_distribution<typename Duration::rep>;
+    using param_type = typename Base::param_type;
+public:
+    uniform_duration_distribution(Duration min, Duration max) : Base(min.count(), max.count()) {}
+    template <class Generator>
+    Duration operator()(Generator && g) {
+        return Duration(Base::operator()(g));
+    }
+    template< class Generator >
+    Duration operator()( Generator && g, const param_type& params ) {
+        return Duration(Base::operator()(g, params));
+    }
+};
+
+// Logging related utility functions
+
+/**
+ * Dummy function used to disable logging
+ */
+inline void NOLOG(char const*, va_list) {}
+
+/**
+ * Wrapper for logging methods
+ */
+struct LogMethod {
+    LogMethod() = default;
+
+    template<typename T>
+    LogMethod(T&& t) : func(std::forward<T>(t)) {}
+
+    void operator()(char const* format, ...) const {
+        va_list args;
+        va_start(args, format);
+        func(format, args);
+        va_end(args);
+    }
+
+    void logPrintable(const uint8_t *buf, size_t buflen) const {
+        std::string buf_clean(buflen, '\0');
+        for (size_t i=0; i<buflen; i++)
+            buf_clean[i] = buf[i] >= 32 && buf[i] <= 126 ? buf[i] : '.';
+        (*this)("%s", buf_clean.c_str());
+    }
+private:
+    std::function<void(char const*, va_list)> func;
+};
+
+// Serialization related definitions and utility functions
+
+typedef std::vector<uint8_t> Blob;
+
+/**
+ * Provides backward compatibility with msgpack 1.0
+ */
+Blob unpackBlob(msgpack::object& o);
+
+template <typename Type>
+Blob
+packMsg(const Type& t) {
+    msgpack::sbuffer buffer;
+    msgpack::packer<msgpack::sbuffer> pk(&buffer);
+    pk.pack(t);
+    return {buffer.data(), buffer.data()+buffer.size()};
+}
+
+template <typename Type>
+Type
+unpackMsg(Blob b) {
+    msgpack::unpacked msg_res = msgpack::unpack((const char*)b.data(), b.size());
+    return msg_res.get().as<Type>();
+}
+
+msgpack::unpacked unpackMsg(Blob b);
+
+}
diff --git a/include/opendht/value.h b/include/opendht/value.h
index c2f08513bae9e4ae6864557b5f4370391b9d3cb3..b79f8b349792bc615b536ab429ec30fd256b6e5f 100644
--- a/include/opendht/value.h
+++ b/include/opendht/value.h
@@ -32,6 +32,8 @@
 
 #include "infohash.h"
 #include "crypto.h"
+#include "utils.h"
+
 #include <msgpack.hpp>
 
 #ifndef _WIN32
@@ -56,68 +58,8 @@ typedef uint16_t in_port_t;
 #include <memory>
 #include <chrono>
 
-#include <cstdarg>
-
 namespace dht {
 
-using clock = std::chrono::steady_clock;
-using time_point = clock::time_point;
-using duration = clock::duration;
-
-time_point from_time_t(std::time_t t);
-std::time_t to_time_t(time_point t);
-
-static /*constexpr*/ const time_point TIME_INVALID = {time_point::min()};
-static /*constexpr*/ const time_point TIME_MAX {time_point::max()};
-
-template <typename Duration = duration>
-class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep> {
-    using Base = std::uniform_int_distribution<typename Duration::rep>;
-    using param_type = typename Base::param_type;
-public:
-    uniform_duration_distribution(Duration min, Duration max) : Base(min.count(), max.count()) {}
-    template <class Generator>
-    Duration operator()(Generator && g) {
-        return Duration(Base::operator()(g));
-    }
-    template< class Generator >
-    Duration operator()( Generator && g, const param_type& params ) {
-        return Duration(Base::operator()(g, params));
-    }
-};
-
-/**
- * Wrapper for logging methods
- */
-struct LogMethod {
-    LogMethod() = default;
-
-    template<typename T>
-    LogMethod( T&& t) : func(std::forward<T>(t)) {}
-
-    void operator()(char const* format, ...) const {
-        va_list args;
-        va_start(args, format);
-        func(format, args);
-        va_end(args);
-    }
-
-    void logPrintable(const uint8_t *buf, size_t buflen) const {
-        std::string buf_clean(buflen, '\0');
-        for (size_t i=0; i<buflen; i++)
-            buf_clean[i] = buf[i] >= 32 && buf[i] <= 126 ? buf[i] : '.';
-        (*this)("%s", buf_clean.c_str());
-    }
-private:
-    std::function<void(char const*, va_list)> func;
-};
-
-/**
- * Dummy function used to disable logging
- */
-inline void NOLOG(char const*, va_list) {}
-
-
 struct Value;
 
 typedef std::function<bool(InfoHash, std::shared_ptr<Value>&, InfoHash, const sockaddr*, socklen_t)> StorePolicy;
@@ -156,24 +98,6 @@ struct ValueType {
     EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
 };
 
-template <typename Type>
-Blob
-packMsg(const Type& t) {
-    msgpack::sbuffer buffer;
-    msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack(t);
-    return {buffer.data(), buffer.data()+buffer.size()};
-}
-
-template <typename Type>
-Type
-unpackMsg(Blob b) {
-    msgpack::unpacked msg_res = msgpack::unpack((const char*)b.data(), b.size());
-    return msg_res.get().as<Type>();
-}
-
-msgpack::unpacked unpackMsg(Blob b);
-
 /**
  * A "value" is data potentially stored on the Dht, with some metadata.
  *
@@ -508,9 +432,4 @@ unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
     return ret;
 }
 
-/**
- * Provides backward compatibility with msgpack 1.0
- */
-Blob unpackBlob(msgpack::object& o);
-
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 727c4b50ba33405e98e92c2954d16e86f6fd5dab..d066626914410fdaa324f0c3819e5cea823cf205 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ libopendht_la_LDFLAGS = @LDFLAGS@ @GNUTLS_LIBS@ @nettle_LIBS@
 
 libopendht_la_SOURCES = \
         dht.cpp \
+        utils.cpp \
         infohash.cpp \
         value.cpp \
         crypto.cpp \
@@ -20,6 +21,7 @@ endif
 nobase_include_HEADERS = \
         ../include/opendht.h \
         ../include/opendht/dht.h \
+        ../include/opendht/utils.h \
         ../include/opendht/infohash.h \
         ../include/opendht/value.h \
         ../include/opendht/crypto.h \
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 4735fd3514851041921f864e858ca448ff630361..ca836e8c030598b9108210702e708d1309150f26 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -30,7 +30,6 @@
 
 #include "crypto.h"
 #include "rng.h"
-#include "value.h"
 
 extern "C" {
 #include <gnutls/gnutls.h>
diff --git a/src/utils.cpp b/src/utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..37561e28329c3a4f315ce4927da077b642f1c8ae
--- /dev/null
+++ b/src/utils.cpp
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (C) 2014-2015 Savoir-faire Linux Inc.
+ *  Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#include "utils.h"
+
+namespace dht {
+
+time_point from_time_t(std::time_t t) {
+    return clock::now() + (std::chrono::system_clock::from_time_t(t) - std::chrono::system_clock::now());
+}
+
+std::time_t to_time_t(time_point t) {
+    return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + 
+            (t - clock::now()));
+}
+
+Blob
+unpackBlob(msgpack::object& o) {
+    switch (o.type) {
+    case msgpack::type::BIN:
+        return {o.via.bin.ptr, o.via.bin.ptr+o.via.bin.size};
+    case msgpack::type::STR:
+        return {o.via.str.ptr, o.via.str.ptr+o.via.str.size};
+    case msgpack::type::ARRAY: {
+        Blob ret(o.via.array.size);
+        std::transform(o.via.array.ptr, o.via.array.ptr+o.via.array.size, ret.begin(), [](const msgpack::object& b) {
+            return b.as<uint8_t>();
+        });
+        return ret;
+    }
+    default:
+        throw msgpack::type_error();
+    }
+}
+
+msgpack::unpacked
+unpackMsg(Blob b) {
+    return msgpack::unpack((const char*)b.data(), b.size());
+}
+
+}
diff --git a/src/value.cpp b/src/value.cpp
index 5d22f259b57c462be73949af17dfe3f0619f7e81..16b6380156153a020d6296978e3604e9188ec743 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -35,16 +35,6 @@
 
 namespace dht {
 
-time_point from_time_t(std::time_t t) {
-    return clock::now() + (std::chrono::system_clock::from_time_t(t) - std::chrono::system_clock::now());
-}
-
-std::time_t to_time_t(time_point t) {
-    return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + 
-            (t - clock::now()));
-}
-
-
 std::ostream& operator<< (std::ostream& s, const Value& v)
 {
     s << "Value[id:" << std::hex << v.id << std::dec << " ";
@@ -169,23 +159,4 @@ Value::msgpack_unpack_body(const msgpack::object& o)
     }
 }
 
-Blob
-unpackBlob(msgpack::object& o) {
-    switch (o.type) {
-    case msgpack::type::BIN:
-        return {o.via.bin.ptr, o.via.bin.ptr+o.via.bin.size};
-    case msgpack::type::STR:
-        return {o.via.str.ptr, o.via.str.ptr+o.via.str.size};
-    case msgpack::type::ARRAY: {
-        Blob ret(o.via.array.size);
-        std::transform(o.via.array.ptr, o.via.array.ptr+o.via.array.size, ret.begin(), [](const msgpack::object& b) {
-            return b.as<uint8_t>();
-        });
-        return ret;
-    }
-    default:
-        throw msgpack::type_error();
-    }
-}
-
 }