Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Шифрование файла (file encryption/encoding)


Автор: Yogurt 22.10.2010, 11:56
Есть файл txt, в котором лежит полезная информация для обработки данных с помощью написанной программы.
Как закодировать или зашифровать файл, чтобы пользователь не мог его посмотреть, а если и смог бы, то ничего бы в нём не понял.
Файл объёмом 150 КБ, у файла есть повторяющаяся каждую строчку структура (короче там лежит много параметров с множеством настроек для каждого: 1 строка - 1 параметр)
Поставил настройку SetFileAttributes(FileName, FILE_ATTRIBUTE_HIDDEN); но это мало помогает
Что ещё можно сделать и есть ли функция установки пароля на файл

P.S. В основном прогаю в MFC, но в данном случае на код это оказывает посредственное влияние

Автор: EvilsInterrupt 22.10.2010, 12:10
Yogurt, задачи :
1) определить от кого скрываемся
2) определить как шустро должны выполняться шифрование\расшифровка
3) определить как раскрывать информацию при работе? Частями или можно целиком?

Автор: Yogurt 25.10.2010, 10:10
1) Скрываем информацию от пользователей
2) Должно открываться шустро. Размер файла будет максимум около 200 Кб, поэтому обычно помещается в оперативную память. Думаю, небольшие преобразования перед этим не повлияют на скорость работы машины
3) Раскрывать целиком

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

Наверное, многие уже сталкивались с этим. Как решили задачу? С какими проблемы обнаружились?

Автор: baldina 25.10.2010, 10:41
Цитата

В основном прогаю в MFC, но в данном случае на код это оказывает посредственное влияние 

поэт...  smile 

Цитата

можно не сам файл шифровать, а его содержимое

э-э... дайте определение, что есть 'сам файл', а что - 'его содержимое'

Цитата

Наверное, многие уже сталкивались с этим. Как решили задачу?

Для начала нужно определить требуемую криптостойкость. Если от пионэров закрываться, можно начать с простейшей подстановки в стиле пляшущих человечков. типа A->B, B->C и т.д.
http://protect.htmlweb.ru/p11.htm

Автор: Yogurt 1.11.2010, 14:04
По-поводу "сам файл, или его содержимое" - файл можно открыть стандартными средствами Винды. Мне интересно, можно ли программно заблокировать файл от Ворда, Экселя и, если получится, блокнота?

По-поводу пляшущих человечков - надеялся, что кто-то уже с этим сталкивался, и расскажет, какие шишки набил. В основном интересует скорость работы с файлом, так как в программе предусмотрено его редактирование.

На счёт содержимого - на файл можно смотреть, как на набор байт, а можно - как на набор символов. Как лучше для кодирования данных?

Автор: baldina 1.11.2010, 15:17
Цитата

 на файл можно смотреть, как на набор байт, а можно - как на набор символов

А что такое байт? А это - символ из алфавита (0..255). Так что для кодирования без разницы...

Цитата

кто-то уже с этим сталкивался

конечно. Вам ссылку дали, оттуда ноги растут на другие ссылки... С этим сталкивались столько, что написаны горы литературы.
А что касается простейшей реализации пляшущих человечков - это на 10 мин работы. Для начинающих - час.

Цитата

программно заблокировать файл от Ворда, Экселя и, если получится, блокнота

можно. хотя сложно и ненадежно (на всякий винт с резьбой найдется...)
шифруйте, и будет вам счастье.
простейший способ - сделайте в цикле для каждого символа/байта файла операцию кодирования:

Код

unsigned char key = 0xED; // замените по вкусу

for (all bytes in file as B)
  B ^= key;


раскодирование - той же самой операцией.
а пока юзеры будут ломать эту "защиту" изучайте литературу

Автор: xvr 2.11.2010, 12:12
Цитата(Yogurt @  1.11.2010,  14:04 Найти цитируемый пост)
По-поводу "сам файл, или его содержимое" - файл можно открыть стандартными средствами Винды. Мне интересно, можно ли программно заблокировать файл от Ворда, Экселя и, если получится, блокнота?
Это как? В смысле, что бы при попытке открыть файл Блокнотом, тот с грохотом падал и уносил с собой пол Винды?  smile 


Автор: Леопольд 2.11.2010, 12:53
Цитата(baldina @  1.11.2010,  15:17 Найти цитируемый пост)
unsigned char key = 0xED; // замените по вкусу
Код
unsigned char key = rand();
 smile 

Автор: Yogurt 2.11.2010, 13:28
Решил вопрос следующим образом:
Создал кодирующий/декодирующий класс. При открытии файла или изменении его содержимого все символы (строками или по отдельности) "проходят" через этот класс. Причём символы шифруются одним, двумя или тримя символами
Это не очень шустро, но пару секунд пользователь потерпеть может

Спасибо всем, кто отписался.

Для baldina : Байт, это не символ, это 8 бит. Символ по значению в разных кодировках значит разное. Как вариант - думал над побитовым считыванием байта, и затем поменять местами первую и вторую половину байта

Автор: Master01 2.11.2010, 14:29
Цитата

