diff --git a/configure.ac b/configure.ac
index 6fd2621d..9a9bf019 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,23 +211,33 @@ AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
 
 AC_CACHE_SAVE
 
+AC_ARG_ENABLE(legacy-protocol,
+  AS_HELP_STRING([--disable-legacy-protocol], [disable support for the legacy (tinc 1.0) protocol]),
+  [ AS_IF([test "x$enable_legacy_protocol" = "xno"],
+    [ AC_DEFINE(DISABLE_LEGACY, 1, [Disable support for the legacy (tinc 1.0) protocol]) ])
+  ]
+)
+
 dnl These are defined in files in m4/
 
 dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], [])
+dnl AC_ARG_WITH(openssl, AC_HELP_STRING([--without-openssl], [disable support for OpenSSL])], [])
 
 tinc_CURSES
 tinc_READLINE
 tinc_ZLIB
 tinc_LZO
 
-if test -n "$with_libgcrypt"; then
-	gcrypt=true
-	tinc_LIBGCRYPT
-else
-	openssl=true
-	tinc_OPENSSL
+if test "x$enable_legacy_protocol" != "xno"; then
+	if test -n "$with_libgcrypt"; then
+		gcrypt=true
+		tinc_LIBGCRYPT
+	else
+		openssl=true
+		tinc_OPENSSL
+	fi
 fi
-	
+
 AM_CONDITIONAL(OPENSSL, test -n "$openssl")
 AM_CONDITIONAL(GCRYPT, test -n "$gcrypt")
 
diff --git a/src/Makefile.am b/src/Makefile.am
index cd84f3a8..5c8a8416 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -92,6 +92,8 @@ tincd_SOURCES = \
 	utils.c utils.h \
 	xalloc.h \
 	version.c version.h \
+	ed25519/ecdh.c \
+	ed25519/ecdsa.c \
 	$(ed25519_SOURCES) \
 	$(chacha_poly1305_SOURCES)
 
@@ -111,6 +113,9 @@ tinc_SOURCES = \
 	top.c top.h \
 	utils.c utils.h \
 	version.c version.h \
+	ed25519/ecdh.c \
+	ed25519/ecdsa.c \
+	ed25519/ecdsagen.c \
 	$(ed25519_SOURCES) \
 	$(chacha_poly1305_SOURCES)
 
@@ -119,12 +124,15 @@ sptps_test_SOURCES = \
 	sptps.c sptps.h \
 	sptps_test.c \
 	utils.c utils.h \
+	ed25519/ecdh.c \
+	ed25519/ecdsa.c \
 	$(ed25519_SOURCES) \
 	$(chacha_poly1305_SOURCES)
 
 sptps_keypair_SOURCES = \
 	sptps_keypair.c \
 	utils.c utils.h \
+	ed25519/ecdsagen.c \
 	$(ed25519_SOURCES)
 
 sptps_speed_SOURCES = \
@@ -132,6 +140,9 @@ sptps_speed_SOURCES = \
 	sptps.c sptps.h \
 	sptps_speed.c \
 	utils.c utils.h \
+	ed25519/ecdh.c \
+	ed25519/ecdsa.c \
+	ed25519/ecdsagen.c \
 	$(ed25519_SOURCES) \
 	$(chacha_poly1305_SOURCES)
 
@@ -173,54 +184,36 @@ tincd_SOURCES += \
 	openssl/cipher.c \
 	openssl/crypto.c \
 	openssl/digest.c openssl/digest.h \
-	ed25519/ecdh.c \
-	ed25519/ecdsa.c \
 	openssl/prf.c \
 	openssl/rsa.c
 tinc_SOURCES += \
 	openssl/cipher.c \
 	openssl/crypto.c \
 	openssl/digest.c openssl/digest.h \
-	ed25519/ecdh.c \
-	ed25519/ecdsa.c \
-	ed25519/ecdsagen.c \
 	openssl/prf.c \
 	openssl/rsa.c \
 	openssl/rsagen.c
 sptps_test_SOURCES += \
 	openssl/crypto.c \
 	openssl/digest.c openssl/digest.h \
-	ed25519/ecdh.c \
-	ed25519/ecdsa.c \
 	openssl/prf.c
 sptps_keypair_SOURCES += \
