Added multistream protocol to communicate with GO version

This commit is contained in:
John Jones 2017-02-02 14:10:12 -05:00
parent 29e1a0c31b
commit d091a29b19
27 changed files with 714 additions and 131 deletions

View file

@ -26,6 +26,7 @@
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.623347632" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"> <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.623347632" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<option id="gnu.c.compiler.option.include.paths.1688271638" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <option id="gnu.c.compiler.option.include.paths.1688271638" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/c-multihash/include}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/c-multihash/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/c-libp2p/include}&quot;"/>
</option> </option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1284958161" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1284958161" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool> </tool>

View file

@ -2,19 +2,27 @@
DEBUG = true DEBUG = true
export DEBUG 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: compile:
cd crypto; make all; cd crypto; make all;
cd thirdparty; make all; cd thirdparty; make all;
cd hashmap; make all; cd hashmap; make all;
cd net; make all;
cd record; make all; cd record; make all;
cd routing; make all; cd routing; make all;
cd secio; make all; cd secio; make all;
ar rcs libp2p.a $(OBJS)
test: compile test: compile link
cd test; make all; cd test; make all;
rebuild: clean all rebuild: clean all
@ -24,6 +32,7 @@ all: test
clean: clean:
cd crypto; make clean; cd crypto; make clean;
cd hashmap; make clean; cd hashmap; make clean;
cd net; make clean;
cd thirdparty; make clean cd thirdparty; make clean
cd test; make clean; cd test; make clean;
cd record; make clean; cd record; make clean;

View file

@ -1,8 +1,8 @@
CC = gcc CC = gcc
CFLAGS = -O0 -I../include -g3 CFLAGS = -O0 -I../include -I../../c-protobuf -I../../c-multihash/include -g3
LFLAGS = LFLAGS =
DEPS = 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) %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)

View file

