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
|
||||
* @param buffer the protobuf
|
||||
|
@ -153,8 +186,15 @@ exit:
|
|||
* @returns true(1) on success, otherwise false(0)
|
||||
*/
|
||||
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];
|
||||
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;
|
||||
unsigned char final_id[final_id_size];
|
||||
memset(final_id, 0, final_id_size);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "mh/hashes.h"
|
||||
#include "libp2p/crypto/encoding/base58.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
|
||||
|
@ -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.
|
||||
* @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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,25 +113,7 @@ int libp2p_net_multistream_connect(const char* hostname, int port) {
|
|||
if (num_bytes <= 0)
|
||||
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
|
||||
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);
|
||||
}
|
||||
// we are now in the loop, so we can switch to another protocol (i.e. /secio/1.0.0)
|
||||
|
||||
retVal = socket;
|
||||
exit:
|
||||
|
|
|
@ -103,7 +103,7 @@ int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_le
|
|||
size_t pos = 0;
|
||||
int retVal = 0;
|
||||
|
||||
if (libp2p_secio_propose_new(out) == 0)
|
||||
if ( (*out = libp2p_secio_propose_new()) == NULL)
|
||||
goto exit;
|
||||
|
||||
while(pos < buffer_length) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h> // for debugging, can remove
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -58,6 +59,45 @@ int libp2p_secio_handshake(struct SecureSession* session, struct RsaPrivateKey*
|
|||
struct Propose* propose_in = 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
|
||||
char nonceOut[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();
|
||||
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:
|
||||
// TODO: public key
|
||||
// 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));
|
||||
// supported hashes
|
||||
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
|
||||
// curve
|
||||
// cipher
|
||||
|
|
|
@ -15,8 +15,7 @@ int test_protobuf_private_key() {
|
|||
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];
|
||||
unsigned char *final_id;
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
memset(final_id, 0, final_id_size);
|
||||
if (!PrettyID(final_id, &final_id_size, hashed, 32))
|
||||
struct PublicKey public_key;
|
||||
public_key.type = KEYTYPE_RSA;
|
||||
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;
|
||||
|
||||
// 4) compare results
|
||||
if (orig_peer_id_size != final_id_size)
|
||||
if (orig_peer_id_size != strlen((char*)final_id))
|
||||
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;
|
||||
|
||||
retVal = 1;
|
||||
|
|
|
@ -11,6 +11,22 @@ int test_multistream_connect() {
|
|||
char* response;
|
||||
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);
|
||||
if (socket_fd < 0)
|
||||
goto exit;
|
||||
|
@ -26,6 +42,8 @@ int test_multistream_connect() {
|
|||
if (retVal <= 0)
|
||||
goto exit;
|
||||
|
||||
fprintf(stdout, "Response from multistream ls: %s", response);
|
||||
|
||||
retVal = 1;
|
||||
|
||||
exit:
|
||||
|
|
|
@ -30,7 +30,8 @@ const char* names[] = {
|
|||
"test_crypto_encoding_base32_encode",
|
||||
"test_protobuf_private_key",
|
||||
"test_secio_handshake",
|
||||
"test_multistream_connect"
|
||||
"test_multistream_connect",
|
||||
"test_multistream_get_list"
|
||||
};
|
||||
|
||||
int (*funcs[])(void) = {
|
||||
|
@ -55,7 +56,8 @@ int (*funcs[])(void) = {
|
|||
test_crypto_encoding_base32_encode,
|
||||
test_protobuf_private_key,
|
||||
test_secio_handshake,
|
||||
test_multistream_connect
|
||||
test_multistream_connect,
|
||||
test_multistream_get_list
|
||||
};
|
||||
|
||||
int testit(const char* name, int (*func)(void)) {
|
||||
|
|
Loading…
Reference in a new issue