Для baldina : Байт, это не символ, это 8 бит. Символ по значению в разных кодировках значит разное. Как вариант - думал над побитовым считыванием байта, и затем поменять местами первую и вторую половину байта


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

Автор: baldina 2.11.2010, 16:58
Yogurt, 
Цитата(Yogurt @  2.11.2010,  13:28 Найти цитируемый пост)
Для baldina : Байт, это не символ, это 8 бит. Символ по значению в разных кодировках значит разное. 

http://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%B9%D1%82
http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D1%84%D0%B0%D0%B2%D0%B8%D1%82_(%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F)

Добавлено через 10 минут и 39 секунд
Цитата(Yogurt @  2.11.2010,  13:28 Найти цитируемый пост)
Причём символы шифруются одним, двумя или тримя символами
Это не очень шустро, но пару секунд пользователь потерпеть может

С реализацией все понятно. А с конечной целью не очень. Какие угрозы вы предотвращаете? Какой ущерб хотите предотвратить?
http://ru.wikipedia.org/wiki/%D0%91%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%B8
http://78.85.20.33:3232/department/security/secbasics/index.html
для начала...

а на "3" вопрос такой: какое отношение имеет фраза
Цитата

Символ по значению в разных кодировках значит разное

к шифрованию файла?

Автор: bass 6.11.2010, 20:47
Код

