diff --git a/c/opendht.cpp b/c/opendht.cpp
index 74a77dcf4b331cbc4286dd0482f823636c291782..16c59fd4e8cff4b70ac8bc140e69fc81a655ee79 100644
--- a/c/opendht.cpp
+++ b/c/opendht.cpp
@@ -16,6 +16,11 @@ void dht_infohash_random(dht_infohash* h)
     *reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::getRandom();
 }
 
+const char* dht_pkid_print(const dht_pkid* h)
+{
+    return reinterpret_cast<const dht::PkId*>(h)->to_c_str();
+}
+
 // dht::Blob
 void dht_blob_delete(dht_blob* data)
 {
@@ -26,7 +31,7 @@ dht_data_view dht_blob_get_data(const dht_blob* data)
 {
     dht_data_view view;
     view.data = reinterpret_cast<const dht::Blob*>(data)->data();
-    view.length = reinterpret_cast<const dht::Blob*>(data)->size();
+    view.size = reinterpret_cast<const dht::Blob*>(data)->size();
     return view;
 }
 
@@ -35,7 +40,7 @@ dht_data_view dht_value_get_data(const dht_value* data)
 {
     dht_data_view view;
     view.data = reinterpret_cast<const dht::Value*>(data)->data.data();
-    view.length = reinterpret_cast<const dht::Value*>(data)->data.size();
+    view.size = reinterpret_cast<const dht::Value*>(data)->data.size();
     return view;
 }
 
@@ -86,6 +91,23 @@ dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_
     return (dht_blob*)rdata;
 }
 
+dht_privatekey* dht_privatekey_generate(unsigned key_length_bits)
+{
+    if (key_length_bits == 0)
+        key_length_bits = 4096;
+    return reinterpret_cast<dht_privatekey*>(new dht::crypto::PrivateKey(dht::crypto::PrivateKey::generate(key_length_bits)));
+}
+
+dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password)
+{
+    return reinterpret_cast<dht_privatekey*>(new dht::crypto::PrivateKey(dat, dat_size, password));
+}
+
+dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* key)
+{
+    return reinterpret_cast<dht_publickey*>(new dht::crypto::PublicKey(reinterpret_cast<const dht::crypto::PrivateKey*>(key)->getPublicKey()));
+}
+
 // dht::DhtRunner
 dht_runner* dht_runner_new() {
     return reinterpret_cast<dht_runner*>(new dht::DhtRunner);
diff --git a/c/opendht_c.h b/c/opendht_c.h
index 35eee1a5dadd4a9b97203ace06a4dc2323dc99d5..b0c7416272c83a569d189781065a533ee3f0ee34 100644
--- a/c/opendht_c.h
+++ b/c/opendht_c.h
@@ -14,7 +14,7 @@ extern "C" {
 // Non-owning data view
 struct OPENDHT_C_PUBLIC dht_data_view {
     const uint8_t* data;
-    size_t length;
+    size_t size;
 };
 typedef struct dht_data_view dht_data_view;
 
@@ -38,6 +38,7 @@ OPENDHT_C_PUBLIC const char* dht_infohash_print(const dht_infohash* h);
 // dht::PkId
 struct OPENDHT_C_PUBLIC dht_pkid { uint8_t d[32]; };
 typedef struct dht_pkid dht_pkid;
+OPENDHT_C_PUBLIC const char* dht_pkid_print(const dht_pkid* h);
 
 // dht::crypto::PublicKey
 struct OPENDHT_C_PUBLIC dht_publickey;
@@ -54,6 +55,9 @@ OPENDHT_C_PUBLIC dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const
 // dht::crypto::PrivateKey
 struct OPENDHT_C_PUBLIC dht_privatekey;
 typedef struct dht_privatekey dht_privatekey;
+OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_generate(unsigned key_length_bits);
+OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password);
+OPENDHT_C_PUBLIC dht_publickey* dht_privatekey_get_publickey(const dht_privatekey*);
 
 // dht::crypto::Certificate
 struct OPENDHT_C_PUBLIC dht_certificate;
diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index 7cd27c1490e16bab381459b58af0b6ca7a81f39c..1bdcb200b9268d06cdf4babeccbe52ace304fb68 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -147,7 +147,8 @@ struct OPENDHT_PUBLIC PrivateKey
     PrivateKey(PrivateKey&& o) noexcept;
     PrivateKey& operator=(PrivateKey&& o) noexcept;
 
-    PrivateKey(const Blob& import, const std::string& password = {});
+    PrivateKey(const uint8_t* src, size_t src_size, const char* password = nullptr);
+    PrivateKey(const Blob& src, const std::string& password = {}) : PrivateKey(src.data(), src.size(), password.data()) {}
     ~PrivateKey();
     explicit operator bool() const { return key; }
 
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 7d0ed146511c497e4dc5258bf1b5aac4f8f5175b..d601247860d9a71eb3848180af3d058072d55063 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -215,15 +215,14 @@ PrivateKey::PrivateKey(gnutls_x509_privkey_t k) : x509_key(k)
     }
 }
 
-PrivateKey::PrivateKey(const Blob& import, const std::string& password)
+PrivateKey::PrivateKey(const uint8_t* src, size_t src_size, const char* password_ptr)
 {
     int err = gnutls_x509_privkey_init(&x509_key);
     if (err != GNUTLS_E_SUCCESS)
         throw CryptoException("Can't initialize private key !");
 
-    const gnutls_datum_t dt {(uint8_t*)import.data(), static_cast<unsigned>(import.size())};
-    const char* password_ptr = password.empty() ? nullptr : password.c_str();
-    int flags = password.empty() ? GNUTLS_PKCS_PLAIN
+    const gnutls_datum_t dt {(uint8_t*)src, static_cast<unsigned>(src_size)};
+    int flags = password_ptr ? GNUTLS_PKCS_PLAIN
                 : ( GNUTLS_PKCS_PBES2_AES_128 | GNUTLS_PKCS_PBES2_AES_192  | GNUTLS_PKCS_PBES2_AES_256
                   | GNUTLS_PKCS_PKCS12_3DES   | GNUTLS_PKCS_PKCS12_ARCFOUR | GNUTLS_PKCS_PKCS12_RC2_40);