@ -1,31 +1,29 @@
#include <stdio.h> #include <stdlib.h>
#include <string.h>
#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* libp2p_crypto_public_key_new() {
struct PublicKey* retVal = malloc(sizeof(struct PublicKey)); struct PublicKey* retVal = malloc(sizeof(struct PublicKey));
if (retVal == NULL) if (retVal == NULL)
return NULL; return NULL;
retVal->key_type = KEYTYPE_INVALID; retVal->type = KEYTYPE_INVALID;
retVal->raw_key = NULL; retVal->data = NULL;
retVal->raw_key_size = 0; retVal->data_size = 0;
return retVal; return retVal;
} }
void libp2p_crypto_public_key_free(struct PublicKey* in) { void libp2p_crypto_public_key_free(struct PublicKey* in) {
if (in != NULL) { if (in != NULL) {
if (in->raw_key != NULL) if (in->data != NULL)
free(in->raw_key); free(in->data);
free(in); free(in);
in = NULL; in = NULL;
} }
@ -33,6 +31,10 @@ void libp2p_crypto_public_key_free(struct PublicKey* in) {
/** /**
* Unmarshal a public key from a protobuf * 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) { 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; pos += bytes_read;
switch(field_no) { switch(field_no) {
case (1): // type 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; goto exit;
pos += bytes_read; pos += bytes_read;
break; break;
case (2): // key 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; goto exit;
pos += bytes_read; pos += bytes_read;
break; break;
@ -75,3 +77,94 @@ exit:
} }
return retVal; 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;
}

66
crypto/peerutils.c Normal file
View file

@ -0,0 +1,66 @@
#include <stdlib.h>
#include <string.h>
#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));
}

View file

@ -92,7 +92,7 @@ A million repetitions of "a"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <libp2p/routing/sha1.h> #include "libp2p/crypto/sha1.h"
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]); void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);

View file

@ -19,11 +19,21 @@ struct PrivateKey {
}; };
struct PublicKey* libp2p_crypto_public_key_new(); struct PublicKey* libp2p_crypto_public_key_new();
void libp2p_crypto_public_key_free(struct PublicKey* in); 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 * 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_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);

View file

@ -9,6 +9,8 @@
#include "mh/multihash.h" #include "mh/multihash.h"
#include "mh/hashes.h" #include "mh/hashes.h"
/*
#define uchar unsigned char // 8-bit byte #define uchar unsigned char // 8-bit byte
#define juint unsigned int // 32-bit word #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 // 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 * 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 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) * @param ID_BUF_SIZE the input size (normally a SHA256, therefore 32 bytes)
* @returns true(1) on success * @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 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. * 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 texttohash the text to hash
* @param text_size the size of the text * @param text_size the size of the text
*/ */
void ID_FromPK_non_null_terminated(char * result,unsigned char * texttohash, size_t text_size) 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. * 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 result where to store the result. Should be 32 chars long
* @param texttohash a null terminated string of the text to hash * @param texttohash a null terminated string of the text to hash
*/ */
void ID_FromPK(char * result,unsigned char * texttohash) void ID_FromPK(char * result,unsigned char * texttohash);
{
ID_FromPK_non_null_terminated(result,texttohash,strlen((char*)texttohash));
}
#endif #endif

View file

@ -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);

View file

@ -0,0 +1,37 @@
#ifndef P2PNET_H
#define P2PNET_H
#include <stdint.h>
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

View file

@ -23,7 +23,7 @@ void libp2p_secio_propose_free(struct Propose* in);
* @param from_size the size of from * @param from_size the size of from
* @returns true(1) on success, otherwise false(0) * @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 * retrieves the approximate size of an encoded version of the passed in struct

View file

@ -1,13 +1,29 @@
#pragma once #pragma once
#include "libp2p/crypto/key.h" #include "libp2p/crypto/key.h"
#include "libp2p/crypto/rsa.h"
/** /**
* A secure connection * A secure connection
*/ */
enum IPTrafficType { TCP, UDP };
struct SecureSession { struct SecureSession {
// to get the connection started
char* host;
int port;
enum IPTrafficType traffic_type;
// once the connection is established
int socket_descriptor; int socket_descriptor;
struct PublicKey remote_key; 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);

18
net/Makefile Normal file
View file

@ -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

117
net/multistream.c Normal file
View file

@ -0,0 +1,117 @@
#include <stdlib.h>
#include <string.h>
#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;
}

View file

@ -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

View file

@ -1,7 +1,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "p2pnet.h" #include "libp2p/net/p2pnet.h"
/* Create a SCTP socket. /* Create a SCTP socket.
*/ */

View file

@ -3,8 +3,11 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "p2pnet.h" #include <errno.h>
#include "libp2p/net/p2pnet.h"
/* associate an IP address with an port to a socket. /* associate an IP address with an port to a socket.
* first param is the socket file description * first param is the socket file description
@ -64,7 +67,12 @@ int socket_local4(int s, uint32_t *ip, uint16_t *port)
return 0; 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) 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); 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;
}

View file

@ -1,7 +1,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "p2pnet.h" #include "libp2p/net/p2pnet.h"
/* Create a TCP socket. /* Create a TCP socket.
*/ */

View file

@ -1,7 +1,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "p2pnet.h" #include "libp2p/net/p2pnet.h"
/* Create a UDP socket. /* Create a UDP socket.
*/ */

View file

@ -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) if (*to != NULL)
free(*to); free(*to);
*to = (void*)malloc(from_size); *to = (void*)malloc(from_size);

View file

@ -1,8 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "libp2p/secio/secio.h" #include "libp2p/secio/secio.h"
#include "libp2p/secio/propose.h" #include "libp2p/secio/propose.h"
#include "libp2p/net/p2pnet.h"
const char* SupportedExchanges = "P-256,P-384,P-521"; const char* SupportedExchanges = "P-256,P-384,P-521";
const char* SupportedCiphers = "AES-256,AES-128,Blowfish"; const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
@ -29,56 +31,104 @@ void libp2p_secio_secure_session_free(struct SecureSession* in) {
free(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 * performs initial communication over an insecure channel to share
* keys, IDs, and initiate connection. This is a framed messaging system * keys, IDs, and initiate connection. This is a framed messaging system
* @param session the secure session to be filled * @param session the secure session to be filled
* @returns true(1) on success, false(0) otherwise * @returns true(1) on success, false(0) otherwise
*/ */
int libp2p_secio_secure_session_handshake(struct SecureSession* session, struct RsaPrivateKey* private_key) { int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey* private_key) {
int retVal = 0, protobuf_size = 0, results_size = 0; int retVal = 0, results_size = 65535, bytes_written = 0;
unsigned char* protobuf = 0;; size_t protobuf_size = 0;
unsigned char* results; unsigned char* protobuf = 0;
struct Propose* propose = NULL; unsigned char results[results_size];
struct SocketMuxer* socketMuxer; struct Propose* propose_out = NULL;
struct Propose* propose_in = NULL;
struct PublicKey* public_key = NULL;
uint32_t ip;
int socket;
// generate 16 byte nonce // generate 16 byte nonce
char nonceOut[16]; char nonceOut[16];
if (!generateNonce(&nonceOut, 16)) { if (!libp2p_secio_generate_nonce(&nonceOut[0], 16)) {
goto exit; goto exit;
} }
propose = libp2p_secio_propose_new(); propose_out = libp2p_secio_propose_new();
libp2p_secio_propose_set_property(&propose->rand, &propose->rand_size, nonceOut, 16); libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, nonceOut, 16);
// will need: // will need:
// TODO: public key // TODO: public key
// supported exchanges // 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 // 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 // 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) // 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); protobuf = (unsigned char*) malloc(protobuf_size);
if (protobuf == NULL) if (protobuf == NULL)
goto exit; 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; goto exit;
libp2p_secio_propose_free(propose); ip = hostname_to_ip(session->host);
if (!libp2p_net_socket_muxer_send(socketMuxer, protobuf, protobuf_size)) 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; goto exit;
// receive response (turn back into a Propose struct) // 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; 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; goto exit;
// get public key // 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 // 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 // negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
// curve // curve
@ -101,7 +151,8 @@ int libp2p_secio_secure_session_handshake(struct SecureSession* session, struct
exit: exit:
ipfs_secio_propose_free(propose); libp2p_secio_propose_free(propose_out);
libp2p_secio_propose_free(propose_in);
if (protobuf != NULL) if (protobuf != NULL)
free(protobuf); free(protobuf);

View file

@ -7,7 +7,7 @@ endif
LFLAGS = -L../ -L../../c-multihash LFLAGS = -L../ -L../../c-multihash
DEPS = crypto/test_base58.h crypto/test_rsa.h test_mbedtls.h 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) %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)

View file

@ -8,31 +8,30 @@ int test_protobuf_private_key() {
size_t decode_base64_size = 0; size_t decode_base64_size = 0;
unsigned char* decode_base64; unsigned char* decode_base64;
// this is a base64 encoded private key. It makes it easier to test if it is in base64 form // 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 PrivateKey* private_key = libp2p_crypto_private_key_new();
struct RsaPrivateKey rsa_private_key = {0}; 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) // 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_size = libp2p_crypto_encoding_base64_decode_size(strlen(orig_priv_key));
decode_base64 = (unsigned char*)malloc(decode_base64_size); decode_base64 = (unsigned char*)malloc(decode_base64_size);
memset(decode_base64, 0, 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 (!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)
goto exit; 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)) if (!libp2p_crypto_private_key_protobuf_decode(decode_base64, decode_base64_size, &private_key))
goto exit; 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)) if (!libp2p_crypto_encoding_x509_der_to_private_key(private_key->data, private_key->data_size, &rsa_private_key))
goto exit; goto exit;
@ -41,10 +40,7 @@ int test_protobuf_private_key() {
goto exit; goto exit;
// 3) grab the public key, hash it, then base58 it // 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); 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); memset(final_id, 0, final_id_size);
if (!PrettyID(final_id, &final_id_size, hashed, 32)) if (!PrettyID(final_id, &final_id_size, hashed, 32))
goto exit; goto exit;

View file

@ -8,7 +8,7 @@
#include "libp2p/crypto/rsa.h" #include "libp2p/crypto/rsa.h"
#include "libp2p/crypto/encoding/base64.h" #include "libp2p/crypto/encoding/base64.h"
#include "libp2p/crypto/encoding/x509.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() { int test_crypto_rsa_public_key_to_peer_id() {
// this is the base64 encoded private key from the config file // 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 // 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); 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 // if we take the private key, retrieve the public key, hash it, we should come up with the peer id

35
test/test_multistream.h Normal file
View file

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#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;
}

