$ git clone https://socialnetwork.ion.nu/socialnetwork.git
commit 78367e210b7e4afb4e03674cb720adb61b2ccbe7
Author: Alicia <...>
Date:   Fri Jan 6 20:02:57 2017 +0000

    Moved private key loading/generation to peer_init() and extracting the key ID in the process.

diff --git a/peer.c b/peer.c
index 1cebb5c..0954eaf 100644
--- a/peer.c
+++ b/peer.c
@@ -34,10 +34,12 @@ struct command
   void(*callback)(struct peer*,void*,unsigned int);
 };
 
+unsigned char peer_id[20];
 static struct peer** peers=0;
 static unsigned int peercount=0;
 static struct command* commands=0;
 static unsigned int commandcount=0;
+static gnutls_x509_privkey_t privkey=0;
 
 void peer_registercmd(const char* name, void(*callback)(struct peer*,void*,unsigned int))
 {
@@ -122,9 +124,45 @@ static void getpeers(struct peer* peer, void* data, unsigned int len)
 printf("We now have %u peers\n", peercount);
 }
 
-void peer_init(void)
+void peer_init(const char* keypath)
 {
   gnutls_global_init();
+  // Load our private key, or generate one if we don't have one yet
+  if(!privkey)
+  {
+    gnutls_x509_privkey_init(&privkey);
+    struct stat st;
+    char loadfailed=1;
+    if(!stat(keypath, &st))
+    {
+      gnutls_datum_t keydata;
+      keydata.size=st.st_size;
+      keydata.data=malloc(st.st_size);
+      int f=open(keypath, O_RDONLY);
+      read(f, keydata.data, st.st_size);
+      close(f);
+      // TODO: Allow encrypted keys, using _import2()
+      if(!gnutls_x509_privkey_import2(privkey, &keydata, GNUTLS_X509_FMT_PEM, 0, GNUTLS_PKCS_PLAIN)){loadfailed=0;}
+      free(keydata.data);
+    }
+    if(loadfailed)
+    {
+// printf("Generating a new key...\n");
+      // TODO: Why do handshakes fail with >3072 bit keys?
+      gnutls_x509_privkey_generate(privkey, GNUTLS_PK_RSA, 3072, 0);
+// printf("Done\n");
+      // TODO: Allow exporting encrypted key, using _export2_pkcs8() I think
+      gnutls_datum_t keydata;
+      gnutls_x509_privkey_export2(privkey, GNUTLS_X509_FMT_PEM, &keydata);
+      int f=open(keypath, O_WRONLY|O_TRUNC|O_CREAT, 0600);
+      write(f, keydata.data, keydata.size);
+      close(f);
+      gnutls_free(keydata.data);
+    }
+    size_t size=20;
+    gnutls_x509_privkey_get_key_id(privkey, 0, peer_id, &size);
+  }
+  // Register core commands
   peer_registercmd("getpeers", sendpeers);
   peer_registercmd("peers", getpeers);
 }
@@ -146,7 +184,7 @@ static int checkcert(gnutls_session_t tls)
   if(!count){return 1;}
   gnutls_x509_crt_t cert;
   gnutls_x509_crt_init(&cert);
-  int x=gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
+  gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
   // Get the certificate's public key ID
   size_t size=20;
   gnutls_x509_crt_get_key_id(cert, 0, peer->id, &size);
@@ -157,51 +195,16 @@ static int checkcert(gnutls_session_t tls)
 
 static void generatecert(gnutls_certificate_credentials_t cred)
 {
-// TODO: Configurable key path
-  // Load our private key, or generate one if we don't have one yet
-  static gnutls_x509_privkey_t key=0;
-  if(!key)
-  {
-    gnutls_x509_privkey_init(&key);
-    struct stat st;
-    char loadfailed=1;
-    if(!stat("priv.pem", &st))
-    {
-      gnutls_datum_t keydata;
-      keydata.size=st.st_size;
-      keydata.data=malloc(st.st_size);
-      int f=open("priv.pem", O_RDONLY);
-      read(f, keydata.data, st.st_size);
-      close(f);
-      // TODO: Allow encrypted keys, using _import2()
-      if(!gnutls_x509_privkey_import2(key, &keydata, GNUTLS_X509_FMT_PEM, 0, GNUTLS_PKCS_PLAIN)){loadfailed=0;}
-      free(keydata.data);
-    }
-    if(loadfailed)
-    {
-// printf("Generating a new key...\n");
-      // TODO: Why do handshakes fail with >3072 bit keys?
-      gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 3072, 0);
-// printf("Done\n");
-      // TODO: Allow exporting encrypted key, using _export2_pkcs8() I think
-      gnutls_datum_t keydata;
-      gnutls_x509_privkey_export2(key, GNUTLS_X509_FMT_PEM, &keydata);
-      int f=open("priv.pem", O_WRONLY|O_TRUNC|O_CREAT, 0600);
-      write(f, keydata.data, keydata.size);
-      close(f);
-      gnutls_free(keydata.data);
-    }
-  }
   // Generate the certificate
   gnutls_x509_crt_t cert;
   gnutls_datum_t certdata;
   gnutls_x509_crt_init(&cert);
-  gnutls_x509_crt_set_key(cert, key);
+  gnutls_x509_crt_set_key(cert, privkey);
   gnutls_x509_crt_set_serial(cert, "", 1);
   gnutls_x509_crt_set_activation_time(cert, time(0)-3600); // Allow up to an hour of time drift
   gnutls_x509_crt_set_expiration_time(cert, time(0)+3600);
-  gnutls_x509_crt_sign(cert, cert, key);
-  gnutls_certificate_set_x509_key(cred, &cert, 1, key);
+  gnutls_x509_crt_sign(cert, cert, privkey);
+  gnutls_certificate_set_x509_key(cred, &cert, 1, privkey);
   gnutls_x509_crt_deinit(cert);
 }
 
diff --git a/peer.h b/peer.h
index 3fce7d6..7f1b6c6 100644
--- a/peer.h
+++ b/peer.h
@@ -34,9 +34,10 @@ struct peer
 // Macros for printing peer IDs in printf-family of functions
 #define PEERFMT "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
 #define PEERARG(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15],x[16],x[17],x[18],x[19]
+extern unsigned char peer_id[20];
 
 extern void peer_registercmd(const char* name, void(*callback)(struct peer*,void*,unsigned int));
-extern void peer_init(void);
+extern void peer_init(const char* keypath);
 extern struct peer* peer_new(struct udpstream* stream, char server);
 extern struct peer* peer_get(struct udpstream* stream);
 extern struct peer* peer_new_unique(int sock, struct sockaddr* addr, socklen_t addrlen);
diff --git a/peertest.c b/peertest.c
index 76e1561..fad78b0 100644
--- a/peertest.c
+++ b/peertest.c
@@ -37,7 +37,7 @@ int main(int argc, char** argv)
     bind(sock, ai->ai_addr, ai->ai_addrlen);
     freeaddrinfo(ai);
   }
-  peer_init();
+  peer_init("priv.pem");
   peer_registercmd("msg", gotmsg);
   peer_bootstrap(sock, "127.0.0.1:4000");
   struct pollfd pfd[]={{.fd=0, .events=POLLIN, .revents=0}, {.fd=sock, .events=POLLIN, .revents=0}};