-	openssl/crypto.c \
-	ed25519/ecdsagen.c
+	openssl/crypto.c
 sptps_speed_SOURCES += \
 	openssl/crypto.c \
 	openssl/digest.c openssl/digest.h \
-	ed25519/ecdh.c \
-	ed25519/ecdsa.c \
-	ed25519/ecdsagen.c \
 	openssl/prf.c
-endif
-
-if GCRYPT
+elif GCRYPT
 tincd_SOURCES += \
 	gcrypt/cipher.c \
 	gcrypt/crypto.c \
 	gcrypt/digest.c gcrypt/digest.h \
-	gcrypt/ecdh.c \
-	gcrypt/ecdsa.c \
 	gcrypt/prf.c \
 	gcrypt/rsa.c
 tinc_SOURCES += \
 	gcrypt/cipher.c \
 	gcrypt/crypto.c \
 	gcrypt/digest.c gcrypt/digest.h \
-	gcrypt/ecdh.c \
-	gcrypt/ecdsa.c \
-	gcrypt/ecdsagen.c \
 	gcrypt/prf.c \
 	gcrypt/rsa.c \
 	gcrypt/rsagen.c
@@ -228,9 +221,28 @@ sptps_test_SOURCES += \
 	gcrypt/cipher.c \
 	gcrypt/crypto.c \
 	gcrypt/digest.c gcrypt/digest.h \
-	gcrypt/ecdh.c \
-	gcrypt/ecdsa.c \
 	gcrypt/prf.c
+sptps_keypair_SOURCES += \
+	openssl/crypto.c
+sptps_speed_SOURCES += \
+	openssl/crypto.c \
+	openssl/digest.c openssl/digest.h \
+	openssl/prf.c
+else
+tincd_SOURCES += \
+	nolegacy/crypto.c \
+	nolegacy/prf.c
+tinc_SOURCES += \
+	nolegacy/crypto.c \
+	nolegacy/prf.c
+sptps_test_SOURCES += \
+	nolegacy/crypto.c \
+	nolegacy/prf.c
+sptps_keypair_SOURCES += \
+	nolegacy/crypto.c
+sptps_speed_SOURCES += \
+	nolegacy/crypto.c \
+	nolegacy/prf.c
 endif
 
 tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
diff --git a/src/cipher.h b/src/cipher.h
index 47cd1cdc..f194c0dc 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -24,6 +24,8 @@
 #define CIPHER_MAX_IV_SIZE 16
 #define CIPHER_MAX_KEY_SIZE 32
 
+#ifndef DISABLE_LEGACY
+
 typedef struct cipher cipher_t;
 
 extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__));
@@ -40,3 +42,5 @@ extern int cipher_get_nid(const cipher_t *);
 extern bool cipher_active(const cipher_t *);
 
 #endif
