diff --git a/c/opendht.cpp b/c/opendht.cpp
index 16c79a5d9acb25dcf9c942cd998a9abd35f18120..ed5412370e5d5424c4ee5ff9af57c9d484105455 100644
--- a/c/opendht.cpp
+++ b/c/opendht.cpp
@@ -122,7 +122,7 @@ void dht_publickey_delete(dht_publickey* pk) {
     delete reinterpret_cast<PubkeySp*>(pk);
 }
 
-int dht_publickey_pack(dht_publickey* pk, char* out, size_t* outlen) {
+int dht_publickey_export(const dht_publickey* pk, char* out, size_t* outlen) {
     const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
     return gnutls_pubkey_export(pkey->pk, GNUTLS_X509_FMT_DER, out, outlen);
 }
@@ -164,6 +164,13 @@ dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const
     }
 }
 
+int dht_privatekey_export(const dht_privatekey* k, char* out, size_t* out_size, const char* password) {
+    if (!out or !out_size or !*out_size)
+        return -1;
+    const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
+    return key->serialize((uint8_t*)out, out_size, password);
+}
+
 dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
     const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
     return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(key->getPublicKey())));
diff --git a/c/opendht_c.h b/c/opendht_c.h
index fd102f279b2230a0e9e3021b6d07cdddebd6b1ea..be856cbb42f262268199a66643be667dbfc0193a 100644
--- a/c/opendht_c.h
+++ b/c/opendht_c.h
@@ -45,7 +45,7 @@ struct OPENDHT_C_PUBLIC dht_publickey;
 typedef struct dht_publickey dht_publickey;
 OPENDHT_C_PUBLIC dht_publickey* dht_publickey_import(const uint8_t* dat, size_t dat_size);
 OPENDHT_C_PUBLIC void dht_publickey_delete(dht_publickey* pk);
-OPENDHT_C_PUBLIC int dht_publickey_pack(dht_publickey* pk, char* out, size_t* out_size);
+OPENDHT_C_PUBLIC int dht_publickey_export(const dht_publickey* pk, char* out, size_t* out_size);
 OPENDHT_C_PUBLIC dht_infohash dht_publickey_get_id(const dht_publickey* pk);
 OPENDHT_C_PUBLIC dht_pkid dht_publickey_get_long_id(const dht_publickey* pk);
 OPENDHT_C_PUBLIC bool dht_publickey_check_signature(const dht_publickey* pk, const char* data, size_t data_size, const char* signature, size_t signature_size);
@@ -56,6 +56,7 @@ 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 int dht_privatekey_export(const dht_privatekey*, char* out, size_t* out_size, const char* password);
 OPENDHT_C_PUBLIC dht_publickey* dht_privatekey_get_publickey(const dht_privatekey*);
 OPENDHT_C_PUBLIC void dht_privatekey_delete(dht_privatekey*);
 
diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index 17ef2b2d3614a746f78fe9fe0af713db1b4455a1..284c6486b82635b517969fd28bbf0a240e2a7b68 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -160,6 +160,7 @@ struct OPENDHT_PUBLIC PrivateKey
     explicit operator bool() const { return key; }
 
     PublicKey getPublicKey() const;
+    int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const;
     Blob serialize(const std::string& password = {}) const;
 
     /**
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 0e3ed7ab59104a86a19486005a873ac46f735c86..216253a5961f78c58783c7c193092bf59f9f5046 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -348,9 +348,7 @@ PrivateKey::serialize(const std::string& password) const
     size_t buf_sz = 8192;
     Blob buffer;
     buffer.resize(buf_sz);
-    int err = password.empty()
-        ? gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, nullptr,          GNUTLS_PKCS_PLAIN,         buffer.data(), &buf_sz)
-        : gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, password.c_str(), GNUTLS_PKCS_PBES2_AES_256, buffer.data(), &buf_sz);
+    auto err = serialize(buffer.data(), &buf_sz, password);
     if (err != GNUTLS_E_SUCCESS) {
         std::cerr << "Could not export private key - " << gnutls_strerror(err) << std::endl;
         return {};
@@ -359,6 +357,16 @@ PrivateKey::serialize(const std::string& password) const
     return buffer;
 }
 
+int
+PrivateKey::serialize(uint8_t* out, size_t* out_len, const std::string& password) const
+{
+    if (!x509_key)
+        return -1;
+    return password.empty()
+        ? gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, nullptr,          GNUTLS_PKCS_PLAIN,         out, out_len)
+        : gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, password.c_str(), GNUTLS_PKCS_PBES2_AES_256, out, out_len);
+}
+
 PublicKey
 PrivateKey::getPublicKey() const
 {