diff --git a/crypto/encoding/base58.c b/crypto/encoding/base58.c new file mode 100644 index 0000000..73f4a26 --- /dev/null +++ b/crypto/encoding/base58.c @@ -0,0 +1,199 @@ +/* + * Copyright 2012-2014 Luke Dashjr + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the standard MIT license. See COPYING for more details. + */ + +#include +#include + +static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +static const int8_t b58digits_map[] = { + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, + -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, + 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, + -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, + 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, +}; + +/** + * convert a base58 encoded string into a binary array + * @param b58 the base58 encoded string + * @param base58_size the size of the encoded string + * @param bin the results buffer + * @param binszp the size of the results buffer + * @returns true(1) on success + */ +int libp2p_crypto_encoding_base58_decode(const char* b58, size_t base58_size, unsigned char** bin, size_t* binszp) +{ + size_t binsz = *binszp; + const unsigned char* b58u = (const void*)b58; + unsigned char* binu = *bin; + size_t outisz = (binsz + 3) / 4; + uint32_t outi[outisz]; + uint64_t t; + uint32_t c; + size_t i, j; + uint8_t bytesleft = binsz % 4; + uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; + unsigned zerocount = 0; + size_t b58sz; + + b58sz = strlen(b58); + + memset(outi, 0, outisz * sizeof(*outi)); + + // Leading zeros, just count + for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) { + ++zerocount; + } + + for (; i < b58sz; ++i) { + if (b58u[i] & 0x80) { + // High-bit set on invalid digit + return 0; + } + if (b58digits_map[b58u[i]] == -1) { + // Invalid base58 digit + return 0; + } + c = (unsigned)b58digits_map[b58u[i]]; + for (j = outisz; j--;) { + t = ((uint64_t)outi[j]) * 58 + c; + c = (t & 0x3f00000000) >> 32; + outi[j] = t & 0xffffffff; + } + if (c) { + // Output number too big (carry to the next int32) + memset(outi, 0, outisz * sizeof(*outi)); + return 0; + } + if (outi[0] & zeromask) { + // Output number too big (last int32 filled too far) + memset(outi, 0, outisz * sizeof(*outi)); + return 0; + } + } + + j = 0; + switch (bytesleft) { + case 3: + *(binu++) = (outi[0] & 0xff0000) >> 16; + case 2: + *(binu++) = (outi[0] & 0xff00) >> 8; + case 1: + *(binu++) = (outi[0] & 0xff); + ++j; + default: + break; + } + + for (; j < outisz; ++j) { + *(binu++) = (outi[j] >> 0x18) & 0xff; + *(binu++) = (outi[j] >> 0x10) & 0xff; + *(binu++) = (outi[j] >> 8) & 0xff; + *(binu++) = (outi[j] >> 0) & 0xff; + } + + // Count canonical base58 byte count + binu = *bin; + for (i = 0; i < binsz; ++i) { + if (binu[i]) { + break; + } + --*binszp; + } + *binszp += zerocount; + + memset(outi, 0, outisz * sizeof(*outi)); + return 1; +} + +/** + * encode an array of bytes into a base58 string + * @param binary_data the data to be encoded + * @param binary_data_size the size of the data to be encoded + * @param base58 the results buffer + * @param base58_size the size of the results buffer + * @returns true(1) on success + */ +//int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char* base58, size_t* base58_size) +int libp2p_crypto_encoding_base58_encode(const unsigned char* data, size_t binsz, unsigned char** b58, size_t* b58sz) +{ + const uint8_t* bin = data; + int carry; + ssize_t i, j, high, zcount = 0; + size_t size; + + while (zcount < (ssize_t)binsz && !bin[zcount]) { + ++zcount; + } + + size = (binsz - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memset(buf, 0, size); + + for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) { + for (carry = bin[i], j = size - 1; (j > high) || carry; --j) { + carry += 256 * buf[j]; + buf[j] = carry % 58; + carry /= 58; + } + } + + for (j = 0; j < (ssize_t)size && !buf[j]; ++j) + ; + + if (*b58sz <= zcount + size - j) { + *b58sz = zcount + size - j + 1; + memset(buf, 0, size); + return 0; + } + + if (zcount) { + memset(b58, '1', zcount); + } + for (i = zcount; j < (ssize_t)size; ++i, ++j) { + (*b58)[i] = b58digits_ordered[buf[j]]; + } + (*b58)[i] = '\0'; + *b58sz = i + 1; + + memset(buf, 0, size); + return 1; +} + +/*** + * calculate the size of the binary results based on an incoming base58 string + * @param base58_string the string + * @returns the size in bytes had the string been decoded + */ +size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string) { + size_t string_length = strlen((char*)base58_string); + size_t decoded_length = 0; + size_t radix = strlen(b58digits_ordered); + double bits_per_digit = log2(radix); + + decoded_length = floor(string_length * bits_per_digit / 8); + return decoded_length; +} + +/** + * calculate the max length in bytes of an encoding of n source bits + * @param base58_string the string + * @returns the maximum size in bytes had the string been decoded + */ +size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string) { + size_t string_length = strlen((char*)base58_string); + size_t decoded_length = 0; + size_t radix = strlen(b58digits_ordered); + double bits_per_digit = log2(radix); + + decoded_length = ceil(string_length * bits_per_digit / 8); + return decoded_length; +} diff --git a/crypto/encoding/x509.c b/crypto/encoding/x509.c new file mode 100644 index 0000000..457c140 --- /dev/null +++ b/crypto/encoding/x509.c @@ -0,0 +1,68 @@ +// +// x509.c +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#include +#include + +#include "mbedtls/rsa.h" +#include "mbedtls/pk.h" +#include "mbedtls/ctr_drbg.h" + +#include "libp2p/crypto/encoding/x509.h" + +/** + * public methods + */ + +/** + * convert a RSA Private Key to an array of bytes in DER format + * @param private_key the private key + * @param bytes where to put the resultant bytes + * @returns true(1) on success + */ +int libp2p_crypto_encoding_x509_private_key_to_der(struct RsaPrivateKey* private_key, unsigned char* bytes[1600]) { + + // get everything setup + mbedtls_pk_context ctx; + mbedtls_pk_init( &ctx); + + mbedtls_pk_setup( &ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); + + mbedtls_rsa_context* rsa = mbedtls_pk_rsa( ctx ); + + // set the values in the context + mbedtls_mpi N; + mbedtls_mpi_init(&N); + mbedtls_mpi_lset(&N, private_key->prime1); + + mbedtls_mpi E; + mbedtls_mpi_init(&E); + mbedtls_mpi_lset(&E, private_key->private_exponent); + + rsa->N = N; + rsa->E = E; + rsa->len = ( mbedtls_mpi_bitlen(&rsa->N ) + 7) >> 3; + + // now write to DER + mbedtls_pk_write_key_der(&ctx, *bytes, 1600); + + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&E); + mbedtls_rsa_free(rsa); + mbedtls_pk_free(&ctx); + + return 1; +} + +int libp2p_crypto_encoding_x509_der_to_private_key(unsigned char* der, size_t der_length, struct RsaPrivateKey* private_key) { + mbedtls_pk_context ctx; + mbedtls_pk_init(&ctx); + + mbedtls_pk_parse_key(&ctx, der, der_length, NULL, 0); + return 1; +} diff --git a/crypto/rsa.c b/crypto/rsa.c index 0ada9c0..02130a6 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -76,3 +76,15 @@ 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 + */ +int crypto_rsa_public_key_bytes(struct RsaPublicKey* public_key, char** bytes, unsigned long long* bytes_size) { + // marshal to x509 + return 0; +} + diff --git a/crypto/x509.c b/crypto/x509.c deleted file mode 100644 index e69de29..0000000 diff --git a/include/libp2p/crypto/encoding/base58.h b/include/libp2p/crypto/encoding/base58.h new file mode 100644 index 0000000..0d238f2 --- /dev/null +++ b/include/libp2p/crypto/encoding/base58.h @@ -0,0 +1,47 @@ +// +// base58.h +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#ifndef base58_h +#define base58_h + +/** + * convert a base58 encoded string into a binary array + * @param base58 the base58 encoded string + * @param base58_size the size of the encoded string + * @param binary_data the results buffer + * @param binary_data_size the size of the results buffer + * @returns true(1) on success + */ +int libp2p_crypto_encoding_base58_decode(const unsigned char* base58, size_t base58_size, unsigned char** binary_data, size_t *binary_data_size); + +/** + * encode an array of bytes into a base58 string + * @param binary_data the data to be encoded + * @param binary_data_size the size of the data to be encoded + * @param base58 the results buffer + * @param base58_size the size of the results buffer + * @returns true(1) on success + */ +int libp2p_crypto_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char** base58, size_t* base58_size); + +/*** + * calculate the size of the binary results based on an incoming base58 string with no initial padding + * @param base58_string the string + * @returns the size in bytes had the string been decoded + */ +size_t libp2p_crypto_encoding_base58_decode_size(const unsigned char* base58_string); + +/** + * calculate the max length in bytes of an encoding of n source bits + * @param base58_string the string + * @returns the maximum size in bytes had the string been decoded + */ +size_t libp2p_crypto_encoding_base58_decode_max_size(const unsigned char* base58_string); + + +#endif /* base58_h */ diff --git a/include/libp2p/crypto/encoding/x509.h b/include/libp2p/crypto/encoding/x509.h new file mode 100644 index 0000000..1e64cdc --- /dev/null +++ b/include/libp2p/crypto/encoding/x509.h @@ -0,0 +1,18 @@ +// +// x509.h +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#ifndef __LIBP2P_CRYPTO_ENCODING_X509_H__ +#define __LIBP2P_CRYPTO_ENCODING_X509_H__ + +#include "libp2p/crypto/rsa.h" + +int libp2p_crypto_encoding_x509_private_key_to_der(struct RsaPrivateKey* private_key, unsigned char* bytes[1600]); + +int libp2p_crypto_encoding_x509_der_to_private_key(unsigned char* der, size_t der_length, struct RsaPrivateKey* private_key); + +#endif /* x509_h */ diff --git a/include/libp2p/crypto/rsa.h b/include/libp2p/crypto/rsa.h index c886ed7..f96e40c 100644 --- a/include/libp2p/crypto/rsa.h +++ b/include/libp2p/crypto/rsa.h @@ -43,5 +43,13 @@ 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 + */ +int crypto_rsa_public_key_bytes(struct RsaPublicKey* public_key, char** bytes, unsigned long long* bytes_size); + #endif /* rsa_h */ diff --git a/include/libp2p/multihash/multihash.h b/include/libp2p/multihash/multihash.h new file mode 100644 index 0000000..687d980 --- /dev/null +++ b/include/libp2p/multihash/multihash.h @@ -0,0 +1,61 @@ +/** + * An implementation of the multihash protocol in C + */ + +#ifndef __LIBP2P_MULTIHASH_H +#define __LIBP2P_MULTIHASH_H + +#define MULTIHASH_SHA1 0x11 +#define MULTIHASH_SHA2_256 0x12 +#define MULTIHASH_SHA2_512 0x13 +#define MULTIHASH_SHA3_512 0x14 +#define MULTIHASH_SHA3_384 0x15 +#define MULTIHASH_SHA3_256 0x16 +#define MULTIHASH_SHA3_224 0x17 +#define MULTIHASH_SHAKE_128 0x18 +#define MULTIHASH_SHAKE_256 0x19 +#define MULTIHASH_BLAKE2B 0x20 +#define MULTIHASH_BLAKE2S 0x21 + +struct MultiHash { + char fn_code; + char size; + unsigned char* data; +}; + +char* libp2p_multihash_get_fn_name(char fn_code); + +/** + * encodes the multihash into a hex string + */ +int libp2p_multihash_hex_string(struct MultiHash* hash, char* string, int max_length); + +/** + * decodes a hex string into a multihash + */ +int libp2p_multihash_from_hex_string(char* string, int length, struct MultiHash* hash); + +/** + * turns a multihash into a b58 string + * @param hash the Multihash to encode + * @param binary_buffer the buffer to fill + * @param max_length the size of the buffer + * @returns true(1) on success + */ +int libp2p_multihash_to_b58(struct MultiHash* hash, unsigned char* binary_buffer, size_t max_length); + +/** + * turns a base58 encoded string into a MultiHash + * @param b58_string the base58 encoded string + * @param b58_string_length the length of the encoded string + * @param hash the MultiHash to fill + * @returns true(1) on success + */ +int libp2p_b58_to_multihash(unsigned char* b58_string, size_t b58_string_length, struct MultiHash* hash); + +/** + * retrieve the size required for the multihash that is embedded in the base58 encoded string + */ +size_t libp2p_multihash_b58_size(unsigned char* b58_string); + +#endif /* multihash_h */ diff --git a/multihash/multihash.c b/multihash/multihash.c new file mode 100644 index 0000000..a2f560e --- /dev/null +++ b/multihash/multihash.c @@ -0,0 +1,186 @@ +// +// multihash.c +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#include +#include +#include + +#include "libp2p/multihash/multihash.h" +#include "libp2p/crypto/encoding/base58.h" + + +char* libp2p_multihash_get_fn_name(char fn_code) { + switch(fn_code) { + case (0x11): + return "sha1"; + case(0x12): + return "sha2-256"; + case(0x13): + return "sha2-512"; + case(0x14): + return "sha3-512"; + case(0x15): + return "sha3-384"; + case(0x16): + return "sha3-256"; + case(0x17): + return "sha3-224"; + case(0x18): + return "shake-128"; + case(0x19): + return "shake-256"; + case(0x20): + return "blake2b"; + case(0x21): + return "blake2s"; + } + return 0x00; +} + +/** + * helper function to convert a char string to a byte + * @param s the string (only grabs the first character) + * @returns the value of the char + */ +unsigned char from_hex_to_char(const char* s) { + // make sure there is a null in position 3 + char buff[3]; + buff[0] = s[0]; + buff[1] = s[1]; + buff[2] = 0; + char* ptr = &buff[2]; + return strtoul(buff, &ptr, 16); +} + +/*** + * convert a MultiHash into a byte array + * @param hash the MultiHash to convert + * @param results the resultant byte array + * @param max_length the maximum length of the byte array + * @returns true(1) on success + */ +int from_multihash_to_byte_array(struct MultiHash* hash, unsigned char* results, size_t max_length) { + // what size is needed? + int required_size = hash->size + 2; + + if (required_size < max_length) + return 0; + + results[0] = hash->fn_code; + results[1] = hash->size; + + // now copy in the data + for(int i = 0; i < hash->size; i++) + results[i+2] = hash->data[i]; + + return 1; +} + +/*** + * public methods + **/ + +/*** + * retrieve the size element of the multihash object that is embedded in the base58 string + * @param b58_string the base58 encoded string + * @returns the size element of the MultiHash object + */ +size_t libp2p_multihash_b58_size(unsigned char* b58_string) { + size_t byte_length = libp2p_crypto_encoding_base58_decode_max_size(b58_string); + unsigned char bytes[byte_length]; + unsigned char* ptr = bytes; + + int retVal = libp2p_crypto_encoding_base58_decode(b58_string, strlen((char*)b58_string), &ptr, &byte_length); + if (retVal == 0) + return 0; + + return ptr[1]; +} + +/** + * turns a multihash into a string of hex + */ +int libp2p_multihash_hex_string(struct MultiHash* hash, char* string, int max_length) { + // calculate the size of the struct + size_t struct_size = sizeof(char) * (hash->size + 2); + + // make sure we have enough space (2 bytes for each byte, plus terminating null + if (max_length < (struct_size * 2)) + return 0; + + // put in the hex values + char temp[3]; + sprintf(temp, "%02x", hash->fn_code); + string[0] = temp[0]; + string[1] = temp[1]; + sprintf(temp, "%02x", hash->size); + string[2] = temp[0]; + string[3] = temp[1]; + for(int i = 0; i < struct_size - 2; i++) { + sprintf(temp, "%02x", hash->data[i]); + string[(i*2) + 4] = temp[0]; + string[(i*2) + 5] = temp[1]; + } + return 1; +} + +/** + * decodes a hex string into a multihash + */ +int libp2p_multihash_from_hex_string(char* string, int length, struct MultiHash* hash) { + hash->fn_code = from_hex_to_char(&string[0]); + hash->size = from_hex_to_char(&string[2]); + for(int i = 0; i < hash->size; i++) { + int pos = (i * 2) + 4; + if (pos > length - 1) + return 0; + hash->data[i] = from_hex_to_char(&string[(i*2) + 4]); + } + return 1; +} + +/** + * turns a multihash into a b58 string + * @param hash the Multihash to encode + * @param binary_buffer the buffer to fill + * @param max_length the size of the buffer + * @returns true(1) on success +*/ +int libp2p_multihash_to_b58(struct MultiHash* hash, unsigned char* binary_buffer, size_t max_length) { + int bytes_length = hash->size + 2; + unsigned char bytes[bytes_length]; + unsigned char* ptr = bytes; + + int retVal = from_multihash_to_byte_array(hash, bytes, bytes_length); + if (retVal == 0) + return 0; + + // finally encode the array into base64 + return libp2p_crypto_encoding_base58_encode(ptr, bytes_length, &binary_buffer, &max_length); +} + +/** + * turns a base58 encoded string into a MultiHash + * @param b58_string the base58 encoded string + * @param b58_string_length the length of the encoded string + * @param hash the MultiHash to fill + * @returns true(1) on success + */ +int libp2p_b58_to_multihash(unsigned char* b58_string, size_t b58_string_length, struct MultiHash* hash) { + size_t buffer_size = libp2p_crypto_encoding_base58_decode_max_size(b58_string); + unsigned char buffer[buffer_size]; + unsigned char* b = buffer; + + libp2p_crypto_encoding_base58_decode(b58_string, b58_string_length, &b, &buffer_size); + + // now build the hash + hash->fn_code = b[0]; + hash->size = b[1]; + memcpy(hash->data, &b[2], hash->size); + return 0; +} diff --git a/test/crypto/test_base58.h b/test/crypto/test_base58.h new file mode 100644 index 0000000..6830e24 --- /dev/null +++ b/test/crypto/test_base58.h @@ -0,0 +1,76 @@ +// +// test_base58.h +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#ifndef test_base58_h +#define test_base58_h + +#include "libp2p/crypto/encoding/base58.h" + +/*** + * tests the base58 encoding and decoding + */ +int test_base58_encode_decode() { + + unsigned char original[3] = { 0x41, 0x42 ,0x00 }; + + size_t buffer_size = 10; + unsigned char buffer[buffer_size]; + unsigned char* ptr = buffer; + + int retVal = libp2p_crypto_encoding_base58_encode(original, 3, &ptr, &buffer_size); + if (retVal == 0) + return 0; + + size_t result_size = 3; + unsigned char result[result_size]; + unsigned char* ptr2 = result; + memset(result, 0, result_size); + + retVal = libp2p_crypto_encoding_base58_decode(ptr, buffer_size, &ptr2, &result_size); + if (retVal == 0) + return 0; + + for (int i = 0; i < 3; i++) + if (original[i] != result[i]) + return 0; + + return 1; +} + +int test_base58_size() { + unsigned char* unencoded = (unsigned char*)"Hello, World!"; + size_t string_length = strlen((char*)unencoded) + 1; + + size_t encoded_length = 100; + unsigned char encoded[encoded_length]; + unsigned char* ptr = encoded; + + // now encode it + libp2p_crypto_encoding_base58_encode(unencoded, string_length, &ptr, &encoded_length); + + size_t size_enc = libp2p_crypto_encoding_base58_decode_size(ptr); + size_t max_size_enc = libp2p_crypto_encoding_base58_decode_max_size(ptr); + + if (size_enc <= string_length && max_size_enc >= string_length) + return 1; + + return 0; + +} + +int test_base58_max_size() { + unsigned char hash[5] = {'S', 'D', 'Y', 'h', 'd' }; + + size_t results = libp2p_crypto_encoding_base58_decode_max_size(hash); + if (results != 4) + return 0; + + return 1; +} + +#endif /* test_base58_h */ diff --git a/test/crypto/test_rsa.h b/test/crypto/test_rsa.h new file mode 100644 index 0000000..110ad7a --- /dev/null +++ b/test/crypto/test_rsa.h @@ -0,0 +1,65 @@ +// +// test_rsa.h +// libp2p_xcode +// +// Created by John Jones on 11/3/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#ifndef test_rsa_h +#define test_rsa_h + +#include +#include +#include + +#include "libp2p/crypto/rsa.h" +#include "libp2p/crypto/encoding/base64.h" +#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 + */ +int test_crypto_rsa_public_key_bytes() { + // first we need a public key + 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.public_key.modulus); + fprintf(temp_file, "%llu", private_key.public_key.exponent); + 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.prime1 = 6908992579533823845; + private_key.private_exponent = 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); + return 1; +} + +int test_crypto_x509_der_to_private() { + char* der = "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="; + size_t b64_length = base64_decode_length((unsigned char*)der, strlen(der)); + unsigned char buffer[b64_length]; + unsigned char* b = buffer; + size_t ultimate_length; + int retVal = base64_decode((unsigned char*)der, strlen(der), b, b64_length, &ultimate_length); + if (retVal == 0) + return 0; + struct RsaPrivateKey private_key; + libp2p_crypto_encoding_x509_der_to_private_key(b, ultimate_length, &private_key); + return 1; +} + +#endif /* test_rsa_h */ diff --git a/test/multihash/test_multihash.h b/test/multihash/test_multihash.h new file mode 100644 index 0000000..af33f0f --- /dev/null +++ b/test/multihash/test_multihash.h @@ -0,0 +1,122 @@ +// +// test_multihash.h +// libp2p_xcode +// +// Created by John Jones on 11/7/16. +// Copyright © 2016 JMJAtlanta. All rights reserved. +// + +#ifndef test_multihash_h +#define test_multihash_h + +#include "libp2p/multihash/multihash.h" +#include "libp2p/crypto/encoding/base58.h" + +int test_multihash_encode() { + struct MultiHash hash; + hash.fn_code = MULTIHASH_SHA1; + hash.size = 2; + unsigned char data[] = "A"; + hash.data = data; + // 8 bytes plus terminating null to make it easier to debug + // note: function does not clear the buffer, so we have to + char buffer[9]; + char* b = buffer; + memset(b, 0, 9); + int retVal = libp2p_multihash_hex_string(&hash, b, 9); + if (retVal == 0) + return 0; + + if (b[0] != '1' && b[1] != '1') + return 0; + if (b[2] != '0' && b[3] != '2') + return 0; + if (b[4] != '4' && b[5] != '1') + return 0; + if (b[6] != '0' && b[7] != '0') + return 0; + return 1; +} + +int test_multihash_decode() { + char in[9] = "11024100"; + char* string = in; + struct MultiHash hash; + + int retVal = libp2p_multihash_from_hex_string(string, 8, &hash); + if (retVal == 0) + return 0; + + if (hash.fn_code != 0x11) + return 0; + if (hash.size != 2) + return 0; + if (hash.data[0] != 0x41 || hash.data[1] != 0x00) + return 0; + return 1; +} + +int test_multihash_base58_decode() { + unsigned char original[5] = { 'S', 'D', 'Y', 'h', 'd' }; + + size_t buffer_len = 4; + unsigned char buffer[buffer_len]; + unsigned char* ptr = buffer; + + int retVal = libp2p_crypto_encoding_base58_decode(original, 5, &ptr, &buffer_len); + if (retVal == 0) + return 0; + if (buffer[0] != 0x11) + return 0; + if (buffer[1] != 0x02) + return 0; + + return 1; +} + +int test_multihash_size() { + unsigned char hash[6] = {'S', 'D', 'Y', 'h', 'd' ,0 }; + unsigned char* ptr = hash; + size_t sz = libp2p_multihash_b58_size(ptr); + + return sz == 2; +} + +int test_multihash_base58_encode_decode() { + // build the original MultiHash + struct MultiHash original; + original.fn_code = MULTIHASH_SHA1; + original.size = 2; + unsigned char data[] = "A"; + original.data = data; + + // have a buffer to store the base58 encoding + size_t buffer_size = 65535; + unsigned char buffer[buffer_size]; + unsigned char* b = buffer; + + // encode it + libp2p_multihash_to_b58(&original, b, buffer_size); + + // build a place to store the new MultiHash + struct MultiHash results; + results.size = 2; + unsigned char results_data[2]; + results.data = results_data; + + // decode it + libp2p_b58_to_multihash(b, strlen((char*)b), &results); + + // compare + if (original.fn_code != results.fn_code) + return 0; + if (original.size != results.size) + return 0; + if (original.data[0] != results.data[0]) + return 0; + if (original.data[1] != results.data[1]) + return 0; + return 1; +} + +#endif /* test_multihash_h */ diff --git a/test/testit.c b/test/testit.c index bab82e3..0c2795f 100644 --- a/test/testit.c +++ b/test/testit.c @@ -1,6 +1,10 @@ #include +#include "crypto/test_rsa.h" +#include "multihash/test_multihash.h" +#include "crypto/test_base58.h" + int testit(const char* name, int (*func)(void)) { printf("Testing %s...\n", name); int retVal = func(); @@ -12,8 +16,17 @@ int testit(const char* name, int (*func)(void)) { } int main(int argc, char** argv) { - //testit("test_repo_config_init", test_repo_config_init); - + //testit("test_crypto_rsa_public_key_bytes", test_crypto_rsa_public_key_bytes); + //testit("test_crypto_x509_private_to_der", test_crypto_x509_private_to_der); + //testit("test_crypto_x509_der_to_private", test_crypto_x509_der_to_private); + testit("test_multihash_encode", test_multihash_encode); + testit("test_multihash_decode", test_multihash_decode); + testit("test_multihash_base58_encode_decode", test_multihash_base58_encode_decode); + testit("test_multihash_base58_decode", test_multihash_base58_decode); + testit("test_base58_encode_decode", test_base58_encode_decode); + testit("test_base58_size", test_base58_size); + testit("test_base58_max_size", test_base58_max_size); + testit("test_multihash_size", test_multihash_size); return 1; }