diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index f3694d096492d932c23e16fb49bd00dcfd8beb82..59a9eb23ef5ab1b0276abd4bb1062c43341a21a4 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -250,7 +250,10 @@ struct OPENDHT_PUBLIC Certificate {
      * ordered from subject to issuer
      */
     Certificate(const Blob& crt);
-    Certificate(const uint8_t* dat, size_t dat_size) {
+    Certificate(const std::string& pem) : cert(nullptr) {
+        unpack((const uint8_t*)pem.data(), pem.size());
+    }
+    Certificate(const uint8_t* dat, size_t dat_size) : cert(nullptr) {
         unpack(dat, dat_size);
     }
 
diff --git a/python/opendht.pyx b/python/opendht.pyx
index 58ab1205efd808bb408600ce806733bcecdb9d18..946952822dd8d20cf6f4e3c88db560bf6dab63f9 100644
--- a/python/opendht.pyx
+++ b/python/opendht.pyx
@@ -241,6 +241,24 @@ cdef class NodeSet(object):
     def __iter__(self):
         return NodeSetIter(self)
 
+cdef class PrivateKey(_WithID):
+    cdef cpp.PrivateKey _key
+    def getId(self):
+        h = InfoHash()
+        h._infohash = self._key.getPublicKey().getId()
+        return h
+    def getPublicKey(self):
+        pk = PublicKey()
+        pk._key = self._key.getPublicKey()
+        return pk
+    def __str__(self):
+        return self.getId().toString().decode()
+    @staticmethod
+    def generate():
+        k = PrivateKey()
+        k._key = cpp.PrivateKey.generate()
+        return k
+
 cdef class PublicKey(_WithID):
     cdef cpp.PublicKey _key
     def getId(self):
@@ -250,10 +268,23 @@ cdef class PublicKey(_WithID):
 
 cdef class Certificate(_WithID):
     cdef shared_ptr[cpp.Certificate] _cert
+    def __init__(self, bytes dat = None):
+        if dat:
+            self._cert = cpp.make_shared[cpp.Certificate](<cpp.string>dat)
     def getId(self):
         h = InfoHash()
-        h._infohash = self._cert.get().getId()
+        if self._cert:
+            h._infohash = self._cert.get().getId()
         return h
+    def toString(self):
+        return self._cert.get().toString().decode()
+    @staticmethod
+    def generate(PrivateKey k, str name, Identity i = Identity(), bool is_ca = False):
+        c = Certificate()
+        c._cert = cpp.make_shared[cpp.Certificate](cpp.Certificate.generate(k._key, name.encode(), i._id, is_ca))
+        return c
+    def __bytes__(self):
+        return self._cert.get().toString() if self._cert else b''
 
 cdef class ListenToken(object):
     cdef cpp.InfoHash _h
@@ -297,7 +328,8 @@ cdef class DhtRunner(_WithID):
         self.thisptr.reset(new cpp.DhtRunner())
     def getId(self):
         h = InfoHash()
-        h._infohash = self.thisptr.get().getId()
+        if self.thisptr:
+            h._infohash = self.thisptr.get().getId()
         return h
     def getNodeId(self):
         return self.thisptr.get().getNodeId().toString()
diff --git a/python/opendht_cpp.pxd b/python/opendht_cpp.pxd
index 5f080de6ce4ec0b321eaa12bf0873e1294c0fdd1..0e5bc73252c73a259b6521a6e987cd50a080601c 100644
--- a/python/opendht_cpp.pxd
+++ b/python/opendht_cpp.pxd
@@ -32,7 +32,9 @@ cdef extern from "<memory>" namespace "std" nogil:
         shared_ptr(T*) except +
         T* get()
         T operator*()
+        bool operator bool() const
         void reset(T*)
+    shared_ptr[T] make_shared[T](...) except +
 
 cdef extern from "<functional>" namespace "std" nogil:
     cdef cppclass hash[T]:
@@ -82,6 +84,8 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto":
     cdef cppclass PrivateKey:
         PrivateKey()
         PublicKey getPublicKey() const
+        @staticmethod
+        PrivateKey generate()
 
     cdef cppclass PublicKey:
         PublicKey()
@@ -89,7 +93,11 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto":
 
     cdef cppclass Certificate:
         Certificate()
+        Certificate(string pem)
         InfoHash getId() const
+        string toString() const
+        @staticmethod
+        Certificate generate(PrivateKey key, string name, Identity ca, bool is_ca)
 
 cdef extern from "opendht/value.h" namespace "dht":
     cdef cppclass Value: