Now correctly generating the Peer ID from a public key
This commit is contained in:
parent
6b24f06855
commit
94566ade69
8 changed files with 119 additions and 71 deletions
42
crypto/key.c
42
crypto/key.c
|
@ -29,6 +29,39 @@ void libp2p_crypto_public_key_free(struct PublicKey* in) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Calculates an approximate required size of a buffer for protobuf encoding a public key
|
||||||
|
* @param in the public key to examine
|
||||||
|
* @returns the size in bytes
|
||||||
|
*/
|
||||||
|
size_t libp2p_crypto_public_key_protobuf_encode_size(struct PublicKey* in) {
|
||||||
|
return 11 + 11 + in->data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Encode a PublicKey into a protobuf
|
||||||
|
* @param in the struct PublicKey
|
||||||
|
* @param buffer where to put the results
|
||||||
|
* @param max_buffer_length the size of the buffer
|
||||||
|
* @param bytes_written how many bytes were used in the buffer
|
||||||
|
* @returns true(1) on success, otherwise false(0)
|
||||||
|
*/
|
||||||
|
int libp2p_crypto_public_key_protobuf_encode(struct PublicKey* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) {
|
||||||
|
// data & data_size
|
||||||
|
size_t bytes_used = 0;
|
||||||
|
*bytes_written = 0;
|
||||||
|
int retVal = 0;
|
||||||
|
// key type (RSA vs ...)
|
||||||
|
retVal = protobuf_encode_varint(1, WIRETYPE_VARINT, in->type, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
|
||||||
|
*bytes_written += bytes_used;
|
||||||
|
// public key
|
||||||
|
retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, in->data, in->data_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used);
|
||||||
|
if (retVal == 0)
|
||||||
|
return 0;
|
||||||
|
*bytes_written += bytes_used;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmarshal a public key from a protobuf
|
* Unmarshal a public key from a protobuf
|
||||||
* @param buffer the protobuf
|
* @param buffer the protobuf
|
||||||
|
@ -153,8 +186,15 @@ exit:
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @returns true(1) on success, otherwise false(0)
|
||||||
*/
|
*/
|
||||||
int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id) {
|
int libp2p_crypto_public_key_to_peer_id(struct PublicKey* public_key, char** peer_id) {
|
||||||
|
|
||||||
|
size_t protobuf_len = libp2p_crypto_public_key_protobuf_encode_size(public_key);
|
||||||
|
unsigned char protobuf[protobuf_len];
|
||||||
|
|
||||||
|
libp2p_crypto_public_key_protobuf_encode(public_key, protobuf, protobuf_len, &protobuf_len);
|
||||||
|
|
||||||
unsigned char hashed[32];
|
unsigned char hashed[32];
|
||||||
libp2p_crypto_hashing_sha256(public_key->data, public_key->data_size, hashed);
|
//libp2p_crypto_hashing_sha256(public_key->data, public_key->data_size, hashed);
|
||||||
|
libp2p_crypto_hashing_sha256(protobuf, protobuf_len, hashed);
|
||||||
size_t final_id_size = 100;
|
size_t final_id_size = 100;
|
||||||
unsigned char final_id[final_id_size];
|
unsigned char final_id[final_id_size];
|
||||||
memset(final_id, 0, final_id_size);
|
memset(final_id, 0, final_id_size);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "mh/hashes.h"
|
#include "mh/hashes.h"
|
||||||
#include "libp2p/crypto/encoding/base58.h"
|
#include "libp2p/crypto/encoding/base58.h"
|
||||||
#include "libp2p/crypto/sha256.h"
|
#include "libp2p/crypto/sha256.h"
|
||||||
|
//#include "libp2p/crypto/key.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -38,20 +39,11 @@ int PrettyID(unsigned char * pointyaddr, size_t* rezbuflen,unsigned char * ID_BU
|
||||||
/****
|
/****
|
||||||
* 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 the text to hash
|
* @param texttohash the text to hash. A DER formatted public key
|
||||||
* @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);
|
libp2p_crypto_hashing_sha256(texttohash, text_size, (unsigned char*)result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,25 +113,7 @@ int libp2p_net_multistream_connect(const char* hostname, int port) {
|
||||||
if (num_bytes <= 0)
|
if (num_bytes <= 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// that should be successful, now we are in the loop, and it is waiting for a protocol buffer to use, so send it again
|
// we are now in the loop, so we can switch to another protocol (i.e. /secio/1.0.0)
|
||||||
protocol_buffer = "/secio/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;
|
|
||||||
// we should get it back again, handshake should be complete.
|
|
||||||
free(results);
|
|
||||||
results = NULL;
|
|
||||||
return_result = libp2p_net_multistream_receive(socket, &results, &results_size);
|
|
||||||
if (return_result == 0 || results_size < 1 || (results[0] == 'n' && results[1] == 'a')) {
|
|
||||||
// it failed, ask for a list
|
|
||||||
protocol_buffer = "ls";
|
|
||||||
num_bytes = libp2p_net_multistream_send(socket, (const unsigned char*)protocol_buffer, strlen(protocol_buffer));
|
|
||||||
if (num_bytes <= 0)
|
|
||||||
goto exit;
|
|
||||||
free(results);
|
|
||||||
results = NULL;
|
|
||||||
return_result = libp2p_net_multistream_receive(socket, &results, &results_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
retVal = socket;
|
retVal = socket;
|
||||||
exit:
|
exit:
|
||||||
|
|
|
@ -103,7 +103,7 @@ int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_le
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
|
|
||||||
if (libp2p_secio_propose_new(out) == 0)
|
if ( (*out = libp2p_secio_propose_new()) == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
while(pos < buffer_length) {
|
while(pos < buffer_length) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h> // for debugging, can remove
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -58,6 +59,45 @@ int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey*
|
||||||
struct Propose* propose_in = NULL;
|
struct Propose* propose_in = NULL;
|
||||||
struct PublicKey* public_key = NULL;
|
struct PublicKey* public_key = NULL;
|
||||||
|
|
||||||
|
// connect to host
|
||||||
|
session->socket_descriptor = libp2p_net_multistream_connect(session->host, session->port);
|
||||||
|
if (session->socket_descriptor == -1)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
|
||||||
|
|
||||||
|
bytes_written = libp2p_net_multistream_send(session->socket_descriptor, protocol, strlen((char*)protocol));
|
||||||
|
if (bytes_written <= 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// we should get back the protocol to signify it was accepted, as well as the protobuf of the Propose struct
|
||||||
|
bytes_written = libp2p_net_multistream_receive(session->socket_descriptor, (char**)&results, &results_size);
|
||||||
|
if (bytes_written < 1 || strstr((char*)results, "secio") == NULL)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// skip to the protobuf section
|
||||||
|
protobuf = (unsigned char*)strchr((char*)results, '\n');
|
||||||
|
if (protobuf == NULL)
|
||||||
|
goto exit;
|
||||||
|
protobuf++;
|
||||||
|
protobuf_size = results_size - (protobuf - results);
|
||||||
|
|
||||||
|
if (!libp2p_secio_propose_protobuf_decode(protobuf, protobuf_size, &propose_in))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// clear results
|
||||||
|
free(results);
|
||||||
|
results = NULL;
|
||||||
|
results_size = 0;
|
||||||
|
|
||||||
|
// hash the protobuf of the 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
|
||||||
|
char* remote_peer_id;
|
||||||
|
libp2p_crypto_public_key_to_peer_id(public_key, &remote_peer_id);
|
||||||
|
|
||||||
// generate 16 byte nonce
|
// generate 16 byte nonce
|
||||||
char nonceOut[16];
|
char nonceOut[16];
|
||||||
if (!libp2p_secio_generate_nonce(&nonceOut[0], 16)) {
|
if (!libp2p_secio_generate_nonce(&nonceOut[0], 16)) {
|
||||||
|
@ -67,6 +107,10 @@ int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey*
|
||||||
propose_out = libp2p_secio_propose_new();
|
propose_out = libp2p_secio_propose_new();
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, nonceOut, 16);
|
libp2p_secio_propose_set_property((void**)&propose_out->rand, &propose_out->rand_size, nonceOut, 16);
|
||||||
|
|
||||||
|
// TODO: the Peer ID looks funny. I don't think it is right.
|
||||||
|
|
||||||
|
// we have their information, now we need to gather ours.
|
||||||
|
|
||||||
// will need:
|
// will need:
|
||||||
// TODO: public key
|
// TODO: public key
|
||||||
// supported exchanges
|
// supported exchanges
|
||||||
|
@ -75,37 +119,6 @@ int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey*
|
||||||
libp2p_secio_propose_set_property((void**)&propose_out->ciphers, &propose_out->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((void**)&propose_out->hashes, &propose_out->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_out);
|
|
||||||
protobuf = (unsigned char*) malloc(protobuf_size);
|
|
||||||
if (protobuf == NULL)
|
|
||||||
goto exit;
|
|
||||||
if (!libp2p_secio_propose_protobuf_encode(propose_out, protobuf, protobuf_size, &protobuf_size))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
// connect to host
|
|
||||||
session->socket_descriptor = libp2p_net_multistream_connect(session->host, session->port);
|
|
||||||
|
|
||||||
bytes_written = libp2p_net_multistream_send(session->socket_descriptor, protobuf, protobuf_size);
|
|
||||||
if (bytes_written <= 0)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
// receive response (turn back into a Propose struct)
|
|
||||||
bytes_written = libp2p_net_multistream_receive(session->socket_descriptor, (char**)&results, &results_size);
|
|
||||||
if (bytes_written == 65535)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
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
|
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
|
||||||
// curve
|
// curve
|
||||||
// cipher
|
// cipher
|
||||||
|
|
|
@ -15,8 +15,7 @@ int test_protobuf_private_key() {
|
||||||
char* orig_peer_id = "QmbTyKkUuv6yaSpTuCFq1Ft6Q3g4wTtFJk1BLGMPRdAEP8";
|
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);
|
||||||
unsigned char hashed[32];
|
unsigned char hashed[32];
|
||||||
size_t final_id_size = 1600;
|
unsigned char *final_id;
|
||||||
unsigned char final_id[final_id_size];
|
|
||||||
|
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -40,16 +39,18 @@ 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
|
||||||
ID_FromPK_non_null_terminated((char*)hashed, (unsigned char*)rsa_private_key.public_key_der, rsa_private_key.public_key_length);
|
struct PublicKey public_key;
|
||||||
memset(final_id, 0, final_id_size);
|
public_key.type = KEYTYPE_RSA;
|
||||||
if (!PrettyID(final_id, &final_id_size, hashed, 32))
|
public_key.data_size = rsa_private_key.public_key_length;
|
||||||
|
public_key.data = rsa_private_key.public_key_der;
|
||||||
|
if (!libp2p_crypto_public_key_to_peer_id(&public_key, (char**)&final_id ))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// 4) compare results
|
// 4) compare results
|
||||||
if (orig_peer_id_size != final_id_size)
|
if (orig_peer_id_size != strlen((char*)final_id))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (strncmp(orig_peer_id, (char*)final_id, final_id_size) != 0)
|
if (strncmp(orig_peer_id, (char*)final_id, strlen(final_id)) != 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
|
@ -11,6 +11,22 @@ int test_multistream_connect() {
|
||||||
char* response;
|
char* response;
|
||||||
size_t response_size;
|
size_t response_size;
|
||||||
|
|
||||||
|
socket_fd = libp2p_net_multistream_connect("www.jmjatlanta.com", 4001);
|
||||||
|
if (socket_fd < 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
return retVal > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_multistream_get_list() {
|
||||||
|
int retVal = 0, socket_fd = -1;
|
||||||
|
char* response;
|
||||||
|
size_t response_size;
|
||||||
|
|
||||||
socket_fd = libp2p_net_multistream_connect("www.jmjatlanta.com", 4001);
|
socket_fd = libp2p_net_multistream_connect("www.jmjatlanta.com", 4001);
|
||||||
if (socket_fd < 0)
|
if (socket_fd < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -26,6 +42,8 @@ int test_multistream_connect() {
|
||||||
if (retVal <= 0)
|
if (retVal <= 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
fprintf(stdout, "Response from multistream ls: %s", response);
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
|
@ -30,7 +30,8 @@ const char* names[] = {
|
||||||
"test_crypto_encoding_base32_encode",
|
"test_crypto_encoding_base32_encode",
|
||||||
"test_protobuf_private_key",
|
"test_protobuf_private_key",
|
||||||
"test_secio_handshake",
|
"test_secio_handshake",
|
||||||
"test_multistream_connect"
|
"test_multistream_connect",
|
||||||
|
"test_multistream_get_list"
|
||||||
};
|
};
|
||||||
|
|
||||||
int (*funcs[])(void) = {
|
int (*funcs[])(void) = {
|
||||||
|
@ -55,7 +56,8 @@ int (*funcs[])(void) = {
|
||||||
test_crypto_encoding_base32_encode,
|
test_crypto_encoding_base32_encode,
|
||||||
test_protobuf_private_key,
|
test_protobuf_private_key,
|
||||||
test_secio_handshake,
|
test_secio_handshake,
|
||||||
test_multistream_connect
|
test_multistream_connect,
|
||||||
|
test_multistream_get_list
|
||||||
};
|
};
|
||||||
|
|
||||||
int testit(const char* name, int (*func)(void)) {
|
int testit(const char* name, int (*func)(void)) {
|
||||||
|
|
Loading…
Reference in a new issue