Консультация № 186928
13.12.2012, 14:48
90.48 руб.
0 49 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Помогите переделать функцию из алгоритма AES. На данный момент функция создает 128-битный шифр ключ из двух блоков по 64 бита. Нужно реализовать возможность вводить 128-битный ключ с клавиатуры. можно сделать так чтобы ключ состоял из двух частей по 64 бита.


Приложение:
__host__ void h_generateCipherKey128( uchar4 *result, uint64_t block1, uint64_t block2 )
{
for (int i = 0; i < 2; ++i) {
result[i + 0].x = (block1 >> (56 - 32*i)) & 0xFF;
result[i + 0].y = (block1 >> (48 - 32*i)) & 0xFF;
result[i + 0].z = (block1 >> (40 - 32*i)) & 0xFF;
result[i + 0].w = (block1 >> (32 - 32*i)) & 0xFF;

result[i + 2].x = (block2 >> (56 - 32*i)) & 0xFF;
result[i + 2].y = (block2 >> (48 - 32*i)) & 0xFF;
result[i + 2].z = (block2 >> (40 - 32*i)) & 0xFF;
result[i + 2].w = (block2 >> (32 - 32*i)) & 0xFF;
}
}

__host__ /*inline*/ uchar4 * d_generateCipherKey128( uint64_t block1, uint64_t block2 ) // в данной функции нужно сделать так чтобы ключ вводился с клавиатуры
{
uchar4 *d_cipher_key;
uchar4 *h_cipher_key = (uchar4 *) malloc(4 * sizeof(uchar4));

// Создает ключ шифрования на хосте из двух блоков uint64_t
h_generateCipherKey128(h_cipher_key, block1, block2);

// Выделяет память для ключа шифрования устройства, копирование хозяина к ней
cudaMalloc((void **) &d_cipher_key, 4 * sizeof(uchar4));
cudaMemcpy(d_cipher_key, h_cipher_key, 4 * sizeof(uchar4), cudaMemcpyHostToDevice);

// Освобождает память, используемая для временного ключа шифра принимающей
free(h_cipher_key);

return d_cipher_key;
}
__host__ void nouveau128( int argc, char *argv[] ) {
uchar4 *h_round_keys;
uchar4 *d_cipher_key, *d_round_keys;
uint8_t *d_sbox, *d_inv_sbox;
char *h_file;
char *d_file;
size_t file_size;
char fname[80],fname1[80], fname2[80];

// Создание 128-битный шифр-ключ из двух uint64_t
d_cipher_key = d_generateCipherKey128( 0x95A8EE8E89979B9E, 0xFDCBC6EB9797528D ); //ключ создается из этих констант
printf("Enter src file name: ");
gets_s(fname);

// Загружает файл с диска
file_size = loadFileIntoMemory(&h_file, fname);

// Выделяет память для различных ресурсов
h_round_keys = (uchar4 *) malloc(11 * 4 * sizeof(uchar4));
cudaMalloc((void **) &d_round_keys, 11 * 4 * sizeof(uchar4));
cudaMalloc((void **) &d_sbox, 256 * sizeof(uint8_t));
cudaMalloc((void **) &d_inv_sbox, 256 * sizeof(uint8_t));
cudaMalloc((void **) &d_file, file_size * sizeof(char));

// Копии памяти на устройстве
cudaMemcpy(d_sbox, s_box, 256 * sizeof(uint8_t), cudaMemcpyHostToDevice);
cudaMemcpy(d_inv_sbox, inv_s_box, 256 * sizeof(uint8_t), cudaMemcpyHostToDevice);
cudaMemcpy(d_file, h_file, file_size * sizeof(char), cudaMemcpyHostToDevice);


// Создает вокруг ключи, сохраняя их на глобальной памяти
d_round_keys = d_expandKey128( d_cipher_key, d_sbox );


// Шифрование файлов
h_file = encryptHostToHost128(h_file, file_size, d_sbox, d_round_keys);
printf("Enter dst file name: ");
gets_s(fname1);
//Записывает зашифрованный файл на диске
writeToFile(h_file, fname1, file_size);


// Расшифровка файлов
h_file = decryptHostToHost128(h_file, file_size, d_inv_sbox, d_round_keys);
printf("Enter res file name: ");
gets_s(fname2);
//Пишет расшифрованный файл на диск
writeToFile(h_file, fname2, file_size);


// Освобождает память, которая больше не используется
free(h_round_keys);
free(h_file);
cudaFree(d_cipher_key);
cudaFree(d_round_keys);
cudaFree(d_inv_sbox);
cudaFree(d_sbox);
cudaFree(d_file);
}

