Криптография в С++

Николай "GоrluM" Андреев

Xakep, номер #051, стр. 051-082-2


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

0 на 0 = 0

0 на 1 = 1

1 на 0 = 1

1 на 1 = 0

В Си оператор xor выглядит как знак "^" (без кавычек). Чтобы проксорить два числа b и с (любого типа, двоичные разряды оператор получит сам), необходимо написать a = b ^ c. Соответственно, имея два символа, символ начальный и символ-ключ, мы можем получить зашифрованный символ и записать его в символ начальный. Вот пример: sim = sim ^ key. В C++ такая строка упрощается до sim ^= key. Это простое выражение уже шифрует один символ с другим. Нашей же программе понадобится зашифровать целый файл с ключом любой длины (т.е. не одним символом), заданным тобой.

Коротко о проекциях файлов

Для открытия файла мы воспользуемся API функцией CreateFile, в первом параметре которой будет содержаться полное имя открываемого файла, например: "C:\\password.txt". Заметь, когда пишешь строку прямо в программе, символ "\" нужно заменить символом "\\", иначе компилятор не поймет и подумает, что это какой-то спецсимвол (например, "\n" - символ перевода каретки). Функция CreateFile вернет нам хэндл открытого для чтения и записи файла hFile, после чего это значение мы передадим функции GetFileSize для того, чтобы узнать размер файла. И только теперь, открыв файл и зная его размер, мы создадим его ПРОЕКЦИЮ.

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

Проекцию мы создаем с помощью функции CreateFileMapping, в первом параметре передавая хэндл открытого нами файла, а в пятом - размер региона, выделяемого под файл. В данном случае он равен размеру файла. Функция нам вернет хэндл проекции (маппинга), который впоследствии мы передадим функции MapViewOfFile, чтобы получить указатель на маппинг в виде одной строки, т.е. массива символов, при редактировании которого все изменения тотчас же отражаются в файле.

Коротко об указателях

Если ты когда-нибудь видел хотя бы один исходник на C++, то мог заметить значок "*", который ставят перед объявлением некоторых переменных разного типа. Этот значок показывает, что данная переменная является указателем, т.е. переменной, адресующей данные в определенное место памяти. Например, я пишу:

char *str = "строка";

В переменной str сохраняются не все семь символов строки, а только адрес расположения этой строки в памяти. Поскольку char - это только один символ, для сохранения целой строки используется массив элементов типа char или указатель на этот массив. Но в случае с массивом ты заранее указываешь длину строки и количество элементов, а с указателем дело обстоит сложнее. Например, мы создали проекцию файла и получили на нее указатель как на строку, массив символов, но в си строкой является массив символов, оканчивающийся нулевым элементом (пишут "\0"). В файле же, в отличие от строки, такой элемент может быть где угодно, не обязательно в конце. Такой расклад не дает нам возможности использовать сишные строковые функции с указателем на проекцию, так как они определяют длину строки как расстояние от начала массива до \0. Но имея размер нашего файла, мы можем вручную обращаться к элементам массива, и это не приведет к ошибкам (например, при попытке открыть несуществующий элемент массива).

Назад на стр. 051-082-1  Содержание  Вперед на стр. 051-082-3