summaryrefslogtreecommitdiff
path: root/other/fun/strkey.c
blob: d769318a1eed59d587f341d194b485691388cb03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* strkey -- String in Public Key
 *
 * Generates Tox's key pairs, checking if a certain string is in the public key.
 *
 * Requires sodium or nacl library.
 *
 * There seem to be some problems with the code working on Windows -- it works
 * when built in debug mode with MinGW 4.8, but it doesn't work correctly when
 * built in release.
 *
 * Usage: strkey <offset> <string>
 *
 * Offset - an integer specifying exact byte offset position of the string you
 * are looking for within a public key. When offset is negative, the program
 * just looks for the desired string being somewhere, doesn't matter where, in
 * the public key.
 *
 * String - a hex string that you want to have in your public key. It must have
 * an even number of letters, since every two hexes map to a single byte of
 * the public key.
 *
 * Examples:
 *   strkey 0 0123
 *   Looks for a public key that begins with "0123".
 *
 *   strkey 1 0123
 *   Looks for a public key that has "0123" starting at its second byte, i.e. "XX0123...".
 *
 *   strkey 2 0123
 *   Looks for a public key that has "0123" starting at its third byte, i.e. "XXXX0123...".
 *   (each two hexes represent a single byte of a public key)
 *
 *   strkey -1 AF57CC
 *   Looks for a public key that contains "AF57CC", regardless of its position.
 *
 * To compile with gcc and sodium: gcc strkey.c -o strkey -lsodium
*/

#include <stdio.h>
#include <string.h>

#include <sodium.h>

#define PRINT_TRIES_COUNT

static void print_key(unsigned char *key)
{
    size_t i;

    for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) {
        if (key[i] < 16) {
            fprintf(stdout, "0");
        }

        fprintf(stdout, "%hhX", key[i]);
    }
}

int main(int argc, char *argv[])
{
    unsigned char public_key[crypto_box_PUBLICKEYBYTES]; // null terminator
    unsigned char secret_key[crypto_box_SECRETKEYBYTES];
    int offset = 0;
    size_t len;
    unsigned char desired_bin[crypto_box_PUBLICKEYBYTES]; // null terminator

    if (argc == 3) {
        offset = atoi(argv[1]);
        char *desired_hex = argv[2];
        len = strlen(desired_hex);

        if (len % 2 != 0) {
            fprintf(stderr, "Desired key should have an even number of letters\n");
            exit(1);
        }

        size_t block_length = (offset < 0 ? 0 : offset) + len / 2;

        if (block_length > crypto_box_PUBLICKEYBYTES) {
            fprintf(stderr, "The given key with the given offset exceed public key's length\n");
            exit(1);
        }

        // convert hex to bin
        char *pos = desired_hex;
        size_t i;

        for (i = 0; i < len; pos += 2) {
            unsigned int value;
            sscanf(pos, "%02x", &value);
            desired_bin[i] = value;
            ++i;
        }
    } else {
        fprintf(stdout, "Usage: executable <byte offset> <desired hex string with even number of letters>\n");
        exit(1);
    }

    len /= 2;

#ifdef PRINT_TRIES_COUNT
    long long unsigned int tries = 0;
#endif

    if (offset < 0) {
        int found = 0;

        do {
#ifdef PRINT_TRIES_COUNT
            tries ++;
#endif
            crypto_box_keypair(public_key, secret_key);
            int i;

            for (i = 0; i <= crypto_box_PUBLICKEYBYTES - len; i ++) {
                if (memcmp(public_key + i, desired_bin, len) == 0) {
                    found = 1;
                    break;
                }
            }
        } while (!found);
    } else {
        unsigned char *p = public_key + offset;

        do {
#ifdef PRINT_TRIES_COUNT
            tries ++;
#endif
            crypto_box_keypair(public_key, secret_key);
        } while (memcmp(p, desired_bin, len) != 0);
    }

    fprintf(stdout, "Public key:  ");
    print_key(public_key);
    fprintf(stdout, "\n");

    fprintf(stdout, "Private key: ");
    print_key(secret_key);
    fprintf(stdout, "\n");

#ifdef PRINT_TRIES_COUNT
    fprintf(stdout, "Found the key pair on %llu try.\n", tries);
#endif

    return 0;
}