Addition of more handshake code for connecting to other nodes
This commit is contained in:
parent
6d9a9e0e70
commit
513b778561
10 changed files with 308 additions and 24 deletions
2
Makefile
2
Makefile
|
@ -11,6 +11,7 @@ compile:
|
||||||
cd hashmap; make all;
|
cd hashmap; make all;
|
||||||
cd record; make all;
|
cd record; make all;
|
||||||
cd routing; make all;
|
cd routing; make all;
|
||||||
|
cd secio; make all;
|
||||||
ar rcs libp2p.a $(OBJS)
|
ar rcs libp2p.a $(OBJS)
|
||||||
|
|
||||||
test: compile
|
test: compile
|
||||||
|
@ -27,5 +28,6 @@ clean:
|
||||||
cd test; make clean;
|
cd test; make clean;
|
||||||
cd record; make clean;
|
cd record; make clean;
|
||||||
cd routing; make clean;
|
cd routing; make clean;
|
||||||
|
cd secio; make all;
|
||||||
rm -rf libp2p.a
|
rm -rf libp2p.a
|
||||||
|
|
||||||
|
|
77
crypto/key.c
Normal file
77
crypto/key.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for public 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;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libp2p_crypto_public_key_free(struct PublicKey* in) {
|
||||||
|
if (in != NULL) {
|
||||||
|
if (in->raw_key != NULL)
|
||||||
|
free(in->raw_key);
|
||||||
|
free(in);
|
||||||
|
in = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshal a public key from a protobuf
|
||||||
|
*/
|
||||||
|
int libp2p_crypto_public_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PublicKey** 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_public_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, &((*out)->key_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)
|
||||||
|
goto exit;
|
||||||
|
pos += bytes_read;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (retVal == 0) {
|
||||||
|
libp2p_crypto_public_key_free(*out);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
29
include/libp2p/crypto/key.h
Normal file
29
include/libp2p/crypto/key.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for public keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum KeyType { KEYTYPE_RSA, KEYTYPE_ED25519, KEYTYPE_INVALID };
|
||||||
|
|
||||||
|
struct PublicKey {
|
||||||
|
enum KeyType type;
|
||||||
|
unsigned char* data;
|
||||||
|
size_t data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PrivateKey {
|
||||||
|
enum KeyType type;
|
||||||
|
unsigned char* data;
|
||||||
|
size_t data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PublicKey* libp2p_crypto_public_key_new();
|
||||||
|
|
||||||
|
void libp2p_crypto_public_key_free(struct PublicKey* 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);
|
34
include/libp2p/secio/exchange.h
Normal file
34
include/libp2p/secio/exchange.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Exchange {
|
||||||
|
unsigned char* epubkey;
|
||||||
|
size_t epubkey_size;
|
||||||
|
unsigned char* signature;
|
||||||
|
size_t signature_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieves the approximate size of an encoded version of the passed in struct
|
||||||
|
* @param in the struct to look at
|
||||||
|
* @reutrns the size of buffer needed
|
||||||
|
*/
|
||||||
|
size_t libp2p_secio_exchange_protobuf_encode_size(struct Exchange* in);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode the struct Exchange in protobuf format
|
||||||
|
* @param in the struct to be encoded
|
||||||
|
* @param buffer where to put the results
|
||||||
|
* @param max_buffer_length the max to write
|
||||||
|
* @param bytes_written how many bytes were written to the buffer
|
||||||
|
* @returns true(1) on success, otherwise false(0)
|
||||||
|
*/
|
||||||
|
int libp2p_secio_exchange_protobuf_encode(struct Exchange* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a protobuf array into an Exchange struct
|
||||||
|
* @param buffer the protobuf array
|
||||||
|
* @param max_buffer_length the length of the buffer
|
||||||
|
* @param out a pointer to the new struct Exchange NOTE: this method allocates memory
|
||||||
|
* @returns true(1) on success, otherwise false(0)
|
||||||
|
*/
|
||||||
|
int libp2p_secio_exchange_protobuf_decode(unsigned char* buffer, size_t max_buffer_length, struct Exchange** out);
|
|
@ -13,6 +13,18 @@ struct Propose {
|
||||||
size_t hashes_size;
|
size_t hashes_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Propose* libp2p_secio_propose_new();
|
||||||
|
void libp2p_secio_propose_free(struct Propose* in);
|
||||||
|
/**
|
||||||
|
* Helper to set the property to a value
|
||||||
|
* @param to the property
|
||||||
|
* @param to_size the size that matches the property
|
||||||
|
* @param from the value to be set in the property
|
||||||
|
* @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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* @param in the struct to look at
|
* @param in the struct to look at
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "libp2p/crypto/key.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A secure connection
|
* A secure connection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct SecureSession {
|
struct SecureSession {
|
||||||
int socket_descriptor;
|
int socket_descriptor;
|
||||||
|
struct PublicKey remote_key;
|
||||||
|
int remote_peer_id;
|
||||||
};
|
};
|
||||||
|
|
18
secio/Makefile
Normal file
18
secio/Makefile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -O0 -Wall -I../include -I../../c-protobuf
|
||||||
|
|
||||||
|
ifdef DEBUG
|
||||||
|
CFLAGS += -g3
|
||||||
|
endif
|
||||||
|
|
||||||
|
LFLAGS =
|
||||||
|
DEPS =
|
||||||
|
OBJS = exchange.o propose.o secio.o
|
||||||
|
|
||||||
|
%.o: %.c $(DEPS)
|
||||||
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
|
all: $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
|
@ -1,14 +1,14 @@
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "protobuf.h"
|
||||||
#include "libp2p/secio/propose.h"
|
#include "libp2p/secio/propose.h"
|
||||||
|
|
||||||
// rand pubkey exchanges ciphers hashes
|
// rand pubkey exchanges ciphers hashes
|
||||||
enum WireType secio_propose_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED };
|
enum WireType secio_propose_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED };
|
||||||
// epubkey signature
|
|
||||||
enum WireType secio_exchange_message_fields[] = { WIRETYPE_LENGTH_DELIMITED, WIRETYPE_LENGTH_DELIMITED };
|
|
||||||
|
|
||||||
struct Propose* libp2p_secio_propose_new() {
|
struct Propose* libp2p_secio_propose_new() {
|
||||||
struct Propose* retVal = (struct Propose*)malloc(sizeof(struct propose));
|
struct Propose* retVal = (struct Propose*)malloc(sizeof(struct Propose));
|
||||||
if (retVal == NULL)
|
if (retVal == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset((void*)retVal, 0, sizeof(struct Propose));
|
memset((void*)retVal, 0, sizeof(struct Propose));
|
||||||
|
@ -28,9 +28,21 @@ void libp2p_secio_propose_free( struct Propose* in) {
|
||||||
if (in->hashes != NULL)
|
if (in->hashes != NULL)
|
||||||
free(in->hashes);
|
free(in->hashes);
|
||||||
free(in);
|
free(in);
|
||||||
|
in = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int libp2p_secio_propose_set_property(void** to, size_t* to_size, void* from, size_t from_size) {
|
||||||
|
if (*to != NULL)
|
||||||
|
free(*to);
|
||||||
|
*to = (void*)malloc(from_size);
|
||||||
|
if (*to == NULL)
|
||||||
|
return 0;
|
||||||
|
memcpy(*to, from, from_size);
|
||||||
|
*to_size = from_size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* @param in the struct to look at
|
* @param in the struct to look at
|
||||||
|
@ -56,27 +68,26 @@ size_t libp2p_secio_propose_protobuf_encode_size(struct Propose* in) {
|
||||||
*/
|
*/
|
||||||
int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) {
|
int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) {
|
||||||
*bytes_written = 0;
|
*bytes_written = 0;
|
||||||
int retVal;
|
|
||||||
size_t bytes_used;
|
size_t bytes_used;
|
||||||
// rand
|
// rand
|
||||||
if (!protobuf_encode_length_delimited(1, secio_propose_message_fields[0], in->rand, in->rand_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
if (!protobuf_encode_length_delimited(1, secio_propose_message_fields[0], (char*)in->rand, in->rand_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
||||||
return -1;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
// public key
|
// public key
|
||||||
if (!protobuf_encode_length_delimited(2, secio_propose_message_fields[1], in->public_key, in->public_key_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
if (!protobuf_encode_length_delimited(2, secio_propose_message_fields[1], (char*)in->public_key, in->public_key_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
||||||
return -1;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
// ciphers
|
// ciphers
|
||||||
if (!protobuf_encode_length_delimited(3, secio_propose_message_fields[2], in->ciphers, in->ciphers_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
if (!protobuf_encode_length_delimited(3, secio_propose_message_fields[2], in->ciphers, in->ciphers_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
||||||
return -1;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
// exchanges
|
// exchanges
|
||||||
if (!protobuf_encode_length_delimited(4, secio_propose_message_fields[3], in->exchanges, in->exchanges_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
if (!protobuf_encode_length_delimited(4, secio_propose_message_fields[3], in->exchanges, in->exchanges_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
||||||
return -1;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
// hashes
|
// hashes
|
||||||
if (!protobuf_encode_length_delimited(5, secio_propose_message_fields[4], in->hashes, in->hashes_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
if (!protobuf_encode_length_delimited(5, secio_propose_message_fields[4], in->hashes, in->hashes_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
|
||||||
return -1;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -91,8 +102,6 @@ int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buff
|
||||||
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Propose** out) {
|
int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct Propose** out) {
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
unsigned char* temp_buffer = NULL;
|
|
||||||
size_t temp_size;
|
|
||||||
|
|
||||||
if (libp2p_secio_propose_new(out) == 0)
|
if (libp2p_secio_propose_new(out) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -140,8 +149,5 @@ exit:
|
||||||
if (retVal == 0) {
|
if (retVal == 0) {
|
||||||
libp2p_secio_propose_free(*out);
|
libp2p_secio_propose_free(*out);
|
||||||
}
|
}
|
||||||
if (temp_buffer != NULL)
|
|
||||||
free(temp_buffer);
|
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "libp2p/secio/secio.h"
|
#include "libp2p/secio/secio.h"
|
||||||
|
#include "libp2p/secio/propose.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";
|
||||||
|
@ -33,20 +36,46 @@ void libp2p_secio_secure_session_free(struct SecureSession* in) {
|
||||||
* @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_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;
|
||||||
|
|
||||||
// generate 16 byte nonce
|
// generate 16 byte nonce
|
||||||
char nonceOut[16];
|
char nonceOut[16];
|
||||||
if (!generateNonce(nonceOut, 16))
|
if (!generateNonce(&nonceOut, 16)) {
|
||||||
return 0;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
propose = libp2p_secio_propose_new();
|
||||||
|
libp2p_secio_propose_set_property(&propose->rand, &propose->rand_size, nonceOut, 16);
|
||||||
|
|
||||||
// will need:
|
// will need:
|
||||||
// public key
|
// TODO: public key
|
||||||
// supported exchanges
|
// supported exchanges
|
||||||
|
libp2p_secio_propose_set_property(&propose->exchanges, &propose->exchanges_size, SupportedExchanges, strlen(SupportedExchanges));
|
||||||
// supported ciphers
|
// supported ciphers
|
||||||
|
libp2p_secio_propose_set_property(&propose->ciphers, &propose->ciphers_size, SupportedCiphers, strlen(SupportedCiphers));
|
||||||
// supported hashes
|
// supported hashes
|
||||||
|
libp2p_secio_propose_set_property(&propose->hashes, &propose->exchanges_size, SupportedHashes, strlen(SupportedHashes));
|
||||||
|
|
||||||
// send request
|
// send request (protobuf, then send)
|
||||||
// receive response
|
protobuf_size = libp2p_secio_propose_protobuf_encode_size(propose);
|
||||||
|
protobuf = (unsigned char*) malloc(protobuf_size);
|
||||||
|
if (protobuf == NULL)
|
||||||
|
goto exit;
|
||||||
|
if (!libp2p_secio_propose_protobuf_encode(propose, protobuf, protobuf_size, &protobuf_size))
|
||||||
|
goto exit;
|
||||||
|
libp2p_secio_propose_free(propose);
|
||||||
|
if (!libp2p_net_socket_muxer_send(socketMuxer, protobuf, protobuf_size))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
// receive response (turn back into a Propose struct)
|
||||||
|
if (!libp2p_net_socket_muxer_receive(socketMuxer, &results, &results_size))
|
||||||
|
goto exit;
|
||||||
|
if (!libp2p_secio_propose_protobuf_decode(results, results_size, &propose))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
// get public key
|
// get public key
|
||||||
// generate their peer id
|
// generate their peer id
|
||||||
|
@ -68,4 +97,14 @@ int libp2p_secio_secure_session_handshake(struct SecureSession* session, struct
|
||||||
|
|
||||||
// send expected message (local nonce) to verify encryption works
|
// send expected message (local nonce) to verify encryption works
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
ipfs_secio_propose_free(propose);
|
||||||
|
if (protobuf != NULL)
|
||||||
|
free(protobuf);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
64
test/crypto/test_key.h
Normal file
64
test/crypto/test_key.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "libp2p/crypto/key.h"
|
||||||
|
|
||||||
|
|
||||||
|
int test_protobuf_private_key() {
|
||||||
|
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
|
||||||
|
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=";
|
||||||
|
struct PrivateKey* private_key = libp2p_crypto_private_key_new();
|
||||||
|
struct RsaPrivateKey rsa_private_key = {0};
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 4) compare results
|
||||||
|
if (orig_peer_id_size != final_id_size)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (strncmp(orig_peer_id, (char*)final_id, final_id_size) != 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
exit:
|
||||||
|
if (decode_base64 != NULL)
|
||||||
|
free(decode_base64);
|
||||||
|
return retVal;
|
||||||
|
}
|
Loading…
Reference in a new issue