diff --git a/other/fun/BUILD.bazel b/other/fun/BUILD.bazel index e730427d89..7ce4acf128 100644 --- a/other/fun/BUILD.bazel +++ b/other/fun/BUILD.bazel @@ -21,8 +21,25 @@ cc_binary( ) cc_binary( - name = "minimal-save-generator", - srcs = ["minimal-save-generator.c"], + name = "create_minimal_savedata", + srcs = ["create_minimal_savedata.c", "create_common.h"], + deps = [ + "@libsodium", + ], +) + +cc_binary( + name = "create_savedata", + srcs = ["create_savedata.c", "create_common.h"], + deps = [ + "//c-toxcore/toxcore", + "@libsodium", + ], +) + +cc_binary( + name = "create_bootstrap_keys", + srcs = ["create_bootstrap_keys.c", "create_common.h"], deps = [ "@libsodium", ], diff --git a/other/fun/create_bootstrap_keys.c b/other/fun/create_bootstrap_keys.c new file mode 100644 index 0000000000..8419c11065 --- /dev/null +++ b/other/fun/create_bootstrap_keys.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * Creates bootstrap keys data for a given secret key, if provided, or a random key otherwise. + * The data is written to stderr, human-readable key info is written to stdout. + * + * Build: gcc -o create_bootstrap_keys create_bootstrap_key.c -lsodium -std=c99 + * + * Usage: ./create_bootstrap_key [secret-key] 2>data + */ +#include + +#include "create_common.h" + +int main(const int argc, const char *const argv[]) +{ + init_sodium(); + + unsigned char public_key[crypto_box_PUBLICKEYBYTES]; + unsigned char secret_key[crypto_box_SECRETKEYBYTES]; + handle_args(argc, argv, "Creates bootstrap keys data", public_key, secret_key); + + print_keys(public_key, secret_key); + + fwrite(public_key, sizeof(public_key), 1, stderr); + fwrite(secret_key, sizeof(secret_key), 1, stderr); + + return 0; +} diff --git a/other/fun/create_common.h b/other/fun/create_common.h new file mode 100644 index 0000000000..6f27f67ed2 --- /dev/null +++ b/other/fun/create_common.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * Shared functions of create_*.c programs. + */ +#include +#include +#include +#include + +#include + +static void init_sodium(void) +{ + if (sodium_init() < 0) { + printf("Error: Failed to initialize sodium.\n"); + exit(1); + } +} + +static int tox_strcasecmp(const char *s1, const char *s2) +{ + while (true) { + const int c1 = tolower(*(s1++)); + const int c2 = tolower(*(s2++)); + + if (c1 == '\0' || c2 == '\0' || c1 != c2) { + return c1 - c2; + } + } +} + +static void print_usage(const char *const argv0, const char *const does_what) +{ + printf("%s for a given secret key, if provided, or a random key otherwise.\n", does_what); + printf("The data is written to stderr, human-readable key info is written to stdout.\n"); + printf("\nUsage: %s [secret-key] 2>data\n", argv0); +} + +static void handle_args(const int argc, const char *const argv[], const char *const does_what, + unsigned char *const public_key, unsigned char *const secret_key) +{ + if (argc == 2 && (!tox_strcasecmp(argv[1], "-h") || !tox_strcasecmp(argv[1], "--help"))) { + print_usage(argv[0], does_what); + exit(0); + } + + if (argc == 1) { + crypto_box_keypair(public_key, secret_key); + } else if (argc == 2 && strlen(argv[1]) == crypto_box_SECRETKEYBYTES * 2) { + size_t bin_len = 0; + + if (sodium_hex2bin(secret_key, crypto_box_SECRETKEYBYTES, argv[1], crypto_box_SECRETKEYBYTES * 2, nullptr, &bin_len, + nullptr) != 0 || bin_len != crypto_box_SECRETKEYBYTES) { + printf("Error: Secret key must be a hex string.\n"); + exit(1); + } + + crypto_scalarmult_base(public_key, secret_key); + } else if (argc == 2) { + printf("Error: Secret key must be a %d character hex string.\n", crypto_box_SECRETKEYBYTES * 2); + exit(1); + } else { + print_usage(argv[0], does_what); + exit(1); + } +} + +static void bin2hex_toupper(char *const hex, const size_t hex_maxlen, const unsigned char *const bin, + const size_t bin_len) +{ + sodium_bin2hex(hex, hex_maxlen, bin, bin_len); + + for (size_t i = 0; i < hex_maxlen; i ++) { + hex[i] = (char)toupper(hex[i]); + } +} + +static void print_keys(const unsigned char *const public_key, const unsigned char *const secret_key) +{ + char public_key_str[crypto_box_PUBLICKEYBYTES * 2 + 1]; + char secret_key_str[crypto_box_SECRETKEYBYTES * 2 + 1]; + bin2hex_toupper(public_key_str, sizeof(public_key_str), public_key, crypto_box_PUBLICKEYBYTES); + bin2hex_toupper(secret_key_str, sizeof(secret_key_str), secret_key, crypto_box_SECRETKEYBYTES); + fprintf(stdout, "Public key: %s\n", public_key_str); + fprintf(stdout, "Secret key: %s\n", secret_key_str); +} diff --git a/other/fun/create_minimal_savedata.c b/other/fun/create_minimal_savedata.c new file mode 100644 index 0000000000..639479e47b --- /dev/null +++ b/other/fun/create_minimal_savedata.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * Creates minimal Tox savedata for a given secret key, if provided, or a random key otherwise. + * The data is written to stderr, human-readable key info is written to stdout. + * + * Build: gcc -o create_minimal_savedata create_minimal_savedata.c -lsodium -std=c99 + * + * Usage: ./create_minimal_savedata [secret-key] 2>data + */ +#include + +#include + +#include "create_common.h" + +int main(const int argc, const char *const argv[]) +{ + init_sodium(); + + unsigned char public_key[crypto_box_PUBLICKEYBYTES]; + unsigned char secret_key[crypto_box_SECRETKEYBYTES]; + handle_args(argc, argv, "Creates minimal Tox savedata", public_key, secret_key); + + print_keys(public_key, secret_key); + + // (uint32_t) 0x00000000, (uint32_t) STATE_COOKIE_GLOBAL 0x15ed1b1f, + // (uint32_t) crypto_box_PUBLICKEYBYTES+crypto_box_SECRETKEYBYTES+sizeof(uint32_t) 0x00000044, + // (uint16_t) STATE_TYPE_NOSPAMKEYS 0x0001, (uint16_t) STATE_COOKIE_TYPE 0x01ce, (uint32_t) nospam 0x00000000 + const char tox_file[] = "\x00\x00\x00\x00\x1f\x1b\xed\x15\x44\x00\x00\x00\x01\x00\xce\x01\x00\x00\x00\x00"; + fwrite(tox_file, sizeof(tox_file) - 1, 1, stderr); + fwrite(public_key, sizeof(public_key), 1, stderr); + fwrite(secret_key, sizeof(secret_key), 1, stderr); + + unsigned char checksum[2] = {0}; + + for (size_t i = 0; i < crypto_box_PUBLICKEYBYTES; i ++) { + checksum[i % 2] ^= public_key[i]; + } + + char checksum_str[sizeof(checksum) * 2 + 1]; + bin2hex_toupper(checksum_str, sizeof(checksum_str), checksum, sizeof(checksum)); + char public_key_str[crypto_box_PUBLICKEYBYTES * 2 + 1]; + bin2hex_toupper(public_key_str, sizeof(public_key_str), public_key, crypto_box_PUBLICKEYBYTES); + fprintf(stdout, "Tox Id: %s00000000%s\n", public_key_str, checksum_str); + + return 0; +} diff --git a/other/fun/create_savedata.c b/other/fun/create_savedata.c new file mode 100644 index 0000000000..ed9d0d874c --- /dev/null +++ b/other/fun/create_savedata.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * Creates Tox savedata for a given secret key, if provided, or a random key otherwise. + * The data is written to stderr, human-readable key info is written to stdout. + * + * Build: gcc -o create_savedata create_savedata.c -lsodium -ltoxcore -std=c99 + * + * Usage: ./create_savedata [secret-key] 2>data + */ +#include +#include +#include + +#include + +#include "../../toxcore/tox.h" +#include "create_common.h" + +static bool create_tox(const unsigned char *const secret_key, Tox **const tox) +{ + Tox_Err_Options_New options_error; + struct Tox_Options *const options = tox_options_new(&options_error); + + if (options_error != TOX_ERR_OPTIONS_NEW_OK) { + tox_options_free(options); + return false; + } + + tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY); + tox_options_set_savedata_data(options, secret_key, crypto_box_SECRETKEYBYTES); + Tox_Err_New tox_error; + *tox = tox_new(options, &tox_error); + + if (tox_error != TOX_ERR_NEW_OK) { + tox_options_free(options); + return false; + } + + tox_options_free(options); + return true; +} + +static bool print_savedata(Tox *const tox) +{ + const size_t savedata_size = tox_get_savedata_size(tox); + uint8_t *const savedata = (uint8_t *const)malloc(savedata_size); + + if (savedata == nullptr) { + tox_kill(tox); + return false; + } + + tox_get_savedata(tox, savedata); + fwrite(savedata, savedata_size, 1, stderr); + free(savedata); + return true; +} + +static bool print_tox_id(const Tox *const tox) +{ + uint8_t *const tox_id = (uint8_t *const)malloc(tox_address_size()); + + if (tox_id == nullptr) { + return false; + } + + tox_self_get_address(tox, tox_id); + const size_t tox_id_str_size = tox_address_size() * 2 + 1; + char *const tox_id_str = (char *const)malloc(tox_id_str_size); + + if (tox_id_str == nullptr) { + free(tox_id); + return false; + } + + bin2hex_toupper(tox_id_str, tox_id_str_size, tox_id, tox_address_size()); + fprintf(stdout, "Tox Id: %s\n", tox_id_str); + free(tox_id_str); + free(tox_id); + return true; +} + +int main(const int argc, const char *const argv[]) +{ + init_sodium(); + + unsigned char public_key[crypto_box_PUBLICKEYBYTES]; + unsigned char secret_key[crypto_box_SECRETKEYBYTES]; + handle_args(argc, argv, "Creates Tox savedata", public_key, secret_key); + + print_keys(public_key, secret_key); + + Tox *tox; + + if (!create_tox(secret_key, &tox)) { + printf("Error: Failed to create a Tox instance.\n"); + return 1; + } + + if (!print_savedata(tox)) { + printf("Error: Failed to print savedata.\n"); + tox_kill(tox); + return 1; + } + + if (!print_tox_id(tox)) { + printf("Error: Failed to print Tox ID.\n"); + tox_kill(tox); + return 1; + } + + tox_kill(tox); + + return 0; +} diff --git a/other/fun/minimal-save-generator.c b/other/fun/minimal-save-generator.c deleted file mode 100644 index b4833ea887..0000000000 --- a/other/fun/minimal-save-generator.c +++ /dev/null @@ -1,62 +0,0 @@ -/* minimal-save-generator -- Minimal Save Generator - * - * Generates a minimal Tox savedata file that can be used in clients. - * Prints the savedata file to stderr, prints information to stdout. - * - * Requires sodium library. - * - * Usage: minimal-save-generator 2> profile.tox - * - * Compile: gcc minimal-save-generator.c -o minimal-save-generator -lsodium -*/ - -#include -#include -#include - -#include - -int main(void) -{ - unsigned char public_key[crypto_box_PUBLICKEYBYTES]; - unsigned char secret_key[crypto_box_SECRETKEYBYTES]; - crypto_box_keypair(public_key, secret_key); - - // print new tox savedata to stderr - char tox_file[] = "\x00\x00\x00\x00\x1f\x1b\xed\x15\x44\x00\x00\x00\x01\x00\xce\x01\x00\x00\x00\x00"; - fwrite(tox_file, sizeof(tox_file) - 1, 1, stderr); - fwrite(public_key, sizeof(public_key), 1, stderr); - fwrite(secret_key, sizeof(secret_key), 1, stderr); - - // print info on it to stdout - char public_key_str[crypto_box_PUBLICKEYBYTES * 2 + 1]; - char secret_key_str[crypto_box_SECRETKEYBYTES * 2 + 1]; - sodium_bin2hex(public_key_str, sizeof(public_key_str), public_key, sizeof(public_key)); - sodium_bin2hex(secret_key_str, sizeof(secret_key_str), secret_key, sizeof(secret_key)); - - for (size_t i = 0; i < sizeof(public_key_str); i ++) { - public_key_str[i] = toupper(public_key_str[i]); - secret_key_str[i] = toupper(secret_key_str[i]); - } - - fprintf(stdout, "Public key: %s\n", public_key_str); - fprintf(stdout, "Secret key: %s\n", secret_key_str); - - // calculate checksum for tox id printing - unsigned char checksum[2] = {0}; - - for (size_t i = 0; i < crypto_box_PUBLICKEYBYTES; i ++) { - checksum[i % 2] ^= public_key[i]; - } - - char checksum_str[sizeof(checksum) * 2 + 1]; - sodium_bin2hex(checksum_str, sizeof(checksum_str), checksum, sizeof(checksum)); - - for (size_t i = 0; i < sizeof(checksum_str); i ++) { - checksum_str[i] = toupper(checksum_str[i]); - } - - fprintf(stdout, "Tox Id: %s00000000%s\n", public_key_str, checksum_str); - - return 0; -}