Обсуждение

давно
Посетитель
276566
297
16.12.2012, 11:06
общий
после того как в этой строчке printf ("%llx %llx, blocks[0], blocks[1]") 1 и 0 поменял местами, после ввода ключа 95A8EE8E89979B9EFDCBC6EB9797528D отображается это 95a8ee8e89979b9e fdcbc6eb9797528d и сразу после этого выдается ошибка invalid allocation size 4294967295 bytes
Неизвестный
16.12.2012, 13:03
общий
что насчет дебагера и советов из сообщений #12, #14?
давно
Посетитель
276566
297
16.12.2012, 14:04
общий
во время отладки значения красного цвета отображаются
_host__ void nouveau128( int argc, char *argv[] ) {
uchar4 *h_round_keys;
uchar4 *d_cipher_key, *d_round_keys;
uint8_t *d_sbox, *d_inv_sbox;
char *h_file;
char *d_file;
size_t file_size;
char fname[80],fname1[80], fname2[80];
/* объявляем массив из двух блоков */
uint64_t blocks[2];

/* считываем от пользователя ключи и заносим в массив */
getkeys(blocks);
printf ("%llx %llx, blocks[1], blocks[0]");
// Создание 128-битный шифр-ключ из двух uint64_t
d_cipher_key = d_generateCipherKey128( blocks[1], blocks[0]/*0x95A8EE8E89979B9E, 0xFDCBC6EB9797528D*/ ); // в этой строчке
printf("Enter src file name: ");
gets_s(fname);

// Загружает файл с диска
file_size = loadFileIntoMemory(&h_file, fname); число указанное в ошибке появляется в этой строчке // в этой строчке

// Выделяет память для различных ресурсов
h_round_keys = (uchar4 *) malloc(11 * 4 * sizeof(uchar4));
cudaMalloc((void **) &d_round_keys, 11 * 4 * sizeof(uchar4)); // в этой строчке
cudaMalloc((void **) &d_sbox, 256 * sizeof(uint8_t));
cudaMalloc((void **) &d_inv_sbox, 256 * sizeof(uint8_t));
cudaMalloc((void **) &d_file, file_size * sizeof(char));

// Копии памяти на устройстве
cudaMemcpy(d_sbox, s_box, 256 * sizeof(uint8_t), cudaMemcpyHostToDevice);
cudaMemcpy(d_inv_sbox, inv_s_box, 256 * sizeof(uint8_t), cudaMemcpyHostToDevice);
cudaMemcpy(d_file, h_file, file_size * sizeof(char), cudaMemcpyHostToDevice);


// Создает вокруг ключи, сохраняя их на глобальной памяти
d_round_keys = d_expandKey128( d_cipher_key, d_sbox ); // в этой строчке


// Шифрование файлов
h_file = encryptHostToHost128(h_file, file_size, d_sbox, d_round_keys); //ошибка выскакивает после этой строчки // в этой строчке,а затем ошибка.
printf("Enter dst file name: ");
gets_s(fname1);
//Записывает зашифрованный файл на диске
writeToFile(h_file, fname1, file_size);


// Расшифровка файлов
h_file = decryptHostToHost128(h_file, file_size, d_inv_sbox, d_round_keys);
printf("Enter res file name: ");
gets_s(fname2);
//Пишет расшифрованный файл на диск
writeToFile(h_file, fname2, file_size);


// Освобождает память, которая больше не используется
free(h_round_keys);
free(h_file);
cudaFree(d_cipher_key);
cudaFree(d_round_keys);
cudaFree(d_inv_sbox);
cudaFree(d_sbox);
cudaFree(d_file);
}
__host__ /*inline*/ uchar4 * d_generateCipherKey128( uint64_t block1, uint64_t block2 )
{

uchar4 *d_cipher_key;
uchar4 *h_cipher_key = (uchar4 *) malloc(4 * sizeof(uchar4));

// Создает ключ шифрования на хосте из двух блоков uint64_t
h_generateCipherKey128(h_cipher_key, block1, block2);

// Выделяет память для ключа шифрования устройства, копирование хозяина к ней
cudaMalloc((void **) &d_cipher_key, 4 * sizeof(uchar4));
cudaMemcpy(d_cipher_key, h_cipher_key, 4 * sizeof(uchar4), cudaMemcpyHostToDevice);

// Освобождает память, используемая для временного ключа шифра принимающей
free(h_cipher_key);

return d_cipher_key;
}