+
+#endif
diff --git a/src/connection.c b/src/connection.c
index 496f6747..0e61132c 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -55,14 +55,16 @@ void free_connection(connection_t *c) {
 	if(!c)
 		return;
 
+#ifndef DISABLE_LEGACY
 	cipher_close(c->incipher);
 	digest_close(c->indigest);
 	cipher_close(c->outcipher);
 	digest_close(c->outdigest);
+	rsa_free(c->rsa);
+#endif
 
 	sptps_stop(&c->sptps);
 	ecdsa_free(c->ecdsa);
-	rsa_free(c->rsa);
 
 	free(c->hischallenge);
 
diff --git a/src/connection.h b/src/connection.h
index b74b582a..30c6598b 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -75,12 +75,15 @@ typedef struct connection_t {
 	struct node_t *node;            /* node associated with the other end */
 	struct edge_t *edge;            /* edge associated with this connection */
 
+#ifndef DISABLE_LEGACY
 	rsa_t *rsa;                     /* his public RSA key */
-	ecdsa_t *ecdsa;                 /* his public ECDSA key */
 	cipher_t *incipher;             /* Cipher he will use to send data to us */
 	cipher_t *outcipher;            /* Cipher we will use to send data to him */
 	digest_t *indigest;
 	digest_t *outdigest;
+#endif
+
+	ecdsa_t *ecdsa;                 /* his public ECDSA key */
 	sptps_t sptps;
 
 	int inmaclength;
diff --git a/src/digest.h b/src/digest.h
index 1e149456..204048ad 100644
--- a/src/digest.h
+++ b/src/digest.h
@@ -22,6 +22,8 @@
 
 #define DIGEST_MAX_SIZE 64
 
+#ifndef DISABLE_LEGACY
+
 typedef struct digest digest_t;
 
 extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__ ((__malloc__));
@@ -37,3 +39,5 @@ extern size_t digest_length(const digest_t *);
 extern bool digest_active(const digest_t *);
 
 #endif
+
+#endif
diff --git a/src/invitation.c b/src/invitation.c
index dff8d5fe..38634886 100644
--- a/src/invitation.c
+++ b/src/invitation.c
@@ -33,6 +33,8 @@
 #include "utils.h"
 #include "xalloc.h"
 
+#include "ed25519/sha512.h"
+
 int addressfamily = AF_UNSPEC;
 
 static void scan_for_hostname(const char *filename, char **hostname, char **port) {
@@ -270,8 +272,6 @@ int cmd_invite(int argc, char *argv[]) {
 		}
 	}
 
-	char hash[25];
-
 	xasprintf(&filename, "%s" SLASH "invitations", confbase);
 	if(mkdir(filename, 0700) && errno != EEXIST) {
 		fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
@@ -365,11 +365,9 @@ int cmd_invite(int argc, char *argv[]) {
 		return 1;
 
 	// Create a hash of the key.
+	char hash[64];
 	char *fingerprint = ecdsa_get_base64_public_key(key);
-	digest_t *digest = digest_open_by_name("sha256", 18);
-	if(!digest)
-		abort();
-	digest_create(digest, fingerprint, strlen(fingerprint), hash);
+	sha512(fingerprint, strlen(fingerprint), hash);
 	b64encode_urlsafe(hash, hash, 18);
 
 	// Create a random cookie for this invitation.
@@ -378,10 +376,10 @@ int cmd_invite(int argc, char *argv[]) {
 
 	// Create a filename that doesn't reveal the cookie itself
 	char buf[18 + strlen(fingerprint)];
-	char cookiehash[25];
+	char cookiehash[64];
 	memcpy(buf, cookie, 18);
 	memcpy(buf + 18, fingerprint, sizeof buf - 18);
-	digest_create(digest, buf, sizeof buf, cookiehash);
+	sha512(buf, sizeof buf, cookiehash);
 	b64encode_urlsafe(cookiehash, cookiehash, 18);
 
 	b64encode_urlsafe(cookie, cookie, 18);
@@ -739,8 +737,9 @@ make_names:
 
 	sptps_send_record(&sptps, 1, b64key, strlen(b64key));
 	free(b64key);
+	ecdsa_free(key);
 
-
+#ifndef DISABLE_LEGACY
 	rsa_t *rsa = rsa_generate(2048, 0x1001);
 	xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
 	f = fopenmask(filename, "w", 0600);
@@ -751,8 +750,8 @@ make_names:
 	rsa_write_pem_public_key(rsa, fh);
 	fclose(fh);
 
-	ecdsa_free(key);
 	rsa_free(rsa);
+#endif
 
 	check_port(name);
 
@@ -958,11 +957,8 @@ int cmd_join(int argc, char *argv[]) {
 
 	// Check if the hash of the key he gave us matches the hash in the URL.
 	char *fingerprint = line + 2;
-	digest_t *digest = digest_open_by_name("sha256", 18);
-	if(!digest)
-		abort();
-	char hishash[18];
-	if(!digest_create(digest, fingerprint, strlen(fingerprint), hishash)) {
+	char hishash[64];
+	if(sha512(fingerprint, strlen(fingerprint), hishash)) {
 		fprintf(stderr, "Could not create digest\n%s\n", line + 2);
 		return 1;
 	}
diff --git a/src/meta.c b/src/meta.c
index 73769d9a..1c29fe9c 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -58,6 +58,9 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
 
 	/* Add our data to buffer */
 	if(c->status.encryptout) {
+#ifdef DISABLE_LEGACY
+		return false;
+#else
 		size_t outlen = length;
 
 		if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
@@ -65,6 +68,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
 					c->name, c->hostname);
 			return false;
 		}
+#endif
 	} else {
 		buffer_add(&c->outbuf, buffer, length);
 	}
@@ -170,6 +174,9 @@ bool receive_meta(connection_t *c) {
 			inlen -= endp - bufp;
 			bufp = endp;
 		} else {
+#ifdef DISABLE_LEGACY
+			return false;
+#else
 			size_t outlen = inlen;
 
 			if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) {
@@ -179,6 +186,7 @@ bool receive_meta(connection_t *c) {
 			}
 
 			inlen = 0;
+#endif
 		}
 
 		while(c->inbuf.len) {
diff --git a/src/net_packet.c b/src/net_packet.c
index c1461091..c07dd1ad 100644
--- a/src/net_packet.c
+++ b/src/net_packet.c
@@ -351,10 +351,14 @@ static bool try_mac(node_t *n, const vpn_packet_t *inpkt) {
 	if(n->status.sptps)
 		return sptps_verify_datagram(&n->sptps, DATA(inpkt), inpkt->len);
 
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	if(!digest_active(n->indigest) || inpkt->len < sizeof(seqno_t) + digest_length(n->indigest))
 		return false;
 
 	return digest_verify(n->indigest, SEQNO(inpkt), inpkt->len - digest_length(n->indigest), DATA(inpkt) + inpkt->len - digest_length(n->indigest));
+#endif
 }
 
 static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
@@ -383,6 +387,9 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
 		return true;
 	}
 
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	if(!n->status.validkey) {
 		logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
 		return false;
@@ -491,6 +498,7 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
 	else
 		receive_packet(n, inpkt);
 	return true;
+#endif
 }
 
 void receive_tcppacket(connection_t *c, const char *buffer, int len) {
@@ -681,6 +689,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
 	if(n->status.sptps)
 		return send_sptps_packet(n, origpkt);
 
+#ifdef DISABLE_LEGACY
+	return;
+#else
 	/* Make sure we have a valid key */
 
 	if(!n->status.validkey) {
@@ -789,6 +800,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
 
 end:
 	origpkt->len = origlen;
+#endif
 }
 
 static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) {
diff --git a/src/net_setup.c b/src/net_setup.c
index 29f12128..1007f699 100644
--- a/src/net_setup.c
+++ b/src/net_setup.c
@@ -145,6 +145,7 @@ bool read_ecdsa_public_key(connection_t *c) {
 	return c->ecdsa;
 }
 
+#ifndef DISABLE_LEGACY
 bool read_rsa_public_key(connection_t *c) {
 	if(ecdsa_active(c->ecdsa))
 		return true;
@@ -182,6 +183,7 @@ bool read_rsa_public_key(connection_t *c) {
 	free(fname);
 	return c->rsa;
 }
+#endif
 
 static bool read_ecdsa_private_key(void) {
 	FILE *fp;
@@ -248,6 +250,7 @@ static bool read_invitation_key(void) {
 	return invitation_key;
 }
 
+#ifndef DISABLE_LEGACY
 static bool read_rsa_private_key(void) {
 	FILE *fp;
 	char *fname;
@@ -304,6 +307,7 @@ static bool read_rsa_private_key(void) {
 	free(fname);
 	return myself->connection->rsa;
 }
+#endif
 
 static timeout_t keyexpire_timeout;
 
@@ -773,6 +777,13 @@ static bool setup_myself(void) {
 
 	myself->options |= PROT_MINOR << 24;
 
+#ifdef DISABLE_LEGACY
+	experimental = read_ecdsa_private_key();
+	if(!experimental) {
+		logger(DEBUG_ALWAYS, LOG_ERR, "No private key available, cannot start tinc!");
+		return false;
+	}
+#else
 	if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
 		experimental = read_ecdsa_private_key();
 		if(!experimental)
@@ -790,6 +801,7 @@ static bool setup_myself(void) {
 			return false;
 		}
 	}
+#endif
 
 	/* Ensure myport is numeric */
 
@@ -854,6 +866,7 @@ static bool setup_myself(void) {
 		sptps_replaywin = replaywin;
 	}
 
+#ifndef DISABLE_LEGACY
 	/* Generate packet encryption key */
 
 	if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
@@ -891,6 +904,7 @@ static bool setup_myself(void) {
 	}
 
 	free(digest);
+#endif
 
 	/* Compression */
 
diff --git a/src/net_socket.c b/src/net_socket.c
index 1bf9d16a..85bc4df5 100644
--- a/src/net_socket.c
+++ b/src/net_socket.c
@@ -549,8 +549,10 @@ begin:
 
 	c->status.connecting = true;
 	c->name = xstrdup(outgoing->name);
+#ifndef DISABLE_LEGACY
 	c->outcipher = myself->connection->outcipher;
 	c->outdigest = myself->connection->outdigest;
+#endif
 	c->outmaclength = myself->connection->outmaclength;
 	c->outcompression = myself->connection->outcompression;
 	c->last_ping_time = now.tv_sec;
@@ -696,8 +698,10 @@ void handle_new_meta_connection(void *data, int flags) {
 
 	c = new_connection();
 	c->name = xstrdup("<unknown>");
+#ifndef DISABLE_LEGACY
 	c->outcipher = myself->connection->outcipher;
 	c->outdigest = myself->connection->outdigest;
+#endif
 	c->outmaclength = myself->connection->outmaclength;
 	c->outcompression = myself->connection->outcompression;
 
diff --git a/src/node.c b/src/node.c
index e97bfaf3..71f55b85 100644
--- a/src/node.c
+++ b/src/node.c
@@ -30,7 +30,7 @@
 #include "utils.h"
 #include "xalloc.h"
 
-static digest_t *sha256;
+#include "ed25519/sha512.h"
 
 splay_tree_t *node_tree;
 static splay_tree_t *node_id_tree;
@@ -48,8 +48,6 @@ static int node_id_compare(const node_t *a, const node_t *b) {
 }
 
 void init_nodes(void) {
-	sha256 = digest_open_by_name("sha256", sizeof(node_id_t));
-
 	node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
 	node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
 	node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
@@ -61,8 +59,6 @@ void exit_nodes(void) {
 	hash_free(node_udp_cache);
 	splay_delete_tree(node_id_tree);
 	splay_delete_tree(node_tree);
-
-	digest_close(sha256);
 }
 
 node_t *new_node(void) {
@@ -86,10 +82,12 @@ void free_node(node_t *n) {
 
 	sockaddrfree(&n->address);
 
+#ifndef DISABLE_LEGACY
 	cipher_close(n->incipher);
 	digest_close(n->indigest);
 	cipher_close(n->outcipher);
 	digest_close(n->outdigest);
+#endif
 
 	ecdsa_free(n->ecdsa);
 	sptps_stop(&n->sptps);
@@ -109,7 +107,9 @@ void free_node(node_t *n) {
 }
 
 void node_add(node_t *n) {
-	digest_create(sha256, n->name, strlen(n->name), &n->id);
+	unsigned char buf[64];
+	sha512(n->name, strlen(n->name),buf);
+	memcpy(&n->id, buf, sizeof n->id);
 
 	splay_insert(node_tree, n);
 	splay_insert(node_id_tree, n);
@@ -191,10 +191,15 @@ bool dump_nodes(connection_t *c) {
 			sprintf(id + 2 * c, "%02hhx", n->id.x[c]);
 		id[sizeof id - 1] = 0;
 		send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
-			   n->name, id, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
-			   digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression,
-			   n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
-			   n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
+			   n->name, id, n->hostname ?: "unknown port unknown",
+#ifdef DISABLE_LEGACY
+			   0, 0, 0,
+#else
+			   cipher_get_nid(n->outcipher), digest_get_nid(n->outdigest), (int)digest_length(n->outdigest),
+#endif
+			   n->outcompression, n->options, bitfield_to_int(&n->status, sizeof n->status),
+			   n->nexthop ? n->nexthop->name : "-", n->via ? n->via->name ?: "-" : "-", n->distance,
+			   n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
 	}
 
 	return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
diff --git a/src/node.h b/src/node.h
index b6db18b3..bd10add7 100644
--- a/src/node.h
+++ b/src/node.h
@@ -57,11 +57,13 @@ typedef struct node_t {
 	ecdsa_t *ecdsa;                         /* His public ECDSA key */
 	sptps_t sptps;
 
+#ifndef DISABLE_LEGACY
 	cipher_t *incipher;                     /* Cipher for UDP packets */
 	digest_t *indigest;                     /* Digest for UDP packets */
 
 	cipher_t *outcipher;                    /* Cipher for UDP packets */
 	digest_t *outdigest;                    /* Digest for UDP packets */
+#endif
 
 	int incompression;                      /* Compressionlevel, 0 = no compression */
 	int outcompression;                     /* Compressionlevel, 0 = no compression */
diff --git a/src/protocol_auth.c b/src/protocol_auth.c
index cd39f28d..0882ddfc 100644
--- a/src/protocol_auth.c
+++ b/src/protocol_auth.c
@@ -45,6 +45,8 @@
 #include "utils.h"
 #include "xalloc.h"
 
+#include "ed25519/sha512.h"
+
 ecdsa_t *invitation_key = NULL;
 
 static bool send_proxyrequest(connection_t *c) {
@@ -211,17 +213,13 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
 		return false;
 
 	// Recover the filename from the cookie and the key
-	digest_t *digest = digest_open_by_name("sha256", 18);
-	if(!digest)
-		abort();
 	char *fingerprint = ecdsa_get_base64_public_key(invitation_key);
 	char hashbuf[18 + strlen(fingerprint)];
-	char cookie[25];
+	char cookie[64];
 	memcpy(hashbuf, data, 18);
 	memcpy(hashbuf + 18, fingerprint, sizeof hashbuf - 18);
-	digest_create(digest, hashbuf, sizeof hashbuf, cookie);
+	sha512(hashbuf, sizeof hashbuf, cookie);
 	b64encode_urlsafe(cookie, cookie, 18);
-	digest_close(digest);
 	free(fingerprint);
 
 	char filename[PATH_MAX], usedname[PATH_MAX];
@@ -412,6 +410,9 @@ bool id_h(connection_t *c, const char *request) {
 }
 
 bool send_metakey(connection_t *c) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	if(!myself->connection->rsa) {
 		logger(DEBUG_CONNECTIONS, LOG_ERR, "Peer %s (%s) uses legacy protocol which we don't support", c->name, c->hostname);
 		return false;
@@ -480,9 +481,13 @@ bool send_metakey(connection_t *c) {
 
 	c->status.encryptout = true;
 	return result;
+#endif
 }
 
 bool metakey_h(connection_t *c, const char *request) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	if(!myself->connection->rsa)
 		return false;
 
@@ -545,9 +550,13 @@ bool metakey_h(connection_t *c, const char *request) {
 	c->allow_request = CHALLENGE;
 
 	return send_challenge(c);
+#endif
 }
 
 bool send_challenge(connection_t *c) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	const size_t len = rsa_size(c->rsa);
 	char buffer[len * 2 + 1];
 
@@ -565,9 +574,13 @@ bool send_challenge(connection_t *c) {
 	/* Send the challenge */
 
 	return send_request(c, "%d %s", CHALLENGE, buffer);
+#endif
 }
 
 bool challenge_h(connection_t *c, const char *request) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	if(!myself->connection->rsa)
 		return false;
 
@@ -606,9 +619,13 @@ bool challenge_h(connection_t *c, const char *request) {
 	c->allow_request = CHAL_REPLY;
 
 	return send_request(c, "%d %s", CHAL_REPLY, buffer);
+#endif
 }
 
 bool chal_reply_h(connection_t *c, const char *request) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	char hishash[MAX_STRING_SIZE];
 
 	if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) {
@@ -645,9 +662,13 @@ bool chal_reply_h(connection_t *c, const char *request) {
 	c->allow_request = ACK;
 
 	return send_ack(c);
+#endif
 }
 
 static bool send_upgrade(connection_t *c) {
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	/* Special case when protocol_minor is 1: the other end is Ed25519 capable,
 	 * but doesn't know our key yet. So send it now. */
 
@@ -659,6 +680,7 @@ static bool send_upgrade(connection_t *c) {
 	bool result = send_request(c, "%d %s", ACK, pubkey);
 	free(pubkey);
 	return result;
+#endif
 }
 
 bool send_ack(connection_t *c) {
diff --git a/src/protocol_key.c b/src/protocol_key.c
index 8b19d900..cfa2f53f 100644
--- a/src/protocol_key.c
+++ b/src/protocol_key.c
@@ -266,6 +266,9 @@ bool send_ans_key(node_t *to) {
 	if(to->status.sptps)
 		abort();
 
+#ifdef DISABLE_LEGACY
+	return false;
+#else
 	size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
 	char key[keylen * 2 + 1];
 
@@ -306,6 +309,7 @@ bool send_ans_key(node_t *to) {
 						digest_get_nid(to->indigest),
 						(int)digest_length(to->indigest),
 						to->incompression);
+#endif
 }
 
 bool ans_key_h(connection_t *c, const char *request) {
@@ -371,9 +375,11 @@ bool ans_key_h(connection_t *c, const char *request) {
 		return send_request(to->nexthop->connection, "%s", request);
 	}
 
+#ifndef DISABLE_LEGACY
 	/* Don't use key material until every check has passed. */
 	cipher_close(from->outcipher);
 	digest_close(from->outdigest);
+#endif
 	from->status.validkey = false;
 
 	if(compression < 0 || compression > 11) {
@@ -408,6 +414,10 @@ bool ans_key_h(connection_t *c, const char *request) {
 		return true;
 	}
 
+#ifdef DISABLE_LEGACY
+	logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%) uses legacy protocol!", from->name, from->hostname);
+	return false;
+#else
 	/* Check and lookup cipher and digest algorithms */
 
 	if(cipher) {
@@ -462,4 +472,5 @@ bool ans_key_h(connection_t *c, const char *request) {
 		send_mtu_probe(from);
 
 	return true;
+#endif
 }
diff --git a/src/tincctl.c b/src/tincctl.c
index abaf6ee8..0eb3a256 100644
--- a/src/tincctl.c
+++ b/src/tincctl.c
@@ -119,8 +119,12 @@ static void usage(bool status) {
 				"  restart [tincd options]    Restart tincd.\n"
 				"  reload                     Partially reload configuration of running tincd.\n"
 				"  pid                        Show PID of currently running tincd.\n"
+#ifdef DISABLE_LEGACY
+				"  generate-keys              Generate a new Ed25519 public/private keypair.\n"
+#else
 				"  generate-keys [bits]       Generate new RSA and Ed25519 public/private keypairs.\n"
 				"  generate-rsa-keys [bits]   Generate a new RSA public/private keypair.\n"
+#endif
 				"  generate-ed25519-keys      Generate a new Ed25519 public/private keypair.\n"
 				"  dump                       Dump a list of one of the following things:\n"
 				"    [reachable] nodes        - all known nodes in the VPN\n"
@@ -415,6 +419,7 @@ static bool ed25519_keygen(bool ask) {
 	return true;
 }
 
+#ifndef DISABLE_LEGACY
 /*
   Generate a public/private RSA keypair, and ask for a file to store
   them in.
@@ -480,6 +485,7 @@ static bool rsa_keygen(int bits, bool ask) {
 
 	return true;
 }
+#endif
 
 char buffer[4096];
 size_t blen = 0;
@@ -1800,7 +1806,12 @@ static int cmd_init(int argc, char *argv[]) {
 	fprintf(f, "Name = %s\n", name);
 	fclose(f);
 
-	if(!rsa_keygen(2048, false) || !ed25519_keygen(false))
+#ifndef DISABLE_LEGACY
+	if(!rsa_keygen(2048, false))
+		return 1;
+#endif
+
+	if(!ed25519_keygen(false))
 		return 1;
 
 	check_port(name);
@@ -1824,7 +1835,11 @@ static int cmd_init(int argc, char *argv[]) {
 }
 
 static int cmd_generate_keys(int argc, char *argv[]) {
+#ifdef DISABLE_LEGACY
+	if(argc > 1) {
+#else
 	if(argc > 2) {
+#endif
 		fprintf(stderr, "Too many arguments!\n");
 		return 1;
 	}
@@ -1832,9 +1847,18 @@ static int cmd_generate_keys(int argc, char *argv[]) {
 	if(!name)
 		name = get_my_name(false);
 
-	return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ed25519_keygen(true));
+#ifndef DISABLE_LEGACY
+	if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)
+		return 1;
+#endif
+
+	if(!ed25519_keygen(true))
+		return 1;
+
+	return 0;
 }
 
+#ifndef DISABLE_LEGACY
 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
 	if(argc > 2) {
 		fprintf(stderr, "Too many arguments!\n");
@@ -1846,6 +1870,7 @@ static int cmd_generate_rsa_keys(int argc, char *argv[]) {
 
 	return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
 }
+#endif
 
 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
 	if(argc > 1) {
@@ -2196,7 +2221,9 @@ static const struct {
 	{"set", cmd_config},
 	{"init", cmd_init},
 	{"generate-keys", cmd_generate_keys},
+#ifndef DISABLE_LEGACY
 	{"generate-rsa-keys", cmd_generate_rsa_keys},
+#endif
 	{"generate-ed25519-keys", cmd_generate_ed25519_keys},
 	{"help", cmd_help},
 	{"version", cmd_version},