From f331f39c774c3fef7a49ff8a870578f32631f45a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Thu, 5 Dec 2019 18:35:23 -0500
Subject: [PATCH] c wrapper: add dht_privatekey_export

---
 c/opendht.cpp            |  9 ++++++++-
 c/opendht_c.h            |  3 ++-
 include/opendht/crypto.h |  1 +
 src/crypto.cpp           | 14 +++++++++++---
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/c/opendht.cpp b/c/opendht.cpp
index 16c79a5d..ed541237 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 fd102f27..be856cbb 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 17ef2b2d..284c6486 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 0e3ed7ab..216253a5 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
 {
-- 
GitLab