diff --git a/INSTALL.md b/INSTALL.md index bce7d679..75c350e1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -44,15 +44,34 @@ This repository, although called `toxcore`, in fact contains several libraries b There are some programs that are not plugged into the CMake build system which you might find interesting. You would need to build those programs yourself. These programs reside in [`other/fun`](other/fun) directory. -| Name | Type | Dependencies | Platform | Description | -|--------------------------|------------|----------------------|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of a specified DHT bootstrap node. | -| `cracker` | Executable | libnacl or libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. | -| `make-funny-savefile` | Script | python | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair. Useful for generating Tox profiles from the output of cracker or strkey programs. | -| `minimal-save-generator` | Executable | libsodium | Cross-platform | Generates a minimal Tox profile file (savedata file) with a random key pair. | -| `save-generator` | Executable | libtoxcore | Cross-platform | Generates a Tox profile file (savedata file) with a random key pair using libtoxcore. Allows setting a name and adding friends. | -| `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. | -| `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte pattern at a specified position or at any position. | +##### Vanity key generators + +Can be used to generate vanity Tox Ids or DHT bootstrap node public keys. + +| Name | Type | Dependencies | Platform | Description | +|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `cracker` | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded. | +| `cracker_simple` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded. | +| `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. | + +##### Key file generators + +Useful for generating Tox profiles from the output of the vanity key generators, as well as generating random Tox profiles. + +| Name | Type | Dependencies | Platform | Description | +|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `make-funny-savefile` | Script | python | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair. | +| `create_bootstrap_keys` | Executable | libsodium | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair. | +| `create_minimal_savedata` | Executable | libsodium | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information. | +| `create_savedata` | Executable | libsodium, libtoxcore | Cross-platform | Generates a Tox profile file (savedata file) with either the provided or a random key pair using libtoxcore, printing the generated Tox Id and secret & public key information. | +| `save-generator` | Executable | libtoxcore | Cross-platform | Generates a Tox profile file (savedata file) with a random key pair using libtoxcore, setting the specified user name, going online and adding specified Tox Ids as friends. | + +##### Other + +| Name | Type | Dependencies | Platform | Description | +|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. | +| `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. | ## Building diff --git a/other/analysis/gen-file.sh b/other/analysis/gen-file.sh index 17ff8b95..bbbd27da 100644 --- a/other/analysis/gen-file.sh +++ b/other/analysis/gen-file.sh @@ -86,6 +86,7 @@ done echo "static void call(int m(), int argc, char **argv) { m(); }" >>amalgamation.cc echo "static void call(int m(int, char **), int argc, char **argv) { m(argc, argv); }" >>amalgamation.cc +echo "static void call(int m(int, const char *const *), int argc, char **argv) { m(argc, argv); }" >>amalgamation.cc echo '} // namespace' >>amalgamation.cc echo "int main(int argc, char **argv) {" >>amalgamation.cc diff --git a/other/fun/BUILD.bazel b/other/fun/BUILD.bazel index 604dce3d..99ee50f7 100644 --- a/other/fun/BUILD.bazel +++ b/other/fun/BUILD.bazel @@ -26,9 +26,30 @@ cc_binary( ) cc_binary( - name = "minimal-save-generator", + name = "create_minimal_savedata", testonly = 1, - srcs = ["minimal-save-generator.c"], + srcs = ["create_minimal_savedata.c", "create_common.h"], + deps = [ + "//c-toxcore/toxcore:ccompat", + "@libsodium", + ], +) + +cc_binary( + name = "create_savedata", + testonly = 1, + srcs = ["create_savedata.c", "create_common.h"], + deps = [ + "//c-toxcore/toxcore", + "//c-toxcore/toxcore:ccompat", + "@libsodium", + ], +) + +cc_binary( + name = "create_bootstrap_keys", + testonly = 1, + srcs = ["create_bootstrap_keys.c", "create_common.h"], deps = [ "//c-toxcore/toxcore:ccompat", "@libsodium", diff --git a/other/fun/create_bootstrap_keys.c b/other/fun/create_bootstrap_keys.c new file mode 100644 index 00000000..8419c110 --- /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 00000000..89ddaac9 --- /dev/null +++ b/other/fun/create_common.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * + * Shared functions of create_*.c programs. + */ +#include +#include +#include +#include +#include + +#include + +#include "../../toxcore/ccompat.h" + +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 00000000..40031999 --- /dev/null +++ b/other/fun/create_minimal_savedata.c @@ -0,0 +1,58 @@ +/* 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); + + // toxcore stores integers in savedata explicitly in little-endian, so this is indeed portable across architectures + // 0x00000000 = (uint32_t) 0 + // 0x15ed1b1f = (uint32_t) STATE_COOKIE_GLOBAL + // 0x00000044 = (uint32_t) (crypto_box_PUBLICKEYBYTES+crypto_box_SECRETKEYBYTES+sizeof(uint32_t)) + // 0x0001 = (uint16_t) STATE_TYPE_NOSPAMKEYS + // 0x01ce = (uint16_t) STATE_COOKIE_TYPE + // 0x00000000 = (uint32_t) nospam + // _ = uint8_t[crypto_box_PUBLICKEYBYTES] public key + // _ = uint8_t[crypto_box_SECRETKEYBYTES] secret key + 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 % sizeof(checksum)] ^= 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 00000000..8a30525c --- /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/ccompat.h" +#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 *)malloc(savedata_size); + + if (savedata == nullptr) { + 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 *)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 *)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 393bb7aa..00000000 --- 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; -}