summaryrefslogtreecommitdiff
path: root/other/fun/sign.c
blob: eaea9d6a6e54180e810a6ed2a47cdfaa95c811b5 (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
/* Binary signer/checker using ed25519
 *
 * Compile with:
 *  gcc -o sign sign.c -lsodium
 *
 * Generate a keypair:
 *  ./sign g
 *
 * Sign a file:
 *  ./sign s PRIVATEKEY file.bin signedfile.bin
 *
 * Check a file:
 *
 * ./sign c PUBKEY signedfile.bin
 *
 * NOTE: The signature is appended to the end of the file.
 */
#include <sodium.h>
#include <string.h>
#include "../../testing/misc_tools.c" // hex_string_to_bin

int load_file(char *filename, char **result)
{
    int size = 0;
    FILE *f = fopen(filename, "rb");

    if (f == NULL) {
        *result = NULL;
        return -1; // -1 means file opening fail
    }

    fseek(f, 0, SEEK_END);
    size = ftell(f);
    fseek(f, 0, SEEK_SET);
    *result = (char *)malloc(size + 1);

    if (size != fread(*result, sizeof(char), size, f)) {
        free(*result);
        return -2; // -2 means file reading fail
    }

    fclose(f);
    (*result)[size] = 0;
    return size;
}

int main(int argc, char *argv[])
{
    unsigned char pk[crypto_sign_ed25519_PUBLICKEYBYTES];
    unsigned char sk[crypto_sign_ed25519_SECRETKEYBYTES];

    if (argc == 2 && argv[1][0] == 'g') {
        crypto_sign_ed25519_keypair(pk, sk);
        printf("Public key:\n");
        int i;

        for (i = 0; i < crypto_sign_ed25519_PUBLICKEYBYTES; i++) {
            printf("%02hhX", pk[i]);
        }

        printf("\nSecret key:\n");

        for (i = 0; i < crypto_sign_ed25519_SECRETKEYBYTES; i++) {
            printf("%02hhX", sk[i]);
        }

        printf("\n");
    }

    if (argc == 5 && argv[1][0] == 's') {
        unsigned char *secret_key = hex_string_to_bin(argv[2]);
        char *data;
        int size = load_file(argv[3], &data);

        if (size < 0)
            goto fail;

        unsigned long long smlen;
        char *sm = malloc(size + crypto_sign_ed25519_BYTES * 2);
        crypto_sign_ed25519(sm, &smlen, data, size, secret_key);
        free(secret_key);

        if (smlen - size != crypto_sign_ed25519_BYTES)
            goto fail;

        FILE *f = fopen(argv[4], "wb");

        if (f == NULL)
            goto fail;

        memcpy(sm + smlen, sm, crypto_sign_ed25519_BYTES); // Move signature from beginning to end of file.

        if (fwrite(sm + (smlen - size), 1, smlen, f) != smlen)
            goto fail;

        fclose(f);
        printf("Signed successfully.\n");
    }

    if (argc == 4 && argv[1][0] == 'c') {
        unsigned char *public_key = hex_string_to_bin(argv[2]);
        char *data;
        int size = load_file(argv[3], &data);

        if (size < 0)
            goto fail;

        char *signe = malloc(size + crypto_sign_ed25519_BYTES);
        memcpy(signe, data + size - crypto_sign_ed25519_BYTES,
               crypto_sign_ed25519_BYTES); // Move signature from end to beginning of file.
        memcpy(signe + crypto_sign_ed25519_BYTES, data, size - crypto_sign_ed25519_BYTES);
        unsigned long long smlen;
        char *m = malloc(size);
        unsigned long long mlen;

        if (crypto_sign_ed25519_open(m, &mlen, signe, size, public_key) == -1) {
            printf("Failed checking sig.\n");
            goto fail;
        }

        printf("Checked successfully.\n");
    }

    return 0;

fail:
    printf("FAIL\n");
    return 1;
}