55
test/test_secio.h Normal file
View file

@ -0,0 +1,55 @@
#include <stdlib.h>
#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;
}

View file

@ -1,11 +1,12 @@
#include <stdio.h> #include <stdio.h>
#include "crypto/test_rsa.h" #include "crypto/test_rsa.h"
#include "crypto/test_base58.h" #include "crypto/test_base58.h"
#include "crypto/test_base32.h" #include "crypto/test_base32.h"
#include "crypto/test_key.h"
#include "test_secio.h"
#include "test_mbedtls.h" #include "test_mbedtls.h"
#include "test_multistream.h"
const char* names[] = { const char* names[] = {
"test_public_der_to_private_der", "test_public_der_to_private_der",
@ -26,7 +27,10 @@ const char* names[] = {
"test_base58_peer_address", "test_base58_peer_address",
//"test_mbedtls_pk_write_key_der", //"test_mbedtls_pk_write_key_der",
//"test_crypto_rsa_sign", //"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) = { int (*funcs[])(void) = {
@ -48,7 +52,10 @@ int (*funcs[])(void) = {
test_base58_peer_address, test_base58_peer_address,
//test_mbedtls_pk_write_key_der, //test_mbedtls_pk_write_key_der,
//test_crypto_rsa_sign, //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)) { int testit(const char* name, int (*func)(void)) {
@ -98,8 +105,8 @@ int main(int argc, char** argv) {
if (tests_ran == 0) if (tests_ran == 0)
printf("***** No tests found *****\n"); printf("***** No tests found *****\n");
else { else {
if (counter > 0) { if (tests_ran - counter > 0) {
printf("***** There were %d failed test(s) *****\n", counter); printf("***** There were %d failed test(s) (%d successful) *****\n", tests_ran - counter, counter);
} else { } else {
printf("All %d tests passed\n", tests_ran); printf("All %d tests passed\n", tests_ran);
} }