__host__ void getkeys(uint64_t *blocks)
{
int done = 0; /* флаг выхода из цикла ввода */

/* Пока пользователь не введёт правильное число */
while (!done) {
char buf[32 + 1]; /* буффер куда будет для введённой строки + конец строки '\0' */
int len; /* длина строки */

char *p; /* b указывает на текущее 32 битное число, куда будем заносить результат */
uint32_t *b; /* p указывает на начало строки в котором находится 32 битное hex число в ASCII виде */

printf ("Enter 128 bit number (16 byte, 32 hex digit): ");
fflush (stdout);
fgets(buf, sizeof(buf), stdin);
len = strlen(buf);

if (len != 32)
{
printf ("Must be from 32 hex digits\n");
continue;
}

done = 1;

b = (uint32_t *)blocks;
for (p = buf + len - 8; done && buf <= p; b++, p -= 8)
{
char *endptr;
*b = strtoul(p, &endptr, 16);

if ((errno == ERANGE && (*b == LONG_MAX || *b == LONG_MIN))
|| (errno != 0 && *b == 0)
|| (endptr == p))
{
printf ("Error (%s), wrong number\n", strerror(errno));
done = 0;
continue;
}
*p = 0; /* отрезаем от введённой пользователем строки очередное 32 битное hex число*/
}
}
}
Неизвестный
16.12.2012, 15:05
общий
16.12.2012, 15:10
Понятно. 4294967295 это int32_t число == -1
Это обозначает что эта функция заканчивается ошибкой.
Скорей всего вы указываете имя файла которого нет в активной директории, в которой запускается программа.
Вы или указывайте полный путь "c:\полный\путь\к\файлу.txt" или в настройках проекта укажите директорию запуска где лежит ваш файл.

И не плохо бы было бы вообще обрабатывать ошибку открытия файла:
1. вместо
Код:

size_t file_size;

сделайте
Код:

ssize_t file_size;

тогда у вас file_size будет знаковый.
2. после этого делайте проверку
Код:

for (;;) // бесконечный цикл, пока не введу правильное имя файла
{
file_size = loadFileIntoMemory(&h_file, fname);
if (file_size != -1)
break;
printf ("Fail open file "%s"\n", fname);
}

К сожалению я не нашел откуда эта фунция loadFileIntoMemory(), поэтому не знаю как вывести более расширеное описание ошибки.
давно
Посетитель
276566
297
16.12.2012, 15:44
общий
обычно когда прога выполняется работа с файла так устроена
введите имя исходного файла: d:\a.txt
введите имя зашифр. файла: d:\a1.txt
введите имя расшифр. файла: d:\a2.txt
т.к. теперь ключ вводится с клавы нужно ли под него выделять память если да то можете реализовать функцию для выделения памяти.
Неизвестный
16.12.2012, 15:55
общий
мм.. странно
память уже выделена. и под два блока для ключа (это массив из двух переменных), и под строку. попробуйте больше памяти может дать под нее, может какие особенности в windows:
вместо
Код:

char buf[32 + 1];

сделать
Код:

char buf[80];


