Является ли libmcrypt ненадежным?

Несколько дней назад я задал вопрос на SO без какого-либо значимого ответа. Ниже это вкратце:

У меня есть клиент-серверная программа на C, которая шифрует/дешифрует данные с помощью библиотеки mcrypt C. Клиент шифрует строку, которую хочет отправить на сервер, отправляет ее и после прочтения сервером расшифровывает. Ниже приведены мои функции шифрования и дешифрования:

функция шифрования:

void encrypt(char *es, char *key, char *civ, size_t  length) {

    MCRYPT td;
    int n;

    td = mcrypt_module_open(MCRYPT_TWOFISH, NULL, MCRYPT_CFB, NULL );
    if (td == MCRYPT_FAILED) {
        log_err(log_opts, strerror(errno));
        exit(1);
    }
    n = mcrypt_enc_get_iv_size(td);

    char iv[n + 1];
    strncpy(iv, civ, n);
    iv[n] = '\0';

    if ((mcrypt_generic_init(td, key, KEY_SIZE, iv)) < 0) {
        log_err(log_opts, "while trying to do mcrypt_generic_init.");
        exit(1);
    }
    mcrypt_generic(td, es, length);

    if (mcrypt_module_close(td) < 0) {
        log_err(log_opts, "while trying to close module.");
        exit(1);
    }

}

функция расшифровки

void decrypt(char *ds, char *key, char *civ, size_t length) {
    MCRYPT td;
    int n;

    td = mcrypt_module_open(MCRYPT_TWOFISH, NULL, MCRYPT_CFB, NULL );
    n = mcrypt_enc_get_iv_size(td);

    char iv[n + 1];
    strncpy(iv, civ, n);
    iv[n] = '\0';

    if ((mcrypt_generic_init(td, key, KEY_SIZE, iv)) < 0) {
        log_err(log_opts, "trying to do mcrypt_generic_init.");
        exit(1);
    }

    mdecrypt_generic(td, ds, length);
    if (mcrypt_module_close(td) < 0) {
        log_err(log_opts, "while trying to close module.");
        exit(1);
    }

}

Моя проблема:

Бывают случаи (от 1 до 10), когда строка, расшифрованная на стороне сервера, но зашифрованная на стороне клиента, не совпадает с исходной. Может ли кто-нибудь предложить мне, откуда может возникнуть проблема?

Теперь мне удалось поймать сценарий, когда я получаю вышеупомянутое плохое поведение, которое я уже описал. Ниже приведена моя функция main:

int main(void) {

    char *newKey = "P1adEfRuPX0AP2UDmSWHhgS6DaIrE4eb5EEJudC";
    char *iv = "asdfkSSDFAEGasld3G9dkDF0";
    char *s1 = "XZH9ZYKQC9*NYSR6UDUII";
    char *s2 = malloc(STRING_SIZE * sizeof(char));

    strcpy(s2, s1);
    printf("%s - %s\n", s1, s2);

    encrypt(s2, newKey, iv, strlen(s2));
    decrypt(s2, newKey, iv, strlen(s2));

    if (strncmp(s1, s2, STRING_SIZE) != 0)
        printf("wrong encrypt-decrypt: %s %s\n", s1, s2);

    exit(0);

}

Ниже приведен вывод этой функции main:

XZH9ZYKQC9*NYSR6UDUII - XZH9ZYKQC9*NYSR6UDUII
wrong encrypt-decrypt: XZH9ZYKQC9*NYSR6UDUII XZH9ZYKQC

Вопрос. Я делаю что-то не так или проблема в этой библиотеке?


person artaxerxe    schedule 12.08.2013    source источник
comment
Что такое STRING_SIZE?   -  person ouah    schedule 12.08.2013
comment
@ouah размер STRING_SIZE – 40.   -  person artaxerxe    schedule 12.08.2013
comment
И KEY_SIZE? Ваша программа неполная, предоставьте всю недостающую информацию.   -  person ouah    schedule 12.08.2013
comment
@ouah KEY_SIZE 16.   -  person artaxerxe    schedule 12.08.2013
comment
Является ли civ вашим вектором инициализации?   -  person chrylis -cautiouslyoptimistic-    schedule 12.08.2013
comment
Я отмечу, что использование strncpy для необработанных двоичных данных, таких как ключи шифрования, IV и зашифрованные тексты, является ошибкой; они могут совершенно законно содержать '\0'. Вместо этого используйте memcpy. Однако я не думаю, что это вызывает проблему здесь.   -  person chrylis -cautiouslyoptimistic-    schedule 12.08.2013


Ответы (1)


Наконец-то я понял, откуда берется проблема. В функции main у меня есть две строки:

encrypt(s2, newKey, iv, strlen(s2));
decrypt(s2, newKey, iv, strlen(s2));

Первая строка в порядке, пока s2 является четко определенной строкой char. Но во второй строке strlen(s2) может вернуть ошибочный результат, если полученный зашифрованный текст содержит '\0'.

Я просто хочу сказать, что комментарий @chrylis дал мне подсказку, где искать проблему.

В заключение, исходя из эмпирического правила, я бы сказал: В C ВЫ НЕ ДОЛЖНЫ ИСПОЛЬЗОВАТЬ ФУНКЦИИ STRING НА ЗАШИФРОВАННОМ ТЕКСЕ.

Спасибо всем за помощь!

person artaxerxe    schedule 13.08.2013
comment
Точнее, вы не должны использовать строковые функции для вещей, которые не соответствуют определению строки в C. (Например, да, произвольный вывод процесса шифрования.) - person This isn't my real name; 15.08.2013