diff --git a/Makefile b/Makefile index ff4daae..893698e 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ + +DEBUG = true +export DEBUG + OBJS = crypto/rsa.o crypto/encoding/asn1.o crypto/encoding/base58.o crypto/encoding/base64.o \ crypto/encoding/x509.o thirdparty/mbedtls/*.o @@ -17,4 +21,4 @@ clean: cd thirdparty; make clean cd test; make clean; rm -rf libp2p.a - \ No newline at end of file + diff --git a/crypto/Makefile b/crypto/Makefile index 7a53625..f6c6c67 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -O0 -I../include +CFLAGS = -O0 -I../include -g3 LFLAGS = DEPS = OBJS = rsa.o diff --git a/crypto/encoding/Makefile b/crypto/encoding/Makefile index b492ef3..95cf94d 100644 --- a/crypto/encoding/Makefile +++ b/crypto/encoding/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -O0 -I../../include +CFLAGS = -O0 -I../../include -g3 LFLAGS = DEPS = OBJS = asn1.o base58.o base64.o x509.o diff --git a/crypto/rsa.c b/crypto/rsa.c index 91f2c1e..899c81b 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -19,7 +19,47 @@ #include "mbedtls/bignum.h" #include "mbedtls/x509.h" #include "mbedtls/rsa.h" +#include "mbedtls/asn1write.h" +/** + * Take an rsa context and turn it into a der formatted byte stream. + * NOTE: the stream starts from the right. So there could be a lot of padding in front. + * Pay attention to the returned size to cut the padding. + * @param rsa the rsa key to encode + * @param buf where to put the bytes + * @param size the max size of the buffer. The actual size used is returned in this value + * @returns true(1) on success, else 0 + */ +int libp2p_crypto_rsa_write_key_der( mbedtls_rsa_context *rsa, unsigned char *buf, size_t* size ) +{ + int ret; + unsigned char *c = buf + *size; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + *size = len; + return 1; +} + +/*** + * Generate an RSA keypair of a certain size, and place the results in the struct + * @param private_key where to put the results + * @param num_bits_for_keypair the number of bits for the key, 1024 is the minimum + * @returns true(1) on success + */ int crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long num_bits_for_keypair) { mbedtls_rsa_context rsa; @@ -29,6 +69,8 @@ int crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long int exponent = 65537; int retVal = 1; + unsigned char* buffer; + const char *pers = "rsa_genkey"; // initialize mbedtls structs @@ -65,20 +107,24 @@ int crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long private_key->P = *(rsa.P.p); private_key->Q = *(rsa.Q.p); private_key->QP = *(rsa.QP.p); - /* - private_key->public_key.modulus = *(rsa.N.p); - private_key->public_key.exponent = *(rsa.E.p); - private_key->prime1 = *(rsa.DP.p); - private_key->prime2 = *(rsa.Q.p); - private_key->private_exponent = *(rsa.D.p); + + size_t buffer_size = 1600; + buffer = malloc(sizeof(char) * buffer_size); + retVal = libp2p_crypto_rsa_write_key_der(&rsa, buffer, &buffer_size); + if (retVal == 0) + return 0; + + // allocate memory for the der + private_key->der = malloc(sizeof(char) * buffer_size); + private_key->der_length = buffer_size; + // add in the der to the buffer + memcpy(private_key->der, &buffer[1600-buffer_size], buffer_size); + + //TODO: Add the peer id - //TODO: fill in the rest of the precomputed values - private_key->precomputed_values.dp = *(rsa.DP.p); - private_key->precomputed_values.dq = *(rsa.DQ.p); - */ - retVal = 1; exit: - + if (buffer != NULL) + free(buffer); mbedtls_rsa_free( &rsa ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); @@ -86,14 +132,13 @@ exit: return retVal; } -/** - * convert a struct RsaPublicKey into a stream of bytes compatible with x509 PKI - * @param public_key the public key struct - * @param bytes the results - * @param bytes_size the length of the results +/*** + * Free resources used by RsaPrivateKey + * @param private_key the resources + * @returns 0 */ -int crypto_rsa_public_key_bytes(struct RsaPublicKey* public_key, char** bytes, unsigned long long* bytes_size) { - // marshal to x509 - return 0; +int crypto_rsa_rsa_private_key_free(struct RsaPrivateKey* private_key) { + if (private_key->der != NULL) + free(private_key->der); } diff --git a/include/libp2p/crypto/rsa.h b/include/libp2p/crypto/rsa.h index 2f3d8bc..22cadf7 100644 --- a/include/libp2p/crypto/rsa.h +++ b/include/libp2p/crypto/rsa.h @@ -9,32 +9,9 @@ #ifndef rsa_h #define rsa_h -struct RsaPublicKey { - unsigned long long modulus; - unsigned long long exponent; -}; - -struct CRTValue { - unsigned long long exponent; - unsigned long long coefficient; - unsigned long long r; -}; - -struct PrecomputedValues { - unsigned long long dp; - unsigned long long dq; - unsigned long long q_inv; - struct CRTValue** crt_values; -}; +#include struct RsaPrivateKey { - /* The old - struct RsaPublicKey public_key; - unsigned long long private_exponent; - unsigned long long prime1; - unsigned long long prime2; - struct PrecomputedValues precomputed_values; - */ unsigned long long QP; unsigned long long DQ; unsigned long long DP; @@ -43,6 +20,8 @@ struct RsaPrivateKey { unsigned long long D; unsigned long long E; unsigned long long N; + char* der; + size_t der_length; }; /** @@ -53,13 +32,11 @@ struct RsaPrivateKey { */ int crypto_rsa_generate_keypair(struct RsaPrivateKey* private_key, unsigned long num_bits_for_keypair); -/** - * convert a struct RsaPublicKey into a stream of bytes compatible with x509 PKI - * @param public_key the public key struct - * @param bytes the results - * @param bytes_size the length of the results +/*** + * Free resources used by RsaPrivateKey + * @param private_key the resources + * @returns 0 */ -int crypto_rsa_public_key_bytes(struct RsaPublicKey* public_key, char** bytes, unsigned long long* bytes_size); - +int crypto_rsa_rsa_private_key_free(struct RsaPrivateKey* private_key); #endif /* rsa_h */ diff --git a/test/Makefile b/test/Makefile index 6c212ce..3101eae 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,5 +1,10 @@ CC = gcc -CFLAGS = -O0 -I../include -I. -g3 +CFLAGS = -O0 -I../include -I. + +ifdef DEBUG +CFLAGS += -g3 +endif + LFLAGS = -L../ DEPS = crypto/test_base58.h crypto/test_mbedtls.h crypto/test_rsa.h OBJS = testit.o @@ -14,4 +19,4 @@ all: testit_libp2p clean: rm -f *.o - rm testit_libp2p + rm -f testit_libp2p diff --git a/test/crypto/test_base58.h b/test/crypto/test_base58.h index f0e56dc..f564b22 100644 --- a/test/crypto/test_base58.h +++ b/test/crypto/test_base58.h @@ -79,14 +79,23 @@ int test_base58_peer_address() { size_t result_buffer_length = libp2p_crypto_encoding_base58_decode_max_size(x_data); unsigned char result_buffer[result_buffer_length]; unsigned char* ptr_to_result = result_buffer; + memset(result_buffer, 0, result_buffer_length); // now get the decoded address int return_value = libp2p_crypto_encoding_base58_decode(x_data, x_data_length, &ptr_to_result, &result_buffer_length); if (return_value == 0) return 0; + // add 2 bytes to the front for the varint + unsigned char final_result[result_buffer_length + 2]; + // TODO: put the 2 bytes of your varint here, and erase the memset line below. + memset(final_result, 0, 2); + memcpy(&(final_result[2]), result_buffer, result_buffer_length); // throw everything in a hex string so we can debug the results - //for(int i = 0; i < x_data_length; i++) - // printf("%02x", result_buffer[i]); - //printf("\n"); + for(int i = 0; i < result_buffer_length + 2; i++) { + // get the char so we can see it in the debugger + unsigned char c = final_result[i]; + printf("%02x", c); + } + printf("\n"); return 1; } diff --git a/test/crypto/test_rsa.h b/test/crypto/test_rsa.h index 6196ed5..bfcf853 100644 --- a/test/crypto/test_rsa.h +++ b/test/crypto/test_rsa.h @@ -18,34 +18,17 @@ #include "libp2p/crypto/encoding/x509.h" /** - * attempt to take a known public key in bytes and convert to bytes compatible with go's version of PKIX + * make sure we can get a DER formatted result */ -int test_crypto_rsa_public_key_bytes() { - // first we need a public key +int test_crypto_rsa_private_key_der() { + struct RsaPrivateKey private_key; - crypto_rsa_generate_keypair(&private_key, 2048); - // save it to a text file (converting the primes to text) - FILE* temp_file = fopen("/tmp/public_key.txt", "w"); - fprintf(temp_file, "%llu\n", private_key.P); - fprintf(temp_file, "%llu\n", private_key.E); - fprintf(temp_file, "%llu", private_key.Q); - fclose(temp_file); - // TODO: get what go produces - // compare what go produces to ours. - return 0; -} - -int test_crypto_x509_private_to_der() { - - struct RsaPrivateKey private_key; - private_key.P = 6908992579533823845; - private_key.E = 65537; - //crypto_rsa_generate_keypair(&private_key, 2048); - unsigned char buffer[1600]; - unsigned char* c = buffer; - libp2p_crypto_encoding_x509_private_key_to_der(&private_key, &c); + if (private_key.der_length == 0) + return 0; + if (private_key.der == NULL) + return 0; return 1; }