Add programs for creating savedata & bootstrap keys

This commit is contained in:
Maxim Biro 2021-12-28 12:55:51 -05:00
parent d2f98b83c2
commit b2ea0e5c76
No known key found for this signature in database
GPG Key ID: AB3AD9896472BFA4
8 changed files with 342 additions and 73 deletions

View File

@ -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.
##### Vanity key generators
Can be used to generate vanity Tox Ids or DHT bootstrap node public keys.
| 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. |
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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. |
| `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. |
## Building

View File

@ -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

View File

@ -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",

View File

@ -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
other/fun/create_common.h Normal file
View File

@ -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);
}

View File

@ -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
other/fun/create_savedata.c Normal file
View File

@ -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;
}
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;
}

View File

@ -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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sodium.h>
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;
}