Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add programs for creating savedata & bootstrap keys #1818

Merged
merged 1 commit into from
Jan 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 28 additions & 9 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions other/analysis/gen-file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 23 additions & 2 deletions other/fun/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 28 additions & 0 deletions other/fun/create_bootstrap_keys.c
Original file line number Diff line number Diff line change
@@ -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 <stdio.h>

#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;
}
89 changes: 89 additions & 0 deletions other/fun/create_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
*
* Shared functions of create_*.c programs.
*/
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sodium.h>

#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);
}
58 changes: 58 additions & 0 deletions other/fun/create_minimal_savedata.c
Original file line number Diff line number Diff line change
@@ -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 <stdio.h>

#include <sodium.h>

#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;
}
115 changes: 115 additions & 0 deletions other/fun/create_savedata.c
Original file line number Diff line number Diff line change
@@ -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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include <sodium.h>

#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;
nurupo marked this conversation as resolved.
Show resolved Hide resolved
}

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[])
nurupo marked this conversation as resolved.
Show resolved Hide resolved
{
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;
}