или вместо fgets в моей фунции используйте gets_s как у вас в остальном коде (у меня этой функции небыло)
давно
Посетитель
276566
297
16.12.2012, 16:42
общий
при попытке сделать так ssize_t file_size; была выдана ошибка что идентификатор не определен, возможно из-за того что в файле sourceannotations.h прописано так typedef _W64 unsigned int size_t;
если в данной строчке "fgets(buf, sizeof(buf), stdin);" сделать gets_s вместо fgets, то выдаст что слишком много аргументов , но если сделать так gets_s(buf,/*sizeof(buf),stdin*/);
так прога работать будет но при выполнении
enter src file name:d:\a.txt // ввели исходный файл после чего он шифруется
enter dst file name:d:\a1.txt // ввели имя зашифрованного файла и сохранили в нем зашифрованную информацию
enter res file name:d:\a2.txt // ввели имя расшифрованного файла, но при этом здесь сохраняется инфа не в расшифрованном виде, а наоборот еще раз шифрует инфу из файла a1.txt и затем сохраняет ее в файле a2.txt
Неизвестный
16.12.2012, 17:47
общий
ну это уже больше похоже на логическую ошибку в коде. надо смотреть дебагером что где
давно
Посетитель
276566
297
16.12.2012, 19:54
общий
https://rfpro.ru/upload/8944- файл с кодом проги
https://rfpro.ru/upload/8945 - файл с показаниями отладки
Неизвестный
17.12.2012, 09:25
общий
файл по прежднему не считывается.
Почему не оставили gets_s вместо fgets?

Попробуйте заменить
Код:

fgets(buf, sizeof(buf), stdin);

на
Код:

gets_s(buf);


и надо поправить так что бы имя файла спрашивалось в бесконечном цикле.
Код:

for (;;) // бесконечный цикл, пока не введу правильное имя файла
{
printf("Enter src file name: ");
gets_s(fname);
file_size = loadFileIntoMemory(&h_file, fname);
if (file_size != -1)
break;
printf ("Fail open file "%s"\n", fname);
}
давно
Посетитель
276566
297
17.12.2012, 11:04
общий
если использовать gets_s(buf), то появляется возможность вводить имя файла, но при этом программа выполняет только шифрование данных,
введите имя исходного файла: d:\a.txt // сначала загружается этот файл, а потом он шифруется
введите имя зашифр. файла: d:\a1.txt // сюда записывается зашифрованная информация
введите имя расшифр. файла: d:\a2.txt // сюда записывается зашифрованная информация из файла a1.txt, которая перед этим еще раз шифруется. хотя в файл a2.txt должна записываться расшифрованная информация.
во время компеляции отображаются следующие warning-и:
>D:/cuda_dip/a2/a2/kernel.cu(748): warning : integer conversion resulted in a change of sign
1>
1>D:/cuda_dip/a2/a2/kernel.cu(1019): warning : integer conversion resulted in a change of sign
1>
1> tmpxft_00000a54_00000000-0_kernel.cudafe1.gpu
1> tmpxft_00000a54_00000000-5_kernel.cudafe2.gpu
1> kernel.cu
1>D:/cuda_dip/a2/a2/kernel.cu(748): warning : integer conversion resulted in a change of sign
1>
1>D:/cuda_dip/a2/a2/kernel.cu(1019): warning : integer conversion resulted in a change of sign
давно
Посетитель
276566
297
18.12.2012, 08:51
общий
скажите как устранить проблему из-за которой прога дважды выполняет шифрование вместо того чтобы, сначала шифровать информацию, а затем дешифровать.
Неизвестный
18.12.2012, 09:18
общий
18.12.2012, 09:18
как я уже говорил это надо смотреть дебагером. та отладка что вы показывали показывала проблемы другого характера. варнинги не показывают ничего интересного
давно
Посетитель
276566
297
19.12.2012, 22:28
общий
20.12.2012, 09:00
помогите устранить проблему. В данной функции есть два буфера: bufin и bufout. в буфер bufin считывается информация из файла размером 3 мегабайта, затем данная информация разбивается на блоки размером 160000, после этого каждый шифруется и записывается в буфер bufout, но поскольку размер последнего блока меньше 160000 то из-за этого во время выполнения программы выскакивает ошибка. как добить последний блок нулями, чтобы его размер был равен 160000.
#include "stdafx.h"
#include <stdio.h>
#include "rijndael.h"
#include <iostream>
#include <time.h>
using namespace std;
#define KEYBITS 256
#define bufsize 160000