BOOL Kript(BYTE * Buffer,DWORD BufferLeght )
{
BYTE cript[0x1C] ={ //здесь ключ};
DWORD count2 =0x1c;//длина ключа
HCRYPTPROV hProv;
HCRYPTKEY hKey;
DWORD size = BufferLeght;
// Получение контекста криптопровайдера
if (!CryptAcquireContext(&hProv, NULL, NULL,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{return 0;}
if(!CryptImportKey(hProv, &cript[0], count2, 0, 0, &hKey))
{return 0;}
if (!CryptEncrypt(hKey, 0, true, 0, Buffer,&BufferLeght,size ))
{return 0;}
CryptReleaseContext(hProv,0);
return 1;
}
BOOL Deskript(BYTE * Buffer,DWORD BufferLeght )
{
BYTE cript[0x1C] ={};
DWORD count2 =0x1c;
HCRYPTPROV hProv;
HCRYPTKEY hKey;
//==================================расшифруем===================================
// Получение контекста криптопровайдера
if(!CryptAcquireContext(&hProv, NULL, NULL,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{return 0;}
if(!CryptImportKey(hProv,&cript[0], count2, 0, 0, &hKey))
{return 0;}
if(!CryptDecrypt(hKey, 0, true, 0, Buffer, &BufferLeght))
{return 0;}
CryptReleaseContext(hProv,0);
//============================================================================
return 1;
}


Зашифровал буфер расшифровал WinAPI А чтоб вордом нельзя было открыть CreateFile но только когда твое приложение запушено с флагом доступ в монопольном режиме.....

Автор: Yogurt 7.12.2010, 11:12
Забил на шифрование из за путаницы при исправлении файла, и сделал маленькую прогу. Текст файла лежит в файле txt, Unicode. Меняю местами все символы (Unicode = DWORD). Так как меняются ещё и символы переноса и окончания строки \n и \r, то после преобразования становится всё совсем непонятно. Всё восстанавливается тем же кодом.

Код

void CryptDword()
{
    // TODO: Add your control notification handler code here
    CStdioFile OFile, IFile;
    int Type;
    #ifdef _UNICODE
        Type = CFile::typeBinary;
    #else
        CFile::typeText;
    #endif

    OFile.Open(L"300.txt", Type | CFile::modeRead);
    IFile.Open(L"I300_new.txt", Type | CFile::modeCreate | CFile::modeWrite);

    ULONGLONG ByteLength = OFile.GetLength(); // байт
    
    BYTE b1, b2;
    WORD w1, w2;

    int i = 0;
    for(; i < ByteLength/4; i++)
    {
        
        //OFile.Read(&b1, sizeof(BYTE));
        //OFile.Read(&b2, sizeof(BYTE));

        //IFile.Write(&b2, sizeof(BYTE));
        //IFile.Write(&b1, sizeof(BYTE));

        OFile.Read(&w1, sizeof(WORD));
        OFile.Read(&w2, sizeof(WORD));

        IFile.Write(&w2, sizeof(WORD));
        IFile.Write(&w1, sizeof(WORD));

    }
    if(ByteLength%4 == 2)
    {
        OFile.Read(&w1, sizeof(WORD));
        IFile.Write(&w1, sizeof(WORD));
    }
    OFile.Close();
    IFile.Close();
}

Автор: xvr 7.12.2010, 12:30
Цитата(Yogurt @  7.12.2010,  11:12 Найти цитируемый пост)
Меняю местами все символы
Способ 'шифровки' взламывается наблюдением содержимого 'зашифрованного' файла в hex виде где то секунд за 5-10. 'Расшифровщик' пишется с нуля минут за 10.
Резюме - использовать в программе уровня выше 'Hello world!' категорически запрещается.


Автор: Yogurt 25.12.2010, 11:03
Прислушался к совету коллег, и попробовал зашифровать с помощью криптостойкого алгоритма, но в результате понял, что наиболее просто, это развернуть каждый байт (в моём случае - каждые 2 байта, тк Юником) в обратном направлении. Алгоритм получился симметричным (им зашифровываю и расшифровываю)
Собственно вот:
Код

// для h
...
    union 
    {
        WORD word_;//union_bit_reverse;
        struct
        {
            unsigned bit1:1;
            unsigned bit2:1;
            unsigned bit3:1;
            unsigned bit4:1;
            unsigned bit5:1;
            unsigned bit6:1;
            unsigned bit7:1;
            unsigned bit8:1;
            unsigned bit9:1;
            unsigned bit10:1;
            unsigned bit11:1;
            unsigned bit12:1;
            unsigned bit13:1;
            unsigned bit14:1;
            unsigned bit15:1;
            unsigned bit16:1;
        } bit;
    } WORD_UN_REVERSE, WORD_UN;
...

// для cpp
void Reverse()
{
    CStdioFile OFile, IFile;
    int Type;
    #ifdef _UNICODE
        Type = CFile::typeBinary;
    #else
        CFile::typeText;
    #endif

    OFile.Open(L"new.txt", Type | CFile::modeRead);
    IFile.Open(L"new1.txt", Type | CFile::modeCreate | CFile::modeWrite);

    ULONGLONG ByteLength = OFile.GetLength(); // байт
    
    BYTE b1, b2;
    WORD w1, w2;

    int i = 0;
    for(int j = 0; i < ByteLength/2; i++, j = j + 2)
    {
        OFile.Read(&w1, sizeof(WORD));

        int value = w1;
        WORD_UN.word_ = w1;

        WORD_UN_REVERSE.bit.bit1 = WORD_UN.bit.bit16;
        WORD_UN_REVERSE.bit.bit2 = WORD_UN.bit.bit15;
        WORD_UN_REVERSE.bit.bit3 = WORD_UN.bit.bit14;
        WORD_UN_REVERSE.bit.bit4 = WORD_UN.bit.bit13;
        WORD_UN_REVERSE.bit.bit5 = WORD_UN.bit.bit12;
        WORD_UN_REVERSE.bit.bit6 = WORD_UN.bit.bit11;
        WORD_UN_REVERSE.bit.bit7 = WORD_UN.bit.bit10;
        WORD_UN_REVERSE.bit.bit8 = WORD_UN.bit.bit9;
        WORD_UN_REVERSE.bit.bit9 = WORD_UN.bit.bit8;
        WORD_UN_REVERSE.bit.bit10 = WORD_UN.bit.bit7;
        WORD_UN_REVERSE.bit.bit11 = WORD_UN.bit.bit6;
        WORD_UN_REVERSE.bit.bit12 = WORD_UN.bit.bit5;
        WORD_UN_REVERSE.bit.bit13 = WORD_UN.bit.bit4;
        WORD_UN_REVERSE.bit.bit14 = WORD_UN.bit.bit3;
        WORD_UN_REVERSE.bit.bit15 = WORD_UN.bit.bit2;
        WORD_UN_REVERSE.bit.bit16 = WORD_UN.bit.bit1;

        IFile.Write(&WORD_UN_REVERSE.word_, sizeof(WORD));
    }

    if(ByteLength%2)
    {
        OFile.Read(&b1, sizeof(BYTE));
        IFile.Write(&b1, sizeof(BYTE));
    }
    
    OFile.Close();
    IFile.Close();
}


P.S. Делаю, как я уже писал, в МФК, но переделать по fopen() и тп не составит труда

Автор: xvr 25.12.2010, 13:31
Цитата(Yogurt @  25.12.2010,  11:03 Найти цитируемый пост)
попробовал зашифровать с помощью криптостойкого алгоритма, но в результате понял, что наиболее просто, это развернуть каждый байт (в моём случае - каждые 2 байта, тк Юником) в обратном направлении. 
Это у вас 'криптостойкий алгоритм'?  smile 
Возьмите RC4 и не мучайтесь
Код

class RC4 {
 unsigned char S[256];
 unsigned char ci, cj;

public:

 void set_seed(unsigned char K[256]);
 int get_byte();
};

int RC4::get_byte()
{
 ci++; cj+=S[ci];
 std::swap(S[ci],S[cj]);
 return S[(S[ci]+S[cj])&255];
}

void RC4::set_seed(unsigned char K[256])
{
 int i;
 for(i=0;i<255;++i) S[i]=i;
 ci=cj=0;
 unsigned char j=0;
 for(i=0;i<256;++i)
  {
   j+=S[i]+K[i];
   std::swap(S[i],S[j]);
  }
}


Использование:
Код

RC4 rc4;
rc4.set_seed(<key>); // ровно 256 байт, можно получить с помощью нескольких MD5 из пароля
while(!eof)
 {
   char c=read_in_byte();
   c^=rc4.get_byte();
   write_out_byte(c);
 }


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)