Непонятный дефект указателя в программе

Я пытаюсь построить модифицированный пример использования DES CBC EDE на openssl. Я использую gcc версии 4.4.6 (Buildroot 2012.02) для компиляции arm (не мой выбор компилятора) в ubuntu 10.04. Вот проблема: когда объявление указателя не закомментировано — все нормально. Тестовое сообщение расшифровывается. Но когда объявление указателя комментируется — тестовое сообщение показывает только 2 первые буквы после расшифровки. Я просто не могу понять, что может сделать объявление о неиспользованном указателе. Вот код:

#include <openssl/des.h>
#include <cstring>

#define BUFSIZE 512

using namespace std;

int main(int argc, char *argv[]) {unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
unsigned char *strangePointer = &out[0];  // what is wrong with it?
int len;

DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;

const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";

memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8);

DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);

DES_set_key((C_Block *)key1, &ks1);
DES_set_key((C_Block *)key2, &ks2);
DES_set_key((C_Block *)key3, &ks3);

const char* message = "Now is the time for all men to stand up and be counted";
/* 64 bytes of plaintext */
len = strlen(message);
memcpy(in,message,len);

printf("Plaintext: [%s]\n", in);

memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);

int lenout = 0;
while(out[lenout] != '\0') ++lenout;

memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);

printf("Decrypted Text: [%s]\n", back);

return 0;
}

1

Решение

В вашем коде есть несколько неверных вещей. Сначала я начну с простого ответа:

Ваш третий ключ даже не заполнен ключевыми данными. Это случайные данные в локальном стеке активации.

memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8); // <<=== NOTE still key2

Ох, копипаст, вы жестокая и бессердечная девка. Во всяком случае, по удаление переменная, которую вы комментируете, этот ключ перемещается дальше (или вниз, в зависимости от вашей реализации) в стек, и в результате получается другое значение. Но суть в том, что вы используете неопределенные данные для своего третьего ключа.

Но это не вся проблема. Это изменение в ключе разоблачает другой вопрос, вы рассчитываете длину вывода, что также неверно. Это:

int lenout = 0;
while(out[lenout] != '\0') ++lenout;

Предполагается, что длина выходного шифра может быть найдена путем поиска 0-байт. Алгоритм DES может легко испустить такой байт в любом месте в блоке шифрования. Это совершенно неправильно. Размер выходного DES_ede3_cbc_encrypt операция шифрования всегда кратна размеру блока, который для DES равен 8 байтам (не случайно размер DES_cblock), Правильный расчет размера выходного буфера:

int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);

что может показаться чертовски большим, но в итоге все это округляется до ближайшего кратного длины блока. Кроме того, вы даже не необходимость input буфер. API выполнит вычисления за вас, если вы просто передадите свое сообщение с входными данными и его истинную длину. Но я оставляю это для вас, чтобы закончить (подсказка: просто удалите input и передать message).

результат:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>

#define BUFSIZE 512

int main(int argc, char *argv[])
{
unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
int len;

DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;

const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";

memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key3,key + 16,8);

DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);

DES_set_key(&key1, &ks1);
DES_set_key(&key2, &ks2);
DES_set_key(&key3, &ks3);

const char* message = "Now is the time for all men to stand up and be counted";
len = strlen(message);
memcpy(in,message,len);

printf("Plaintext: [%s]\n", in);

memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);

int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);

memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);

printf("Decrypted Text: [%s]\n", back);

return 0;
}

Выход

Plaintext: [Now is the time for all men to stand up and be counted]
Decrypted Text: [Now is the time for all men to stand up and be counted]
3

Другие решения

Вы, скорее всего, испытываете переполнение буфера. Декларация len идет после back в стеке. Если back переполняет, затем len будет перезаписано Добавление другой переменной (strangePointer) между ними добавляет пробел в стеке, который останавливает перезапись len.

Вероятно, увеличивается BUFSIZE должен решить вашу проблему.

0

По вопросам рекламы [email protected]