unsigned char bufin[bufsize],bufout[bufsize];

int main(int argc, char ** argv)
{
unsigned long rk[RKLENGTH(KEYBITS)];
unsigned char key[KEYLENGTH(KEYBITS)];
int i;
int nrounds,realreads;
char password[80], sfname[80],dfname[80];
FILE *input,*output;

unsigned char plaintext[16];
unsigned char ciphertext[16];
clock_t t1,t2;
float tm;

/*
if (argc < 3)
{
fputs("Missing argument\n", stderr);
return 1;
}*/

printf("Enter key: ");
gets(password);
printf("Enter source file name: ");
gets(sfname);
printf("Enter destination file name: ");
gets(dfname);
t1=clock();
for (i = 0; i < sizeof(key); i++)
key[i] = *password != 0 ? (*password)++ : 0;

input=fopen(sfname,"rb");
output = fopen(dfname, "wb");
if (output == NULL)
{
fputs("File write error", stderr);
return 1;
}

nrounds = rijndaelSetupEncrypt(rk, key, 256);
//do
{
realreads=fread(bufin,1,bufsize,input);
int j=0;
while(j<=realreads){
for (int i = 0; i < 16; i++)
{
plaintext[i] = bufin[i+j];
}
rijndaelEncrypt(rk, nrounds, plaintext, ciphertext);
for (int i = 0; i < 16; i++)
{
bufout[i+j]=ciphertext[i];
}
j+=16;
}
fwrite(bufout,1,realreads,output);
}//while(realreads==bufsize);
t2=clock();
tm=(float)(t2-t1)/CLOCKS_PER_SEC;
printf("t=%f\n",tm);
fclose(output);
}
Неизвестный
20.12.2012, 12:26
общий
Адресаты:
Вставить перед fread() обнуление bufout
Код:

