diff --git a/.cproject b/.cproject
index bd43fbf..542ec82 100644
--- a/.cproject
+++ b/.cproject
@@ -26,6 +26,7 @@
diff --git a/Makefile b/Makefile
index 224d126..a147db5 100644
--- a/Makefile
+++ b/Makefile
@@ -2,19 +2,27 @@
DEBUG = true
export DEBUG
-OBJS = crypto/*.o crypto/encoding/*.o thirdparty/mbedtls/*.o hashmap/hashmap.o record/*.o routing/*.o
+OBJS = crypto/*.o crypto/encoding/*.o \
+ thirdparty/mbedtls/*.o \
+ hashmap/hashmap.o \
+ net/*.o \
+ record/*.o \
+ routing/*.o \
+ secio/*.o
+link: $(OBJS)
+ ar rcs libp2p.a $(OBJS)
compile:
cd crypto; make all;
cd thirdparty; make all;
cd hashmap; make all;
+ cd net; make all;
cd record; make all;
cd routing; make all;
cd secio; make all;
- ar rcs libp2p.a $(OBJS)
-test: compile
+test: compile link
cd test; make all;
rebuild: clean all
@@ -24,6 +32,7 @@ all: test
clean:
cd crypto; make clean;
cd hashmap; make clean;
+ cd net; make clean;
cd thirdparty; make clean
cd test; make clean;
cd record; make clean;
diff --git a/crypto/Makefile b/crypto/Makefile
index e0ea3ac..825d6d9 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -1,8 +1,8 @@
CC = gcc
-CFLAGS = -O0 -I../include -g3
+CFLAGS = -O0 -I../include -I../../c-protobuf -I../../c-multihash/include -g3
LFLAGS =
DEPS =
-OBJS = rsa.o sha256.o sha512.o sha1.o
+OBJS = rsa.o sha256.o sha512.o sha1.o key.o peerutils.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
diff --git a/crypto/key.c b/crypto/key.c
index 8d91484..83ec18a 100644
--- a/crypto/key.c
+++ b/crypto/key.c
@@ -1,31 +1,29 @@
-#include
+#include
+#include
+
+#include "libp2p/crypto/key.h"
+#include "libp2p/crypto/sha256.h"
+#include "libp2p/crypto/peerutils.h"
+#include "protobuf.h"
/**
- * Utilities for public keys
+ * Utilities for public and private keys
*/
-enum KeyType { KEYTYPE_RSA, KEYTYPE_ED25519, KEYTYPE_INVALID };
-
-struct PublicKey {
- enum KeyType key_type;
- char* raw_key;
- size_t raw_key_size;
-};
-
struct PublicKey* libp2p_crypto_public_key_new() {
struct PublicKey* retVal = malloc(sizeof(struct PublicKey));
if (retVal == NULL)
return NULL;
- retVal->key_type = KEYTYPE_INVALID;
- retVal->raw_key = NULL;
- retVal->raw_key_size = 0;
+ retVal->type = KEYTYPE_INVALID;
+ retVal->data = NULL;
+ retVal->data_size = 0;
return retVal;
}
void libp2p_crypto_public_key_free(struct PublicKey* in) {
if (in != NULL) {
- if (in->raw_key != NULL)
- free(in->raw_key);
+ if (in->data != NULL)
+ free(in->data);
free(in);
in = NULL;
}
@@ -33,6 +31,10 @@ void libp2p_crypto_public_key_free(struct PublicKey* in) {
/**
* Unmarshal a public key from a protobuf
+ * @param buffer the protobuf
+ * @param buffer_length the length of the protobuf
+ * @param out the pointer to the struct PublicKey that will be allocated
+ * @returns true(1) on success, otherwise false(0)
*/
int libp2p_crypto_public_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PublicKey** out) {
@@ -55,12 +57,12 @@ int libp2p_crypto_public_key_protobuf_decode(unsigned char* buffer, size_t buffe
pos += bytes_read;
switch(field_no) {
case (1): // type
- if (protobuf_decode_varint(&buffer[pos], buffer_length - pos, &((*out)->key_type), &bytes_read) == 0)
+ if (protobuf_decode_varint(&buffer[pos], buffer_length - pos, (long long unsigned int*)&((*out)->type), &bytes_read) == 0)
goto exit;
pos += bytes_read;
break;
case (2): // key
- if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->raw_key), &((*out)->raw_key_size), &bytes_read) == 0)
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->data), &((*out)->data_size), &bytes_read) == 0)
goto exit;
pos += bytes_read;
break;
@@ -75,3 +77,94 @@ exit:
}
return retVal;
}
+
+struct PrivateKey* libp2p_crypto_private_key_new() {
+ struct PrivateKey* retVal = malloc(sizeof(struct PrivateKey));
+ if (retVal == NULL)
+ return NULL;
+ retVal->type = KEYTYPE_INVALID;
+ retVal->data = NULL;
+ retVal->data_size = 0;
+ return retVal;
+}
+
+void libp2p_crypto_private_key_free(struct PrivateKey* in) {
+ if (in != NULL) {
+ if (in->data != NULL)
+ free(in->data);
+ free(in);
+ in = NULL;
+ }
+}
+
+/**
+ * Unmarshal a private key from a protobuf
+ * @param buffer the protobuf
+ * @param buffer_length the length of the protobuf
+ * @param out the pointer to the struct PrivateKey that will be allocated
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_crypto_private_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PrivateKey** out) {
+
+ // first field is type (RSA vs ED25519)
+ // second field is the public key
+
+ size_t pos = 0;
+ int retVal = 0;
+
+ if ( (*out = libp2p_crypto_private_key_new()) == NULL)
+ goto exit;
+
+ while(pos < buffer_length) {
+ size_t bytes_read = 0;
+ int field_no;
+ enum WireType field_type;
+ if (protobuf_decode_field_and_type(&buffer[pos], buffer_length, &field_no, &field_type, &bytes_read) == 0) {
+ goto exit;
+ }
+ pos += bytes_read;
+ switch(field_no) {
+ case (1): // type
+ if (protobuf_decode_varint(&buffer[pos], buffer_length - pos, (long long unsigned int*)&((*out)->type), &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ break;
+ case (2): // key
+ if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->data), &((*out)->data_size), &bytes_read) == 0)
+ goto exit;
+ pos += bytes_read;
+ break;
+ }
+ }
+
+ retVal = 1;
+
+exit:
+ if (retVal == 0) {
+ libp2p_crypto_private_key_free(*out);
+ }
+ return retVal;
+}
+
+/**
+ * convert a public key into a peer id
+ * @param public_key the public key struct
+ * @param peer_id the results, in a null-terminated string
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id) {
+ unsigned char hashed[32];
+ libp2p_crypto_hashing_sha256(public_key->data, public_key->data_size, hashed);
+ size_t final_id_size = 100;
+ unsigned char final_id[final_id_size];
+ memset(final_id, 0, final_id_size);
+ if (!PrettyID(final_id, &final_id_size, hashed, 32))
+ return 0;
+ *peer_id = (char*)malloc(final_id_size + 1);
+ if (*peer_id == NULL)
+ return 0;
+ memset(*peer_id, 0, final_id_size + 1);
+ memcpy(*peer_id, final_id, final_id_size);
+ return 1;
+}
+
diff --git a/crypto/peerutils.c b/crypto/peerutils.c
new file mode 100644
index 0000000..5952d0a
--- /dev/null
+++ b/crypto/peerutils.c
@@ -0,0 +1,66 @@
+#include
+#include
+
+#include "mh/multihash.h"
+#include "mh/hashes.h"
+#include "libp2p/crypto/encoding/base58.h"
+#include "libp2p/crypto/sha256.h"
+
+/**
+ * base58 encode a string NOTE: this also puts the prefix 'Qm' in front as the ID is a multihash
+ * @param pointyaddr where the results will go
+ * @param rezbuflen the length of the results buffer. It will also put how much was used here
+ * @param ID_BUF the input text (usually a SHA256 hash)
+ * @param ID_BUF_SIZE the input size (normally a SHA256, therefore 32 bytes)
+ * @returns true(1) on success
+ */
+int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BUF, size_t ID_BUF_SIZE)//b58 encoded ID buf
+{
+ int returnstatus = 0;
+
+ unsigned char temp_buffer[*rezbuflen];
+
+ memset(temp_buffer, 0, *rezbuflen);
+
+ // wrap the base58 into a multihash
+ int retVal = mh_new(temp_buffer, MH_H_SHA2_256, ID_BUF, ID_BUF_SIZE);
+ if (retVal < 0)
+ return 0;
+
+ // base58 the multihash
+ returnstatus = libp2p_crypto_encoding_base58_encode(temp_buffer, strlen((char*)temp_buffer), &pointyaddr, rezbuflen);
+ if(returnstatus == 0)
+ return 0;
+
+ return 1;
+}
+
+/****
+ * Make a SHA256 hash of what is usually the DER formatted private key.
+ * @param result where to store the result. Should be 32 chars long
+ * @param texttohash the text to hash
+ * @param text_size the size of the text
+ */
+void ID_FromPK_non_null_terminated(char * result,unsigned char * texttohash, size_t text_size)
+{
+ /* old way
+ unsigned char hash[32];
+ bzero(hash,32);
+ SHA256_CTX ctx;
+ sha256_init(&ctx);
+ sha256_update(&ctx,texttohash,text_size);
+ sha256_final(&ctx,hash);
+ a_store_hash(result,hash);
+ */
+ libp2p_crypto_hashing_sha256(texttohash, text_size, (unsigned char*)result);
+}
+
+/****
+ * Make a SHA256 hash of what is usually the DER formatted private key.
+ * @param result where to store the result. Should be 32 chars long
+ * @param texttohash a null terminated string of the text to hash
+ */
+void ID_FromPK(char * result,unsigned char * texttohash)
+{
+ ID_FromPK_non_null_terminated(result,texttohash,strlen((char*)texttohash));
+}
diff --git a/crypto/sha1.c b/crypto/sha1.c
index d2ed6b4..5bf90ec 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -92,7 +92,7 @@ A million repetitions of "a"
#include
#include
-#include
+#include "libp2p/crypto/sha1.h"
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
diff --git a/include/libp2p/crypto/key.h b/include/libp2p/crypto/key.h
index f201970..12355b7 100644
--- a/include/libp2p/crypto/key.h
+++ b/include/libp2p/crypto/key.h
@@ -19,11 +19,21 @@ struct PrivateKey {
};
struct PublicKey* libp2p_crypto_public_key_new();
-
void libp2p_crypto_public_key_free(struct PublicKey* in);
+struct PrivateKey* libp2p_crypto_private_key_new();
+void libp2p_crypto_private_key_free(struct PrivateKey* in);
+
/**
* Unmarshal a public key from a protobuf
*/
int libp2p_crypto_public_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PublicKey** out);
-int libp2p_crypto_private_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PublicKey** out);
+int libp2p_crypto_private_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PrivateKey** out);
+
+/**
+ * convert a public key into a peer id
+ * @param public_key the public key struct
+ * @param peer_id the results, in a null-terminated string
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id);
diff --git a/include/libp2p/peerutils.h b/include/libp2p/crypto/peerutils.h
similarity index 86%
rename from include/libp2p/peerutils.h
rename to include/libp2p/crypto/peerutils.h
index 17b12a5..48ecd76 100644
--- a/include/libp2p/peerutils.h
+++ b/include/libp2p/crypto/peerutils.h
@@ -9,6 +9,8 @@
#include "mh/multihash.h"
#include "mh/hashes.h"
+/*
+
#define uchar unsigned char // 8-bit byte
#define juint unsigned int // 32-bit word
// DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it
@@ -170,6 +172,8 @@ void a_store_hash(unsigned char * result,unsigned char hash[])
}
}
+*/
+
/**
* base58 encode a string NOTE: this also puts the prefix 'Qm' in front as the ID is a multihash
* @param pointyaddr where the results will go
@@ -178,26 +182,7 @@ void a_store_hash(unsigned char * result,unsigned char hash[])
* @param ID_BUF_SIZE the input size (normally a SHA256, therefore 32 bytes)
* @returns true(1) on success
*/
-int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BUF, size_t ID_BUF_SIZE)//b58 encoded ID buf
-{
- int returnstatus = 0;
-
- unsigned char temp_buffer[*rezbuflen];
-
- memset(temp_buffer, 0, *rezbuflen);
-
- // wrap the base58 into a multihash
- int retVal = mh_new(temp_buffer, MH_H_SHA2_256, ID_BUF, ID_BUF_SIZE);
- if (retVal < 0)
- return 0;
-
- // base58 the multihash
- returnstatus = libp2p_crypto_encoding_base58_encode(temp_buffer, strlen((char*)temp_buffer), &pointyaddr, rezbuflen);
- if(returnstatus == 0)
- return 0;
-
- return 1;
-}
+int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BUF, size_t ID_BUF_SIZE);//b58 encoded ID buf
/****
* Make a SHA256 hash of what is usually the DER formatted private key.
@@ -205,28 +190,13 @@ int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BU
* @param texttohash the text to hash
* @param text_size the size of the text
*/
-void ID_FromPK_non_null_terminated(char * result,unsigned char * texttohash, size_t text_size)
-{
- /* old way
- unsigned char hash[32];
- bzero(hash,32);
- SHA256_CTX ctx;
- sha256_init(&ctx);
- sha256_update(&ctx,texttohash,text_size);
- sha256_final(&ctx,hash);
- a_store_hash(result,hash);
- */
- libp2p_crypto_hashing_sha256(texttohash, text_size, (unsigned char*)result);
-}
+void ID_FromPK_non_null_terminated(char * result,unsigned char * texttohash, size_t text_size);
/****
* Make a SHA256 hash of what is usually the DER formatted private key.
* @param result where to store the result. Should be 32 chars long
* @param texttohash a null terminated string of the text to hash
*/
-void ID_FromPK(char * result,unsigned char * texttohash)
-{
- ID_FromPK_non_null_terminated(result,texttohash,strlen((char*)texttohash));
-}
+void ID_FromPK(char * result,unsigned char * texttohash);
#endif
diff --git a/include/libp2p/net/multistream.h b/include/libp2p/net/multistream.h
new file mode 100644
index 0000000..2c03bae
--- /dev/null
+++ b/include/libp2p/net/multistream.h
@@ -0,0 +1,30 @@
+#pragma once
+
+/***
+ * An implementation of the libp2p multistream
+ */
+
+/**
+ * Write to an open multistream host
+ * @param socket_fd the socket file descriptor
+ * @param data the data to send
+ * @param data_length the length of the data
+ * @returns the number of bytes written
+ */
+int libp2p_net_multistream_send(int socket_fd, const unsigned char* data, size_t data_length);
+/**
+ * Read from a multistream socket
+ * @param socket_fd the socket file descriptor
+ * @param results where to put the results. NOTE: this memory is allocated
+ * @param results_size the size of the results in bytes
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_net_multistream_receive(int socket_fd, char** results, size_t* results_size);
+
+/**
+ * Connect to a multistream host, and this includes the multistream handshaking.
+ * @param hostname the host
+ * @param port the port
+ * @returns the socket file descriptor of the connection, or -1 on error
+ */
+int libp2p_net_multistream_connect(const char* hostname, int port);
diff --git a/include/libp2p/net/p2pnet.h b/include/libp2p/net/p2pnet.h
new file mode 100644
index 0000000..57b0646
--- /dev/null
+++ b/include/libp2p/net/p2pnet.h
@@ -0,0 +1,37 @@
+#ifndef P2PNET_H
+#define P2PNET_H
+
+#include
+
+ int socket_open4();
+ int socket_bind4(int s, uint32_t ip, uint16_t port);
+ int socket_bind4_reuse(int s, uint32_t ip, uint16_t port);
+ int socket_accept4(int s, uint32_t *ip, uint16_t *port);
+ int socket_local4(int s, uint32_t *ip, uint16_t *port);
+ int socket_connect4(int s, uint32_t ip, uint16_t port);
+ int socket_listen(int s, uint32_t *localip, uint16_t *localport);
+ ssize_t socket_read(int s, char *buf, size_t len, int flags);
+ ssize_t socket_write(int s, char *buf, size_t len, int flags);
+ /**
+ * Used to send the size of the next transmission for "framed" transmissions. NOTE: This will send in big endian format
+ * @param s the socket descriptor
+ * @param size the size to send
+ * @param flags socket flags
+ * @returns number of bytes sent
+ */
+ ssize_t socket_write_size(int s, unsigned long size, int flags);
+
+ int socket_tcp4(void);
+
+ int socket_stream_sctp4(void);
+
+ int socket_udp4(void);
+
+ /**
+ * convert a hostname into an ip address
+ * @param hostname the name of the host. i.e. www.jmjatlanta.com
+ * @returns the ip address as an uint32_t
+ */
+ uint32_t hostname_to_ip(const char* hostname);
+
+#endif // P2PNET_H
diff --git a/include/libp2p/secio/propose.h b/include/libp2p/secio/propose.h
index ca31180..3762c4d 100644
--- a/include/libp2p/secio/propose.h
+++ b/include/libp2p/secio/propose.h
@@ -23,7 +23,7 @@ void libp2p_secio_propose_free(struct Propose* in);
* @param from_size the size of from
* @returns true(1) on success, otherwise false(0)
*/
-int libp2p_secio_propose_set_property(void** to, size_t* to_size, void* from, size_t from_size);
+int libp2p_secio_propose_set_property(void** to, size_t* to_size, const void* from, size_t from_size);
/**
* retrieves the approximate size of an encoded version of the passed in struct
diff --git a/include/libp2p/secio/secio.h b/include/libp2p/secio/secio.h
index 6dc669e..878e1fc 100644
--- a/include/libp2p/secio/secio.h
+++ b/include/libp2p/secio/secio.h
@@ -1,13 +1,29 @@
#pragma once
#include "libp2p/crypto/key.h"
+#include "libp2p/crypto/rsa.h"
/**
* A secure connection
*/
+enum IPTrafficType { TCP, UDP };
+
struct SecureSession {
+ // to get the connection started
+ char* host;
+ int port;
+ enum IPTrafficType traffic_type;
+ // once the connection is established
int socket_descriptor;
struct PublicKey remote_key;
- int remote_peer_id;
+ char* remote_peer_id;
};
+
+/***
+ * performs initial communication over an insecure channel to share
+ * keys, IDs, and initiate connection. This is a framed messaging system
+ * @param session the secure session to be filled
+ * @returns true(1) on success, false(0) otherwise
+ */
+int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey* private_key);
diff --git a/net/Makefile b/net/Makefile
new file mode 100644
index 0000000..5e9e63e
--- /dev/null
+++ b/net/Makefile
@@ -0,0 +1,18 @@
+CC = gcc
+CFLAGS = -O0 -Wall -I../include -I../../c-protobuf
+
+ifdef DEBUG
+CFLAGS += -g3
+endif
+
+LFLAGS =
+DEPS =
+OBJS = sctp.o socket.o tcp.o udp.o multistream.o
+
+%.o: %.c $(DEPS)
+ $(CC) -c -o $@ $< $(CFLAGS)
+
+all: $(OBJS)
+
+clean:
+ rm -f *.o
diff --git a/net/multistream.c b/net/multistream.c
new file mode 100644
index 0000000..2214763
--- /dev/null
+++ b/net/multistream.c
@@ -0,0 +1,117 @@
+#include
+#include
+
+#include "libp2p/net/p2pnet.h"
+#include "varint.h"
+
+/***
+ * An implementation of the libp2p multistream
+ */
+
+/**
+ * Write to an open multistream host
+ * @param socket_fd the socket file descriptor
+ * @param data the data to send
+ * @param data_length the length of the data
+ * @returns the number of bytes written
+ */
+int libp2p_net_multistream_send(int socket_fd, const unsigned char* data, size_t data_length) {
+ int num_bytes = 0;
+
+ if (data_length > 0) { // only do this is if there is something to send
+ // first send the size
+ unsigned char varint[12];
+ size_t varint_size = 0;
+ varint_encode(data_length, &varint[0], 12, &varint_size);
+ num_bytes = socket_write(socket_fd, (char*)varint, varint_size, 0);
+ if (num_bytes == 0)
+ return 0;
+ // then send the actual data
+ num_bytes += socket_write(socket_fd, (char*)data, data_length, 0);
+ }
+
+ return num_bytes;
+}
+
+/***
+ * Parse the incoming data, removing the size indicator at the front of the array
+ * @param incoming the incoming data
+ * @param incoming_size the size of the incoming data
+ * @param outgoing the buffer to hold the outgoing data, allocated within this function
+ * @param outgoing_size the outgoing size
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_net_multistream_parse_results(char* incoming, size_t incoming_size, char** outgoing, size_t* outgoing_size) {
+ int retVal = 0;
+ if (incoming_size > 0) {
+ // TODO: handle this differently
+ // read the varint
+ // allocate memory
+ *outgoing = (char*)malloc(incoming_size - 1);
+ if (*outgoing == NULL)
+ return 0;
+ // copy in the data
+ memcpy(*outgoing, &incoming[1], incoming_size - 1);
+ *outgoing_size = incoming_size - 1;
+ retVal = 1;
+ }
+ return retVal;
+}
+
+/**
+ * Read from a multistream socket
+ * @param socket_fd the socket file descriptor
+ * @param results where to put the results. NOTE: this memory is allocated
+ * @param results_size the size of the results in bytes
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_net_multistream_receive(int socket_fd, char** results, size_t* results_size) {
+ int bytes = 0;
+ size_t buffer_size = 65535;
+ char buffer[buffer_size];
+
+ bytes = socket_read(socket_fd, buffer, buffer_size, 0);
+ if (bytes == 0)
+ return 0;
+
+ // parse the results, removing the leading size indicator
+ return libp2p_net_multistream_parse_results(buffer, bytes, results, results_size);
+}
+
+
+/**
+ * Connect to a multistream host, and this includes the multistream handshaking.
+ * @param hostname the host
+ * @param port the port
+ * @returns the socket file descriptor of the connection, or -1 on error
+ */
+int libp2p_net_multistream_connect(const char* hostname, int port) {
+ int retVal = -1, socket = -1;
+ char* results = NULL;
+ size_t results_size;
+ size_t num_bytes = 0;
+
+ uint32_t ip = hostname_to_ip(hostname);
+ socket = socket_open4();
+
+ // connect
+ if (socket_connect4(socket, ip, port) != 0)
+ goto exit;
+
+ // try to receive the protocol id
+ retVal = libp2p_net_multistream_receive(socket, &results, &results_size);
+
+ // send the multistream handshake
+ const char* protocol_buffer = "/multistream/1.0.0\n";
+
+ num_bytes = libp2p_net_multistream_send(socket, (const unsigned char*)protocol_buffer, strlen(protocol_buffer));
+ if (num_bytes <= 0)
+ goto exit;
+
+ retVal = socket;
+ exit:
+ if (results != NULL)
+ free(results);
+ return retVal;
+}
+
diff --git a/net/p2pnet.h b/net/p2pnet.h
deleted file mode 100644
index a11e025..0000000
--- a/net/p2pnet.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef P2PNET_H
- #define P2PNET_H
-
- int socket_bind4(int s, uint32_t ip, uint16_t port);
- int socket_bind4_reuse(int s, uint32_t ip, uint16_t port);
- int socket_accept4(int s, uint32_t *ip, uint16_t *port);
- int socket_local4(int s, uint32_t *ip, uint16_t *port);
- int socket_connect4(int s, uint32_t ip, uint16_t port);
- int socket_listen(int s, uint32_t *localip, uint16_t *localport);
- ssize_t socket_read(int s, char *buf, size_t len, int flags);
- ssize_t socket_write(int s, char *buf, size_t len, int flags);
-
- int socket_tcp4(void);
-
- int socket_stream_sctp4(void);
-
- int socket_udp4(void);
-#endif // P2PNET_H
diff --git a/net/sctp.c b/net/sctp.c
index 0ebbe7a..827ded8 100644
--- a/net/sctp.c
+++ b/net/sctp.c
@@ -1,7 +1,7 @@
#include
#include
#include
-#include "p2pnet.h"
+#include "libp2p/net/p2pnet.h"
/* Create a SCTP socket.
*/
diff --git a/net/socket.c b/net/socket.c
index 7c7f476..c22ad7a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -3,8 +3,11 @@
#include
#include
#include
+#include
#include
-#include "p2pnet.h"
+#include
+
+#include "libp2p/net/p2pnet.h"
/* associate an IP address with an port to a socket.
* first param is the socket file description
@@ -64,7 +67,12 @@ int socket_local4(int s, uint32_t *ip, uint16_t *port)
return 0;
}
-/* start a client connection.
+/***
+ * start a client connection.
+ * @param s the socket number
+ * @param ip the ip address
+ * @param port the port number
+ * @return 0 on success, otherwise -1
*/
int socket_connect4(int s, uint32_t ip, uint16_t port)
{
@@ -112,3 +120,83 @@ ssize_t socket_write(int s, char *buf, size_t len, int flags)
{
return send(s, buf, len, flags);
}
+
+int socket_open4() {
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ return sockfd;
+}
+
+/**
+ * Used to send the size of the next transmission for "framed" transmissions. NOTE: This will send in big endian format
+ * @param s the socket descriptor
+ * @param size the size to send
+ * @param flags socket flags
+ * @returns number of bytes sent
+ */
+ssize_t socket_write_size(int s, unsigned long size, int flags) {
+ // determine if we're big or little endian
+ int big_endian = 1;
+ if (*(char*)&big_endian == 1) {
+ big_endian = 0;
+ }
+ // convert to int32_t
+ int32_t conv = htonl(size);
+ // swap bytes if this machine is little endian
+ if (!big_endian) {
+ uint32_t b0, b1, b2, b3;
+ b0 = (conv & 0x000000ff) << 24u;
+ b1 = (conv & 0x0000ff00) << 8u;
+ b2 = (conv & 0x00ff0000) >> 8u;
+ b3 = (conv & 0xff000000) >> 24u;
+ conv = b0 | b1 | b2 | b3;
+ }
+
+ // send to socket
+ char* data = (char*)&conv;
+ int left = sizeof(conv);
+ ssize_t rc;
+ int retries_left = 100;
+ do {
+ rc = send(s, data, left, flags);
+ if (rc < 0) {
+ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+ retries_left--;
+ if (retries_left <= 0)
+ break;
+ } else {
+ return -1;
+ }
+ } else {
+ data += rc;
+ left -= rc;
+ }
+ } while (left > 0);
+ return sizeof(conv) - left;
+ //return send(s, size, 4, flags);
+}
+
+
+/**
+ * convert a hostname into an ip address
+ * @param hostname the name of the host. i.e. www.jmjatlanta.com
+ * @returns the ip address as an uint32_t
+ */
+uint32_t hostname_to_ip(const char* hostname)
+{
+ struct hostent *he;
+ struct in_addr **addr_list;
+
+ if ( (he = gethostbyname( hostname ) ) == NULL)
+ {
+ // get the host info
+ herror("gethostbyname");
+ return 1;
+ }
+
+ addr_list = (struct in_addr **) he->h_addr_list;
+ if ((*addr_list) == NULL)
+ return 0;
+
+ return addr_list[0]->s_addr;
+}
diff --git a/net/tcp.c b/net/tcp.c
index 7ab51a9..3206ceb 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -1,7 +1,7 @@
#include
#include
#include
-#include "p2pnet.h"
+#include "libp2p/net/p2pnet.h"
/* Create a TCP socket.
*/
diff --git a/net/udp.c b/net/udp.c
index 08dab8d..4985196 100644
--- a/net/udp.c
+++ b/net/udp.c
@@ -1,7 +1,7 @@
#include
#include
#include
-#include "p2pnet.h"
+#include "libp2p/net/p2pnet.h"
/* Create a UDP socket.
*/
diff --git a/secio/propose.c b/secio/propose.c
index d95c342..ef7ee8d 100644
--- a/secio/propose.c
+++ b/secio/propose.c
@@ -32,7 +32,7 @@ void libp2p_secio_propose_free( struct Propose* in) {
}
}
-int libp2p_secio_propose_set_property(void** to, size_t* to_size, void* from, size_t from_size) {
+int libp2p_secio_propose_set_property(void** to, size_t* to_size, const void* from, size_t from_size) {
if (*to != NULL)
free(*to);
*to = (void*)malloc(from_size);
diff --git a/secio/secio.c b/secio/secio.c
index 8d794d2..387e2ed 100644
--- a/secio/secio.c
+++ b/secio/secio.c
@@ -1,8 +1,10 @@
#include
#include
+#include
#include "libp2p/secio/secio.h"
#include "libp2p/secio/propose.h"
+#include "libp2p/net/p2pnet.h"
const char* SupportedExchanges = "P-256,P-384,P-521";
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
@@ -29,56 +31,104 @@ void libp2p_secio_secure_session_free(struct SecureSession* in) {
free(in);
}
+/**
+ * Generate a random nonce
+ * @param results where to put the results
+ * @param length the length of the nonce
+ * @returns true(1) on success, otherwise false(0)
+ */
+int libp2p_secio_generate_nonce(char* results, int length) {
+ results = "abcdefghijklmno";
+ return 1;
+}
+
/***
* performs initial communication over an insecure channel to share
* keys, IDs, and initiate connection. This is a framed messaging system
* @param session the secure session to be filled
* @returns true(1) on success, false(0) otherwise
*/
-int libp2p_secio_secure_session_handshake(struct SecureSession* session, struct RsaPrivateKey* private_key) {
- int retVal = 0, protobuf_size = 0, results_size = 0;
- unsigned char* protobuf = 0;;
- unsigned char* results;
- struct Propose* propose = NULL;
- struct SocketMuxer* socketMuxer;
+int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey* private_key) {
+ int retVal = 0, results_size = 65535, bytes_written = 0;
+ size_t protobuf_size = 0;
+ unsigned char* protobuf = 0;
+ unsigned char results[results_size];
+ struct Propose* propose_out = NULL;
+ struct Propose* propose_in = NULL;
+ struct PublicKey* public_key = NULL;
+ uint32_t ip;
+ int socket;
// generate 16 byte nonce
char nonceOut[16];
- if (!generateNonce(&nonceOut, 16)) {
+ if (!libp2p_secio_generate_nonce(&nonceOut[0], 16)) {
goto exit;
}
- propose = libp2p_secio_propose_new();
- libp2p_secio_propose_set_property(&propose->rand, &propose->rand_size, nonceOut, 16);
+ propose_out = libp2p_secio_propose_new();
+ libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, nonceOut, 16);
// will need:
// TODO: public key
// supported exchanges
- libp2p_secio_propose_set_property(&propose->exchanges, &propose->exchanges_size, SupportedExchanges, strlen(SupportedExchanges));
+ libp2p_secio_propose_set_property((void**)&propose_out->exchanges, &propose_out->exchanges_size, SupportedExchanges, strlen(SupportedExchanges));
// supported ciphers
- libp2p_secio_propose_set_property(&propose->ciphers, &propose->ciphers_size, SupportedCiphers, strlen(SupportedCiphers));
+ libp2p_secio_propose_set_property((void**)&propose_out->ciphers, &propose_out->ciphers_size, SupportedCiphers, strlen(SupportedCiphers));
// supported hashes
- libp2p_secio_propose_set_property(&propose->hashes, &propose->exchanges_size, SupportedHashes, strlen(SupportedHashes));
+ libp2p_secio_propose_set_property((void**)&propose_out->hashes, &propose_out->exchanges_size, SupportedHashes, strlen(SupportedHashes));
// send request (protobuf, then send)
- protobuf_size = libp2p_secio_propose_protobuf_encode_size(propose);
+ protobuf_size = libp2p_secio_propose_protobuf_encode_size(propose_out);
protobuf = (unsigned char*) malloc(protobuf_size);
if (protobuf == NULL)
goto exit;
- if (!libp2p_secio_propose_protobuf_encode(propose, protobuf, protobuf_size, &protobuf_size))
+ if (!libp2p_secio_propose_protobuf_encode(propose_out, protobuf, protobuf_size, &protobuf_size))
goto exit;
- libp2p_secio_propose_free(propose);
- if (!libp2p_net_socket_muxer_send(socketMuxer, protobuf, protobuf_size))
+ ip = hostname_to_ip(session->host);
+ socket = socket_open4();
+ // connect
+ if (socket_connect4(socket, ip, session->port) != 0)
+ goto exit;
+
+ // try 1
+ // first try to send mulitstream line
+ char buf[21];
+ buf[0] = 23;
+ strcpy(&buf[1], "/multistream/1.0.0\n");
+ bytes_written = socket_write_size(socket, 20, sizeof(uint32_t));
+ if (bytes_written != 4)
+ goto exit;
+ bytes_written = socket_write(socket, buf, 20, 0);
+ if (bytes_written != 20)
+ goto exit;
+ // check to see what was written back...
+ bytes_written = socket_read(socket, (char*)&results[0], results_size, 0);
+ if (bytes_written == 65535)
+ goto exit;
+ // end of try 1
+
+ // send struct Propose in protobuf format
+ bytes_written = socket_write_size(socket, protobuf_size, sizeof(uint32_t));
+ if (bytes_written != 4)
+ goto exit;
+ bytes_written = socket_write(socket, (char*)protobuf, protobuf_size, 0);
+ if (bytes_written != protobuf_size)
goto exit;
// receive response (turn back into a Propose struct)
- if (!libp2p_net_socket_muxer_receive(socketMuxer, &results, &results_size))
+ bytes_written = socket_read(socket, (char*)&results[0], results_size, 0);
+ if (bytes_written == 65535)
goto exit;
- if (!libp2p_secio_propose_protobuf_decode(results, results_size, &propose))
+
+ if (!libp2p_secio_propose_protobuf_decode(results, results_size, &propose_in))
goto exit;
// get public key
+ if (!libp2p_crypto_public_key_protobuf_decode(propose_in->public_key, propose_in->public_key_size, &public_key))
+ goto exit;
// generate their peer id
+ char* remote_peer_id;
+ libp2p_crypto_public_key_to_peer_id(public_key, &remote_peer_id);
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
// curve
@@ -101,7 +151,8 @@ int libp2p_secio_secure_session_handshake(struct SecureSession* session, struct
exit:
- ipfs_secio_propose_free(propose);
+ libp2p_secio_propose_free(propose_out);
+ libp2p_secio_propose_free(propose_in);
if (protobuf != NULL)
free(protobuf);
diff --git a/test/Makefile b/test/Makefile
index 37300d6..52d6cde 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -7,7 +7,7 @@ endif
LFLAGS = -L../ -L../../c-multihash
DEPS = crypto/test_base58.h crypto/test_rsa.h test_mbedtls.h
-OBJS = testit.o
+OBJS = testit.o ../../c-protobuf/protobuf.o ../../c-protobuf/varint.o ../libp2p.a
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
diff --git a/test/crypto/test_key.h b/test/crypto/test_key.h
index 65b72be..2657865 100644
--- a/test/crypto/test_key.h
+++ b/test/crypto/test_key.h
@@ -8,31 +8,30 @@ int test_protobuf_private_key() {
size_t decode_base64_size = 0;
unsigned char* decode_base64;
// this is a base64 encoded private key. It makes it easier to test if it is in base64 form
- char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQDTDJBWjDzS/HxDNOHazvzH2bu9CPMVHUrrvKRdBUM5ansL6/CC3MVZ6HVm4O6QHRapN6EF2CbrTgI4KBOXIL125Xo8MlROnyfXYk3O5q2tgwL/MbW8kXjtkyCfBak7MUoLOdLU7Svg0gkl3l+uDAiDcCLnwJVcFfq9ch6z4wMOhYJqE5dtx0uXxn6IuKWl1B69FTvBXCc0thw8Rw54b941FDcsBH5ttV9mRNCJym3poZ5qalNgXlxoIIB+PUx5QD+aq7KMJdpAX8HkapBntCOahP/QUceRmma0grlZLeYkH6/oi/hIrM6se3KUZ+F6tBuDFys8UAZy/X2BCUbKjbxtAgMBAAECggEANWfQfpYuLhXGPBt9q6kFPm1SnJtPJ+CpvM2XqhJS2IyhZnrl+bd0GTRBwS7aL42s1lVFYf04nAK5fQxnKK8YQqX/MIxr2RldM5ukpN6qxGWKtJkXrAgD2dqJPrRoBpqKahzPxSHfIJ0Fw5dqDtjsrpYJvyt0oEDPmnDuZAbmFx4sJqnesPNhKxtRMBx1+yxGVuRVJjHcqAgqPqwNiuoMEaYMY+G9yzT6vza8ovCpbX7BBIgM5fAT9PD8TBG//Vu9THvj/ZomiVG2qv6RL0qQyVb+DUzPZz1amBsSvahtXCl72jA3JwAZ943RxSR66P934S0ashkVwLUi46z/EAbJ4QKBgQDojGIO07BEVL2+7VxlGL9XGZQp4Y3qlhh2zDDQGwkCq/KQ+BdNYWitPwqRl9GqFLgpmeQIhyHTOa/IThx+AXGKVQ24ROH+skUs4IbO6R3qY7BKtb5lkZE/Yln09x70BBngUYAzh/rtnsXO3cl1x2XDDqUbCwlGcDAs8Jh/6UnvQwKBgQDoVSQs7Uq9MJCGIUM2bixX89tHzSxq5mn9wMD3/XRVfT5Ua8YkYBuzcmlcT39N7L5BwuyFqX3Vi7lv/Ya/qaQP6XkrZ8W1OAaTlYewfE5ZgknJqSpXcNWhABKeNmqndvqyQ/8HNCv/j8AdraGB2DGO57Xso5J0CQ43W/U9+QIyjwKBgHLL2hw3o+wXaRO3WMUPUmVM2zdRgR0suybp5a7Vqb0H5NZrohUw4NulIzJ8H6Q2VjMzJL6Q9sGu2HepF6ecTtBa7ErqtiVlG4Dr1aCOs5XhYEWBMlwxX+JKSt4Cn+UVoTB7Cy5lEhn7JurX0Xuy0ylXMWoIKKv89cs5eg6quzTBAoGAaq9eEztLjKCWXOE9SetBdYnG8aunb9cqaJlwgu/h0bfXPVDYBbAUSEyLURY4MQI7Q1tM3Pu9iqfEmUZj7/LoIV5mg6X9RX/alT6etk3+dF+9nlqN1OU9U9cCtZ/rTcb2y5EptJcidRH/eCFY/pTV/PcttOJPx/S4kHcroC+N8MUCgYEA6DA5QHxHfNN6Nxv+pEzy2DIxFe9RrBxS+KPBsra1C8jgdeMf4EmfU0Nox92V0q0bRrD5ztqQwSONI0hSRb1iiMWR6MuFnAFajUJfASjjIlZ6nIQjQslI7vjlvYyyHS/p/Codxap+yJlTLWwVEOXp2D9pWwiMq1xEyf0TH1BosvM=";
+ // these were pulled from the GO version of ipfs
+ char* orig_priv_key = "CAASqgkwggSmAgEAAoIBAQD0a4RI+bF/ov7IVOGSJ8dQfnK1DwM0gwVuJAd+3LXxIZEPZzsKIKia0TojDbTdLvOJ23wsaojTF/4bSzBK5otdAz8YSgez4vTRUV5pUqvCkK0dSJJ1DHTdrFUwvzlXuKbwNbvWyzjmKfeaE9a9YLzhrUIUTRvKyqhZXr++vMy3hw4fdtGUTJWeiqmoIuJWIZ1748Ff6LjcP7TdG7OvY4q+U9ilEJYdF4aM+TJY193zKp0GNWohunuVrtOUnL9VQaSSDbvGdFS1Mg9iCN6kRBQTHVQvFzvuEw/Y2LvoPH3yFG1zj6bDLWfOBhegy/6Zi6fi4E1UfgJNFN1sjWF+gZoHAgMBAAECggEBALTqBD9zuoMsJYQo99IT6X7WKZeE5i1vMYzF1Fp9iZpS6ylIkrW7WLFHXs3lblMtVoxazn2d2WrOXoLbU4KNROhy57fVy//FZMqufMBetc3NAqYjOmyy7KnLzj7Hu+0HO2GflEq3n4UV2TTNrGv+d7BfawLV1FV1TcjgzfKjkq/gMDCTPMgfT7lcF4TGSqv6Pgudp8RRn/R7EKOx+I8/XkJsZWP3XJ0zj4ciqDmKrX2j7wZMT8CH/8wfyg4NGk1+TN4xBB2CXgulIWJg5yhzu+JgbGnHEL/Ga+i40XJe+RnlKDpjQ+ZFyrOkmHpIldasjWNGFeKwLjzrDQfyDRwex5ECgYEA+fFGJ+zbi2YJwHDO/44PmvcoCWpho0ah7y+O5/LEVROTYEoNRqodLet+z+LMKDq/o2qTNaYJLiDGMBZzhqyJIFR5ZJ5MhgLloY1gL8s0a7KMWDbh7giiWSu5zqhB3Du8Tom+8bYZUxOL4zhzCGrFitRqiEIIjy1/c5qyRQZaZx8CgYEA+lf6tdO6kKiAOxm7sdZ3rEl4UGFY+tEqgivKwurLRIor0XDfhCKr1hCfsZggpR8SMLfjCuNEgKbceofcKMa8OtyDbMPRz0mYNkCELTUYA+r8Ib/LvleQApMcLn+TDNwEnGlglSrrF33RVAUK+i/WfSXUvZRVpLQpRmdAqHjJeBkCgYEA0+Zz/iFXOGW32slJFWxRWqYz8VeZk52saGY/l/I/9Yj1J2tgugo7VtUS3BiB0ZGNK3SNfaxYmBz9KYO/Sew5DYnQqTdz1SHboQ2FAMAcnznutlNBVFdJnKPvkX8g5yBV05gApFgoPECUFn2jOP2coMjZ0M97Bjgil9YNUWvDdS0CgYEA4beFs3+tzVRAGgl/tD7dNBgiRMchBTSmkSuO6+PrVmcGTxboUSk5qg7fDa9Ob9LuAcMrENwNHbpVPJ1WoeVePewpC14bxDxk4zWUd3ZRquaqYnud5obor4mYdUxNd+DAv447qQNDaLDmlkzdsuqDB9+eSzh9Z72RIYtjPwN5E7ECgYEAsbqkMZXfK1tTRfduX+7KOlPMfcSr29X6nuDglcna4dHec6FAOzp3xL2722nnFt6gygc7pErrm0m0Wd/6BMTb4T3+GYwkDiMjM2CsTZYjpzrUri/VfRR509rScxHVR0/1PTFWN0K0+VZbEAyXDbbs4opq40tW0dWtcKxaNlimMw8=";
struct PrivateKey* private_key = libp2p_crypto_private_key_new();
struct RsaPrivateKey rsa_private_key = {0};
+ char* orig_peer_id = "QmbTyKkUuv6yaSpTuCFq1Ft6Q3g4wTtFJk1BLGMPRdAEP8";
+ size_t orig_peer_id_size = strlen(orig_peer_id);
+ unsigned char hashed[32];
+ size_t final_id_size = 1600;
+ unsigned char final_id[final_id_size];
- // convert from base64
// 1) take the private key and turn it back into bytes (decode base 64)
decode_base64_size = libp2p_crypto_encoding_base64_decode_size(strlen(orig_priv_key));
decode_base64 = (unsigned char*)malloc(decode_base64_size);
memset(decode_base64, 0, decode_base64_size);
- int retVal = libp2p_crypto_encoding_base64_decode((unsigned char*)orig_priv_key, strlen(orig_priv_key), &decode_base64[0], decode_base64_size, &decode_base64_size);
- if (retVal == 0)
+ if (!libp2p_crypto_encoding_base64_decode((unsigned char*)orig_priv_key, strlen(orig_priv_key), &decode_base64[0], decode_base64_size, &decode_base64_size))
goto exit;
- // the first 5 bytes [0-4] are protobuf metadata before the DER encoded private key
- // byte 0 is "Tag 1 which is a varint"
- // byte 1 is the value of the varint
- // byte 2 is "Tag 2 which is a type 2, length delimited field"
- // bytes 3 & 4 is a varint with the value of 1191, which is the number of bytes that follow
-
if (!libp2p_crypto_private_key_protobuf_decode(decode_base64, decode_base64_size, &private_key))
goto exit;
- // 2) take the bytes of the private key and turn it back into a private key struct
+ // 2) take the bytes of the private key and turn it back into an RSA private key struct
+ //TODO: should verify that this key is RSA
if (!libp2p_crypto_encoding_x509_der_to_private_key(private_key->data, private_key->data_size, &rsa_private_key))
goto exit;
@@ -41,10 +40,7 @@ int test_protobuf_private_key() {
goto exit;
// 3) grab the public key, hash it, then base58 it
- unsigned char hashed[32];
ID_FromPK_non_null_terminated((char*)hashed, (unsigned char*)rsa_private_key.public_key_der, rsa_private_key.public_key_length);
- size_t final_id_size = 1600;
- unsigned char final_id[final_id_size];
memset(final_id, 0, final_id_size);
if (!PrettyID(final_id, &final_id_size, hashed, 32))
goto exit;
diff --git a/test/crypto/test_rsa.h b/test/crypto/test_rsa.h
index e8098af..8b9054b 100644
--- a/test/crypto/test_rsa.h
+++ b/test/crypto/test_rsa.h
@@ -8,7 +8,7 @@
#include "libp2p/crypto/rsa.h"
#include "libp2p/crypto/encoding/base64.h"
#include "libp2p/crypto/encoding/x509.h"
-#include "libp2p/peerutils.h"
+#include "libp2p/crypto/peerutils.h"
/**
@@ -123,9 +123,11 @@ int test_public_der_to_private_der() {
int test_crypto_rsa_public_key_to_peer_id() {
// this is the base64 encoded private key from the config file
- char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQDTDJBWjDzS/HxDNOHazvzH2bu9CPMVHUrrvKRdBUM5ansL6/CC3MVZ6HVm4O6QHRapN6EF2CbrTgI4KBOXIL125Xo8MlROnyfXYk3O5q2tgwL/MbW8kXjtkyCfBak7MUoLOdLU7Svg0gkl3l+uDAiDcCLnwJVcFfq9ch6z4wMOhYJqE5dtx0uXxn6IuKWl1B69FTvBXCc0thw8Rw54b941FDcsBH5ttV9mRNCJym3poZ5qalNgXlxoIIB+PUx5QD+aq7KMJdpAX8HkapBntCOahP/QUceRmma0grlZLeYkH6/oi/hIrM6se3KUZ+F6tBuDFys8UAZy/X2BCUbKjbxtAgMBAAECggEANWfQfpYuLhXGPBt9q6kFPm1SnJtPJ+CpvM2XqhJS2IyhZnrl+bd0GTRBwS7aL42s1lVFYf04nAK5fQxnKK8YQqX/MIxr2RldM5ukpN6qxGWKtJkXrAgD2dqJPrRoBpqKahzPxSHfIJ0Fw5dqDtjsrpYJvyt0oEDPmnDuZAbmFx4sJqnesPNhKxtRMBx1+yxGVuRVJjHcqAgqPqwNiuoMEaYMY+G9yzT6vza8ovCpbX7BBIgM5fAT9PD8TBG//Vu9THvj/ZomiVG2qv6RL0qQyVb+DUzPZz1amBsSvahtXCl72jA3JwAZ943RxSR66P934S0ashkVwLUi46z/EAbJ4QKBgQDojGIO07BEVL2+7VxlGL9XGZQp4Y3qlhh2zDDQGwkCq/KQ+BdNYWitPwqRl9GqFLgpmeQIhyHTOa/IThx+AXGKVQ24ROH+skUs4IbO6R3qY7BKtb5lkZE/Yln09x70BBngUYAzh/rtnsXO3cl1x2XDDqUbCwlGcDAs8Jh/6UnvQwKBgQDoVSQs7Uq9MJCGIUM2bixX89tHzSxq5mn9wMD3/XRVfT5Ua8YkYBuzcmlcT39N7L5BwuyFqX3Vi7lv/Ya/qaQP6XkrZ8W1OAaTlYewfE5ZgknJqSpXcNWhABKeNmqndvqyQ/8HNCv/j8AdraGB2DGO57Xso5J0CQ43W/U9+QIyjwKBgHLL2hw3o+wXaRO3WMUPUmVM2zdRgR0suybp5a7Vqb0H5NZrohUw4NulIzJ8H6Q2VjMzJL6Q9sGu2HepF6ecTtBa7ErqtiVlG4Dr1aCOs5XhYEWBMlwxX+JKSt4Cn+UVoTB7Cy5lEhn7JurX0Xuy0ylXMWoIKKv89cs5eg6quzTBAoGAaq9eEztLjKCWXOE9SetBdYnG8aunb9cqaJlwgu/h0bfXPVDYBbAUSEyLURY4MQI7Q1tM3Pu9iqfEmUZj7/LoIV5mg6X9RX/alT6etk3+dF+9nlqN1OU9U9cCtZ/rTcb2y5EptJcidRH/eCFY/pTV/PcttOJPx/S4kHcroC+N8MUCgYEA6DA5QHxHfNN6Nxv+pEzy2DIxFe9RrBxS+KPBsra1C8jgdeMf4EmfU0Nox92V0q0bRrD5ztqQwSONI0hSRb1iiMWR6MuFnAFajUJfASjjIlZ6nIQjQslI7vjlvYyyHS/p/Codxap+yJlTLWwVEOXp2D9pWwiMq1xEyf0TH1BosvM=";
+ //char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQDTDJBWjDzS/HxDNOHazvzH2bu9CPMVHUrrvKRdBUM5ansL6/CC3MVZ6HVm4O6QHRapN6EF2CbrTgI4KBOXIL125Xo8MlROnyfXYk3O5q2tgwL/MbW8kXjtkyCfBak7MUoLOdLU7Svg0gkl3l+uDAiDcCLnwJVcFfq9ch6z4wMOhYJqE5dtx0uXxn6IuKWl1B69FTvBXCc0thw8Rw54b941FDcsBH5ttV9mRNCJym3poZ5qalNgXlxoIIB+PUx5QD+aq7KMJdpAX8HkapBntCOahP/QUceRmma0grlZLeYkH6/oi/hIrM6se3KUZ+F6tBuDFys8UAZy/X2BCUbKjbxtAgMBAAECggEANWfQfpYuLhXGPBt9q6kFPm1SnJtPJ+CpvM2XqhJS2IyhZnrl+bd0GTRBwS7aL42s1lVFYf04nAK5fQxnKK8YQqX/MIxr2RldM5ukpN6qxGWKtJkXrAgD2dqJPrRoBpqKahzPxSHfIJ0Fw5dqDtjsrpYJvyt0oEDPmnDuZAbmFx4sJqnesPNhKxtRMBx1+yxGVuRVJjHcqAgqPqwNiuoMEaYMY+G9yzT6vza8ovCpbX7BBIgM5fAT9PD8TBG//Vu9THvj/ZomiVG2qv6RL0qQyVb+DUzPZz1amBsSvahtXCl72jA3JwAZ943RxSR66P934S0ashkVwLUi46z/EAbJ4QKBgQDojGIO07BEVL2+7VxlGL9XGZQp4Y3qlhh2zDDQGwkCq/KQ+BdNYWitPwqRl9GqFLgpmeQIhyHTOa/IThx+AXGKVQ24ROH+skUs4IbO6R3qY7BKtb5lkZE/Yln09x70BBngUYAzh/rtnsXO3cl1x2XDDqUbCwlGcDAs8Jh/6UnvQwKBgQDoVSQs7Uq9MJCGIUM2bixX89tHzSxq5mn9wMD3/XRVfT5Ua8YkYBuzcmlcT39N7L5BwuyFqX3Vi7lv/Ya/qaQP6XkrZ8W1OAaTlYewfE5ZgknJqSpXcNWhABKeNmqndvqyQ/8HNCv/j8AdraGB2DGO57Xso5J0CQ43W/U9+QIyjwKBgHLL2hw3o+wXaRO3WMUPUmVM2zdRgR0suybp5a7Vqb0H5NZrohUw4NulIzJ8H6Q2VjMzJL6Q9sGu2HepF6ecTtBa7ErqtiVlG4Dr1aCOs5XhYEWBMlwxX+JKSt4Cn+UVoTB7Cy5lEhn7JurX0Xuy0ylXMWoIKKv89cs5eg6quzTBAoGAaq9eEztLjKCWXOE9SetBdYnG8aunb9cqaJlwgu/h0bfXPVDYBbAUSEyLURY4MQI7Q1tM3Pu9iqfEmUZj7/LoIV5mg6X9RX/alT6etk3+dF+9nlqN1OU9U9cCtZ/rTcb2y5EptJcidRH/eCFY/pTV/PcttOJPx/S4kHcroC+N8MUCgYEA6DA5QHxHfNN6Nxv+pEzy2DIxFe9RrBxS+KPBsra1C8jgdeMf4EmfU0Nox92V0q0bRrD5ztqQwSONI0hSRb1iiMWR6MuFnAFajUJfASjjIlZ6nIQjQslI7vjlvYyyHS/p/Codxap+yJlTLWwVEOXp2D9pWwiMq1xEyf0TH1BosvM=";
+ char* orig_priv_key = "CAASqgkwggSmAgEAAoIBAQD0a4RI+bF/ov7IVOGSJ8dQfnK1DwM0gwVuJAd+3LXxIZEPZzsKIKia0TojDbTdLvOJ23wsaojTF/4bSzBK5otdAz8YSgez4vTRUV5pUqvCkK0dSJJ1DHTdrFUwvzlXuKbwNbvWyzjmKfeaE9a9YLzhrUIUTRvKyqhZXr++vMy3hw4fdtGUTJWeiqmoIuJWIZ1748Ff6LjcP7TdG7OvY4q+U9ilEJYdF4aM+TJY193zKp0GNWohunuVrtOUnL9VQaSSDbvGdFS1Mg9iCN6kRBQTHVQvFzvuEw/Y2LvoPH3yFG1zj6bDLWfOBhegy/6Zi6fi4E1UfgJNFN1sjWF+gZoHAgMBAAECggEBALTqBD9zuoMsJYQo99IT6X7WKZeE5i1vMYzF1Fp9iZpS6ylIkrW7WLFHXs3lblMtVoxazn2d2WrOXoLbU4KNROhy57fVy//FZMqufMBetc3NAqYjOmyy7KnLzj7Hu+0HO2GflEq3n4UV2TTNrGv+d7BfawLV1FV1TcjgzfKjkq/gMDCTPMgfT7lcF4TGSqv6Pgudp8RRn/R7EKOx+I8/XkJsZWP3XJ0zj4ciqDmKrX2j7wZMT8CH/8wfyg4NGk1+TN4xBB2CXgulIWJg5yhzu+JgbGnHEL/Ga+i40XJe+RnlKDpjQ+ZFyrOkmHpIldasjWNGFeKwLjzrDQfyDRwex5ECgYEA+fFGJ+zbi2YJwHDO/44PmvcoCWpho0ah7y+O5/LEVROTYEoNRqodLet+z+LMKDq/o2qTNaYJLiDGMBZzhqyJIFR5ZJ5MhgLloY1gL8s0a7KMWDbh7giiWSu5zqhB3Du8Tom+8bYZUxOL4zhzCGrFitRqiEIIjy1/c5qyRQZaZx8CgYEA+lf6tdO6kKiAOxm7sdZ3rEl4UGFY+tEqgivKwurLRIor0XDfhCKr1hCfsZggpR8SMLfjCuNEgKbceofcKMa8OtyDbMPRz0mYNkCELTUYA+r8Ib/LvleQApMcLn+TDNwEnGlglSrrF33RVAUK+i/WfSXUvZRVpLQpRmdAqHjJeBkCgYEA0+Zz/iFXOGW32slJFWxRWqYz8VeZk52saGY/l/I/9Yj1J2tgugo7VtUS3BiB0ZGNK3SNfaxYmBz9KYO/Sew5DYnQqTdz1SHboQ2FAMAcnznutlNBVFdJnKPvkX8g5yBV05gApFgoPECUFn2jOP2coMjZ0M97Bjgil9YNUWvDdS0CgYEA4beFs3+tzVRAGgl/tD7dNBgiRMchBTSmkSuO6+PrVmcGTxboUSk5qg7fDa9Ob9LuAcMrENwNHbpVPJ1WoeVePewpC14bxDxk4zWUd3ZRquaqYnud5obor4mYdUxNd+DAv447qQNDaLDmlkzdsuqDB9+eSzh9Z72RIYtjPwN5E7ECgYEAsbqkMZXfK1tTRfduX+7KOlPMfcSr29X6nuDglcna4dHec6FAOzp3xL2722nnFt6gygc7pErrm0m0Wd/6BMTb4T3+GYwkDiMjM2CsTZYjpzrUri/VfRR509rScxHVR0/1PTFWN0K0+VZbEAyXDbbs4opq40tW0dWtcKxaNlimMw8=";
// this is the peer id from the config file
- char* orig_peer_id = "QmRskXriTSRjAftYX7QG1i1jAhouz5AHaLYZKNhEWRu5Fq";
+ //char* orig_peer_id = "QmRskXriTSRjAftYX7QG1i1jAhouz5AHaLYZKNhEWRu5Fq";
+ char* orig_peer_id = "QmbTyKkUuv6yaSpTuCFq1Ft6Q3g4wTtFJk1BLGMPRdAEP8";
size_t orig_peer_id_size = strlen(orig_peer_id);
// if we take the private key, retrieve the public key, hash it, we should come up with the peer id
diff --git a/test/test_multistream.h b/test/test_multistream.h
new file mode 100644
index 0000000..82a086e
--- /dev/null
+++ b/test/test_multistream.h
@@ -0,0 +1,35 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "libp2p/net/multistream.h"
+
+int test_multistream_connect() {
+ int retVal = 0, socket_fd = -1;
+ char* response;
+ size_t response_size;
+
+ socket_fd = libp2p_net_multistream_connect("www.jmjatlanta.com", 4001);
+ if (socket_fd < 0)
+ goto exit;
+
+ // try to respond something, perhaps either the protocol id or the ls command
+ //const unsigned char* out = "/multistream/1.0.0\n";
+ const unsigned char* out = "ls";
+
+ if (libp2p_net_multistream_send(socket_fd, out, strlen((char*)out)) <= 0)
+ goto exit;
+
+ // retrieve response
+ retVal = libp2p_net_multistream_receive(socket_fd, &response, &response_size);
+ if (retVal <= 0)
+ goto exit;
+
+ retVal = 1;
+
+ exit:
+
+ return retVal > 0;
+}
diff --git a/test/test_secio.h b/test/test_secio.h
new file mode 100644
index 0000000..66e4701
--- /dev/null
+++ b/test/test_secio.h
@@ -0,0 +1,55 @@
+#include
+
+#include "libp2p/secio/secio.h"
+
+
+int test_secio_handshake() {
+ int retVal = 0;
+ size_t decode_base64_size = 0;
+ unsigned char* decode_base64;
+ // this is a base64 encoded private key. It makes it easier to test if it is in base64 form
+ // these were pulled from the GO version of ipfs
+ char* orig_priv_key = "CAASqgkwggSmAgEAAoIBAQD0a4RI+bF/ov7IVOGSJ8dQfnK1DwM0gwVuJAd+3LXxIZEPZzsKIKia0TojDbTdLvOJ23wsaojTF/4bSzBK5otdAz8YSgez4vTRUV5pUqvCkK0dSJJ1DHTdrFUwvzlXuKbwNbvWyzjmKfeaE9a9YLzhrUIUTRvKyqhZXr++vMy3hw4fdtGUTJWeiqmoIuJWIZ1748Ff6LjcP7TdG7OvY4q+U9ilEJYdF4aM+TJY193zKp0GNWohunuVrtOUnL9VQaSSDbvGdFS1Mg9iCN6kRBQTHVQvFzvuEw/Y2LvoPH3yFG1zj6bDLWfOBhegy/6Zi6fi4E1UfgJNFN1sjWF+gZoHAgMBAAECggEBALTqBD9zuoMsJYQo99IT6X7WKZeE5i1vMYzF1Fp9iZpS6ylIkrW7WLFHXs3lblMtVoxazn2d2WrOXoLbU4KNROhy57fVy//FZMqufMBetc3NAqYjOmyy7KnLzj7Hu+0HO2GflEq3n4UV2TTNrGv+d7BfawLV1FV1TcjgzfKjkq/gMDCTPMgfT7lcF4TGSqv6Pgudp8RRn/R7EKOx+I8/XkJsZWP3XJ0zj4ciqDmKrX2j7wZMT8CH/8wfyg4NGk1+TN4xBB2CXgulIWJg5yhzu+JgbGnHEL/Ga+i40XJe+RnlKDpjQ+ZFyrOkmHpIldasjWNGFeKwLjzrDQfyDRwex5ECgYEA+fFGJ+zbi2YJwHDO/44PmvcoCWpho0ah7y+O5/LEVROTYEoNRqodLet+z+LMKDq/o2qTNaYJLiDGMBZzhqyJIFR5ZJ5MhgLloY1gL8s0a7KMWDbh7giiWSu5zqhB3Du8Tom+8bYZUxOL4zhzCGrFitRqiEIIjy1/c5qyRQZaZx8CgYEA+lf6tdO6kKiAOxm7sdZ3rEl4UGFY+tEqgivKwurLRIor0XDfhCKr1hCfsZggpR8SMLfjCuNEgKbceofcKMa8OtyDbMPRz0mYNkCELTUYA+r8Ib/LvleQApMcLn+TDNwEnGlglSrrF33RVAUK+i/WfSXUvZRVpLQpRmdAqHjJeBkCgYEA0+Zz/iFXOGW32slJFWxRWqYz8VeZk52saGY/l/I/9Yj1J2tgugo7VtUS3BiB0ZGNK3SNfaxYmBz9KYO/Sew5DYnQqTdz1SHboQ2FAMAcnznutlNBVFdJnKPvkX8g5yBV05gApFgoPECUFn2jOP2coMjZ0M97Bjgil9YNUWvDdS0CgYEA4beFs3+tzVRAGgl/tD7dNBgiRMchBTSmkSuO6+PrVmcGTxboUSk5qg7fDa9Ob9LuAcMrENwNHbpVPJ1WoeVePewpC14bxDxk4zWUd3ZRquaqYnud5obor4mYdUxNd+DAv447qQNDaLDmlkzdsuqDB9+eSzh9Z72RIYtjPwN5E7ECgYEAsbqkMZXfK1tTRfduX+7KOlPMfcSr29X6nuDglcna4dHec6FAOzp3xL2722nnFt6gygc7pErrm0m0Wd/6BMTb4T3+GYwkDiMjM2CsTZYjpzrUri/VfRR509rScxHVR0/1PTFWN0K0+VZbEAyXDbbs4opq40tW0dWtcKxaNlimMw8=";
+ struct PrivateKey* private_key = libp2p_crypto_private_key_new();
+ struct RsaPrivateKey rsa_private_key = {0};
+ char* orig_peer_id = "QmbTyKkUuv6yaSpTuCFq1Ft6Q3g4wTtFJk1BLGMPRdAEP8";
+ size_t orig_peer_id_size = strlen(orig_peer_id);
+ unsigned char hashed[32];
+ size_t final_id_size = 1600;
+ unsigned char final_id[final_id_size];
+
+ // 1) take the private key and turn it back into bytes (decode base 64)
+ decode_base64_size = libp2p_crypto_encoding_base64_decode_size(strlen(orig_priv_key));
+ decode_base64 = (unsigned char*)malloc(decode_base64_size);
+ memset(decode_base64, 0, decode_base64_size);
+
+ if (!libp2p_crypto_encoding_base64_decode((unsigned char*)orig_priv_key, strlen(orig_priv_key), &decode_base64[0], decode_base64_size, &decode_base64_size))
+ goto exit;
+
+ if (!libp2p_crypto_private_key_protobuf_decode(decode_base64, decode_base64_size, &private_key))
+ goto exit;
+
+ // 2) take the bytes of the private key and turn it back into an RSA private key struct
+ //TODO: should verify that this key is RSA
+ if (!libp2p_crypto_encoding_x509_der_to_private_key(private_key->data, private_key->data_size, &rsa_private_key))
+ goto exit;
+
+ // 2b) take the private key and fill in the public key DER
+ if (!libp2p_crypto_rsa_private_key_fill_public_key(&rsa_private_key))
+ goto exit;
+
+
+ struct SecureSession secure_session;
+
+ secure_session.host = "www.jmjatlanta.com";
+ secure_session.port = 4001;
+ secure_session.traffic_type = TCP;
+
+ if (!libp2p_secio_handshake(&secure_session, &rsa_private_key))
+ goto exit;
+
+ retVal = 1;
+ exit:
+
+ return retVal;
+}
diff --git a/test/testit.c b/test/testit.c
index d46faa2..cbf7568 100644
--- a/test/testit.c
+++ b/test/testit.c
@@ -1,11 +1,12 @@
-
#include
-
#include "crypto/test_rsa.h"
#include "crypto/test_base58.h"
#include "crypto/test_base32.h"
+#include "crypto/test_key.h"
+#include "test_secio.h"
#include "test_mbedtls.h"
+#include "test_multistream.h"
const char* names[] = {
"test_public_der_to_private_der",
@@ -26,7 +27,10 @@ const char* names[] = {
"test_base58_peer_address",
//"test_mbedtls_pk_write_key_der",
//"test_crypto_rsa_sign",
- "test_crypto_encoding_base32_encode"
+ "test_crypto_encoding_base32_encode",
+ "test_protobuf_private_key",
+ "test_secio_handshake",
+ "test_multistream_connect"
};
int (*funcs[])(void) = {
@@ -48,7 +52,10 @@ int (*funcs[])(void) = {
test_base58_peer_address,
//test_mbedtls_pk_write_key_der,
//test_crypto_rsa_sign,
- test_crypto_encoding_base32_encode
+ test_crypto_encoding_base32_encode,
+ test_protobuf_private_key,
+ test_secio_handshake,
+ test_multistream_connect
};
int testit(const char* name, int (*func)(void)) {
@@ -98,8 +105,8 @@ int main(int argc, char** argv) {
if (tests_ran == 0)
printf("***** No tests found *****\n");
else {
- if (counter > 0) {
- printf("***** There were %d failed test(s) *****\n", counter);
+ if (tests_ran - counter > 0) {
+ printf("***** There were %d failed test(s) (%d successful) *****\n", tests_ran - counter, counter);
} else {
printf("All %d tests passed\n", tests_ran);
}