....
{
memset(bufout, 0, bufsize);
realreads=fread(bufin,1,bufsize,input);
....
давно
Посетитель
276566
297
20.12.2012, 16:09
общий
при попытке расшифровать файл данной функцией выскакивает ошибка "expression(stream!=null)". в чем причина и как устранить.
функция для расшифрования:
#include "stdafx.h"
#include <stdio.h>
#include "rijndael.h"
#include <string.h>
#include <time.h>
#define bufsize 160000
#define KEYBITS 256
unsigned char bufin[bufsize], bufout[bufsize];

int main(int argc, char * fname)
{
unsigned long rk[RKLENGTH(KEYBITS)];
unsigned char key[KEYLENGTH(KEYBITS)];
int i;
int nrounds, realreads;
char password[80], sfname[80], dfname[80];
FILE *input, *output;
unsigned char plaintext[16];
unsigned char ciphertext[16];
clock_t t1,t2;
float tm;
/* if (argc < 3)
{
fputs("Missing argument", stderr);
return 1;
}*/
printf("enter key: ");
gets_s(password);
printf("enter src file name: ");
gets_s(sfname);
printf("enter dst file name: ");
gets_s(sfname);
t1=clock();
for (i = 0; i < sizeof(key); i++)
key[i] = *password != 0 ? (*password)++ : 0;
input = fopen(sfname, "rb");
output=fopen(dfname, "wb");
/*if (input == NULL)
{
fputs("File read error", stderr);
return 1;
}*/
nrounds = rijndaelSetupDecrypt(rk, key, 256);
// do
{
realreads=fread(bufin,1,bufsize,input);
if(realreads<bufsize)
memset(&bufin[realreads],0,bufsize-realreads);
int j=0;
while(j<=realreads){
for(int i=0; i<16; i++)
{
ciphertext[i]=bufin[i+j];
}
rijndaelDecrypt(rk, nrounds, ciphertext, plaintext);
for(int i=0; i<16; i++)
{
bufout[i+j]=plaintext[i];
}
j+=16;
}
int towrite=realreads;
if((realreads%16)!=0)
{
towrite/=16;
towrite+=1;
towrite*=16;
}
fwrite(bufout,1,towrite,output);
}
//while(realreads==bufsize);
t2=clock();
tm=(float)(t2-t1)/CLOCKS_PER_SEC;
printf("t=%f\n",tm);
fclose(output);
}
Неизвестный
20.12.2012, 16:45
общий
Адресаты:
У вас не обрабатываются ошибки открытия, записи и чтения файлов.
Например при ошибке отктырия файла fopen возвращает NULL, а в глобальной переменной errno находится код ошибки. По этому коду ошибки можно вывести текстовое собщение связаное с этим кодом с помощью strerror(). В примерах выше я показывал его использование.

Тоже самое относится к fread и fwrite. Нужно внимательно прочитать документацию к ним, и сделать обработку ошибок.

После чего у вас будет описание что конкретно происходит, а не невразумительное сообщение в assert. Хотя и по нему можно судить что у вас файл не открывается.
давно
Посетитель
276566
297
20.12.2012, 17:58
общий
во время отладки ошибка выскакивает на этой строчке "realreads=fread(bufin,1,bufsize,input);"
Неизвестный
20.12.2012, 18:16
общий
ну всё правильно. fopen вернуло NULL (ошибка), а в fread стоит assert проверяющий что ему в качестве указателя на структуру файла не передали NULL. вот и результата. все советы из поста #35 остались в силе
давно
Посетитель
276566
297
20.12.2012, 18:28
общий
что сделать чтобы ошибка исчезла
давно
Посетитель
276566
297
20.12.2012, 19:13
общий
можете написать решение этой проблемы
Неизвестный
20.12.2012, 19:16
общий
20.12.2012, 19:17
Сначала сделать обработку ошибок, потом по сообщению об ошибке понять почему не открывается файл, а потом уже решать проблему. Все что видно сейчас, это то что файл не открывается.
давно
Посетитель
276566
297
20.12.2012, 19:28
общий
можете написать обработку ошибок, просто не знаю как правильно реализовать функцию для обработки ошибок
давно
Посетитель
276566
297
20.12.2012, 21:17
общий
как в таком обработчике вывести код ошибки
if (input == NULL)
{
fputs("File read error", stderr);
return 1;
}
Неизвестный
20.12.2012, 21:33
общий
В сообщении 4 есть мой код, строчка 36. Я ранее упоминал функцию strerror() и что я ее использовал.

Код:

printf ("Error open file (%s): %s\n", sfname, strerror(errno));
давно
Посетитель
276566
297
20.12.2012, 21:55
общий
вставил эту строчку в результате выдается этажа ошибка
https://rfpro.ru/upload/8987-скрин ошибки
realreads=fread(bufin,1,bufsize,input);
printf ("Error open file (%s): %s\n", sfname, strerror(errno));
давно
Посетитель
276566
297
21.12.2012, 13:28
общий
https://rfpro.ru/upload/8996- в данном файле лежит два проекта: один проект зашифровывает информацию, а другой расшифровывает. например файл размер в 30 мегабайт обрабатывается за 0.497000. размер расшифрованного файла совпадает с размером зашифрованного.
по идее на CPU aes не может обработать файл в 30 мегабайт за такое маленькое время. можете посмотреть данные проги и найти причину того почему размер расшифрованного файла равен размеру зашифрованного, и почему выдается такое маленькое время.
давно
Посетитель
276566
297
21.12.2012, 14:06
общий
скажите если после выполнения программы отображается время 0.566000 с использованием CLOCKS_PER_SEC, это значит что программа выполнилась за 566 миллисекунд
давно
Посетитель
276566
297
21.12.2012, 20:06
общий
скажите вы можете запустить на своем компе программы находящиеся в данном файле и записать время за которое они зашифруют и расшифруют файл, также вложил в папку несколько текстовых файлов разного размера чтобы знать сколько времени потребуется на каждый из них. можете также написать модель своего процессора, частоту, кол-во оперативной памяти.
https://rfpro.ru/upload/8997
Неизвестный
21.12.2012, 20:19
общий
Адресаты:
К сожалению помочь не могу, так как у меня нет windows. А портирование под linux вашей програмы заберёт неадекватно много времени что бы ответить на эту просьбу.
Форма ответа