;----------------------------------------------------- ; Реализация универсального цикла шифрования алгоритма ; криптографического преобразования ГОСТ 28147-89. ; Copyright (C) 1992-1994 Винокуров А.Ю.,г.Москва. ;----------------------------------------------------- ;>Параметры при вызове: ; (DX,AX)=N1, (BP,DI)=N2; ; ES:SI - адрес ключа; ; DS:BX - адрес таблицы замен; ; CX - число основных шагов ;>Результаты на выходе: ; (BP,DI)=N1, (DX,AX)=N2 для циклов 32-З,32-Р; ; (DX,AX)=N1, (BP,DI)=N2 для цикла 16-З; ;>Используемые регистры: ВСЕ ;>Замечания: ; В конце выполнения содержимое регистров следующее: ; BX-(указатель таблицы замен) - то же, что в начале ; SI-(указатель ключа) - указывает на первый байт за ; ключом - это на 32*4=128 больше первоначального ; значения SI для циклов шифрования и на 16*4=64 ; больше первоначального значения для цикла выра- ; ботки имитоприставки ; CX=0 ; Содержимое сегментных регистров не изменяется. ;----------------------------------------------------- ; .model large,C .code $gost gost proc near public gost ; Внутренний цикл работы П/П ; 1. Начало цикла и сохранение старого N1 iloop: push DX push AX ; 2. Добавление к N1 ключа по модулю 2^32 add AX,ES:[SI] adc DX,ES:[SI+2] add SI,4 ; 3. Поблочная замена в S со сдвигом на 8 бит влево ! xlat ; перекодируем AL xchg AH,AL ; и меняем его с AH inc BH ; продвигаем указатель замены xlat ; перекодируем AH xchg DL,AL ; и меняем его с DL inc BH ; продвигаем указатель замены xlat ; перекодируем DL xchg DH,AL ; и меняем его с DH inc BH ; продвигаем указатель замены xlat ; перекодируем DH sub BH,3 ; BX <- его прежнее значение ; 4. Вращение S еще на 3 бита влево REPT 3 shl AX,1 rcl DX,1 adc AX,0 ENDM ; 5. Вычисление новых значений N1,N2 xor DX,BP xor AX,DI pop DI pop BP ; Завершение внутреннего цикла loop iloop ret gost endp end ;----------------------------------------------------- ; Шифрование массива данных в режиме простой замены ; Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ;----------------------------------------------------- ; Параметры при вызове передаются в стэке : ; Смещение Размер П А Р А М Е Т Р ; NEAR FAR ; 2 4 4 FAR-адрес ключа ; 6 8 4 FAR-адрес блока данных ; 10 12 4 FAR-адрес таблицы замен ; 14 16 2 Количество шифруемых блоков ;----------------------------------------------------- ; При выходе: адрес шифруемой области скорректирован ; Счетчик длины = 0 ;----------------------------------------------------- ; Зашифрование или расшифрование задается передачей ; соответствующего адреса ключа - порядок элементов ; в ключах зашифрования и расшифрования взаимно ; обратный. ;----------------------------------------------------- ; .model large,C .code $gost extrn gost:near simple proc public simple ; вычисляем смещение параметров в стэке a=8 ; 4 регистра в стэке IF (TYPE simple) EQ 0FFFEh a=a+2 ; если simple - far-процедура ENDIF ; Задаем смещение аргументов в стэке ; key= 2+a ; смещение адреса ключа syn= 6+a ; смещение адреса данных chg= 10+a ; смещение адреса табл. замен len= 14+a ; смещение счетчика блоков ; ; Сохранение регистров в соответствии с согл. Turbo C push BP push DS ; это не всегда обязательно push SI push DI ; Настройка рабочих регистров mov BP,SP ; стэковый кадр lds BX,chg[BP] ; таблица замен ; Загрузка блока в регистры circle: les SI,syn[BP] ; загрузка адр.с-поcылки mov AX,ES:[SI] ; AX <- младшее слово N1 mov DX,ES:2[SI] ; DX <- старшее слово N1 mov DI,ES:4[SI] ; DI <- младшее слово N2 mov CX,ES:6[SI] ; CX <- старшее слово N2 ; Готовим регистры и вызываем простую замену les SI,key[BP] mov BP,CX mov CX,32 call gost mov CX,BP mov BP,SP ; Запись результата на место les SI,syn[BP] ; загрузка адреса синхропопылки mov ES:[SI],DI ; з а н о с и м mov ES:2[SI],CX ; р е з у л ь т а т mov ES:4[SI],AX ; н а е г о mov ES:6[SI],DX ; м е с т о !!! ; Проверка на конец цикла dec WORD PTR len[BP]; коррекция счетчика jnz circle ; циклимся ; Восстановление регистров pop DI pop SI pop DS pop BP ret simple endp end ;------------------------------------------------------ ; Шифрование массива данных в режиме гаммирования ; согласно криптоалгоритму ГОСТ 28147-89 ; Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ;------------------------------------------------------ ; Параметры при вызове передаются в стэке : ; Смещение Размер П А Р А М Е Т Р ;NEAR FAR ; 2 4 4 FAR-адрес ключа ; 6 8 4 FAR-адрес синхропосылки (S1,S2) ; 10 12 4 FAR-адрес таблицы замен ; 14 16 4 FAR-адрес области назначения ; 18 20 2 число шифруемых блоков ;------------------------------------------------------ ; При выходе: адрес области назначения и длина ; содержат скорректированные параметры ;------------------------------------------------------ ; определяем константы C1,C2 по ГОСТ ; C1low equ 0101h C1high equ 0101h C2low equ 0104h C2high equ 0101h ; .model large,C .code $gost extrn gost:near gamma proc public gamma ; вычисляем смещение параметров в стэке a=8 ; 4 регистра в стэке IF (TYPE gamma) EQ 0FFFEh a=a+2 ; если gamma - far-процедура ENDIF ; Задаем смещение аргументов в стэке ; key= 2+a syn= 6+a chg= 10+a con= 14+a tar= 14+a len= 18+a ; ; Сохранение регистров согласно соглашениям Turbo C push BP push DS ; это нужно не всегда ! push SI push DI ; настройка регистров mov BP,SP ; стэковый кадр lds BX,chg[BP] ; DS:BX <- адрес табл.замен ; Добавление констант circle: les SI,syn[BP] ; адрес синхропопылки mov AX,ES:[SI] ; AX <- младшее слово S1 mov DX,ES:2[SI] ; DX <- старшее слово S1 mov DI,ES:4[SI] ; DI <- младшее слово S2 mov CX,ES:6[SI] ; CX <- старшее слово S2 add AX,C1low ; изменение S1: adc DX,C1high ; S1=(S1+C1) mod 2^32 stc ; для добавление 1 к N2 adc DI,C2low ; изменение S2: adc CX,C2high ; S2=(S2+C2) mod (2^32-1) cmc ; если не было переноса,то sbb DI,0 ; не стоило добавлять 1, sbb CX,0 ; поэтому S2=S2-1 mov ES:[SI],AX ; заносим новые mov ES:2[SI],DX ; значения S1,S2 mov ES:4[SI],DI ; на их mov ES:6[SI],CX ; место !!! ; Готовим регистры для вызова цикла 32-З; les SI,key[BP] ; ES:SI <- адрес ключа mov BP,CX ; BP <- старшее слово S2 mov CX,32 ; CX <- число основн. шагов call gost ; шаг простой замены mov CX,BP ; CX <- старшее слово S2 mov BP,SP ; BP <- стековый кадр ; Использование сгенерированного блока гаммы les SI,tar[BP] ; DS:SI<-адрес назначения xor ES:[SI],DI ; Гаммируем xor ES:2[SI],CX ; 8-байтный xor ES:4[SI],AX ; блок xor ES:6[SI],DX ; данных add word ptr tar[BP],8; коррекция указателя dec word ptr len[BP] ; коррекция счетчика jnz circle ; на генерацию нового блока ; Восстановление регистров из стэка pop DI pop SI pop DS pop BP ret gamma endp end ;------------------------------------------------------ ; Зашифрование массива данных в режиме гаммирования с ; обратной связью согласно алгоритму ГОСТ 28147-89 ; Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ;------------------------------------------------------ ; Параметры при вызове передаются в стэке : ; Смещение Размер П А Р А М Е Т Р ;NEAR FAR ; 2 4 4 FAR-адрес ключа ; 6 8 4 FAR-адрес синхропосылки (S1,S2) ; 10 12 4 FAR-адрес таблицы замен ; 14 16 4 FAR-адрес области назначения ; 18 20 2 число шифруемых блоков ;------------------------------------------------------ ; При выходе: адрес области назначения и синхропосылка ; содержат скорректированные параметры, счетчик = 0 ;------------------------------------------------------ ; .model large,C .code $gost extrn gost:near gammaLE proc public gammaLE ; вычисляем смещение параметров в стэке a=8 ; 4 регистра в стэке IF (TYPE gammaLE) EQ 0FFFEh a=a+2 ; если gamma - far-процедура ENDIF ; Задаем смещение аргументов в стэке ; key= 2+a syn= 6+a chg= 10+a tar= 14+a len= 18+a ; ; Сохранение регистров согласно соглашениям Turbo C push BP push DS ; это нужно не всегда ! push SI push DI ; Добавление констант mov BP,SP ; настройка стэкового кадра lds SI,syn[BP] ; DS:SI -> синхропопылка mov AX,[SI] ; AX <= младшее слово S1 mov DX,2[SI] ; DX <= старшее слово S1 mov DI,4[SI] ; DI <= младшее слово S2 mov CX,6[SI] ; CX <= старшее слово S2 lds BX,chg[BP] ; DS:BX <- адрес табл.замен ; Готовим регистры и вызываем цикл 32-З circle: les SI,key[BP] ; ES:SI <- адрес ключа mov BP,CX ; BP <- старшее слово S2 mov CX,32 ; CX <- число основн. шагов call gost ; шаг простой замены mov CX,BP ; CX <- старшее слово S2 mov BP,SP ; BP <- стековый кадр ; Использование сгенерированного блока гаммы les SI,tar[BP] ; DS:SI<-адрес назначения ; будет альтернатива xor DI,ES:[SI] ; Гаммируем xor CX,ES:2[SI] ; 8-байтный xor AX,ES:4[SI] ; блок xor DX,ES:6[SI] ; данных mov ES:[SI],DI ; и записываем mov ES:2[SI],CX ; его mov ES:4[SI],AX ; на нужное mov ES:6[SI],DX ; место xchg AX,DI ; обмен значениями xchg DX,CX ; S1 <--> S2 ; альтернатива последним 10 строкам:короче,но медленнее ; на процессорах 8086,8088. ; xor ES:[SI],DI ; Гаммируем ; xor ES:2[SI],CX ; 8-байтный ; xor ES:4[SI],AX ; блок ; xor ES:6[SI],DX ; данных ; mov AX,ES:[SI] ; загружаем ; mov DX,ES:2[SI] ; блок для ; mov DI,ES:4[SI] ; следующего ; mov CX,ES:6[SI] ; шага ; альтернатива закончена add word ptr tar[BP],8; коррекция указателя dec word ptr len[BP] ; коррекция счетчика jnz circle ; на генерацию нового блока ; заносим новое значение синхропосылки на его место ; (это нужно для обработки массива данных частями) lds SI,syn[BP] ; DS:SI -> синхропосылка mov [SI],AX ; заносим новые mov 2[SI],DX ; значения S1,S2 mov 4[SI],DI ; на их mov 6[SI],CX ; место !!! ; Восстановление регистров из стэка pop DI pop SI pop DS pop BP ret gammaLE endp end ;------------------------------------------------------ ; Расшифрование массива данных в режиме гаммирования с ; обратной связью согласно алгоритму ГОСТ 28147-89 ; Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ;------------------------------------------------------ ; Параметры при вызове передаются в стэке : ; Смещение Размер П А Р А М Е Т Р ;NEAR FAR ; 2 4 4 FAR-адрес ключа ; 6 8 4 FAR-адрес синхропосылки (S1,S2) ; 10 12 4 FAR-адрес таблицы замен ; 14 16 4 FAR-адрес области назначения ; 18 20 2 число шифруемых блоков ;------------------------------------------------------ ; При выходе: адрес области назначения и синхропосылка ; содержат скорректированные параметры, счетчик = 0 ;------------------------------------------------------ ; .model large,C .code $gost extrn gost:near gammaLD proc public gammaLD ; вычисляем смещение параметров в стэке a=8 ; 4 регистра в стэке IF (TYPE gammaLD) EQ 0FFFEh a=a+2 ; если gamma - far-процедура ENDIF ; Задаем смещение аргументов в стэке ; key= 2+a syn= 6+a chg= 10+a tar= 14+a len= 18+a ; ; Сохранение регистров согласно соглашениям Turbo C push BP push DS ; это нужно не всегда ! push SI push DI ; Загрузка регистров для вызова цикла шифрования mov BP,SP ; настройка стэкового кадра lds SI,syn[BP] ; DS:SI -> синхропопылка mov AX,[SI] ; AX <= младшее слово S1 mov DX,2[SI] ; DX <= старшее слово S1 mov DI,4[SI] ; DI <= младшее слово S2 mov CX,6[SI] ; CX <= старшее слово S2 lds BX,chg[BP] ; DS:BX <- адрес табл.замен ; Готовим регистры для вызова цикла 32-З; circle: les SI,key[BP] ; ES:SI <- адрес ключа mov BP,CX ; BP <- старшее слово S2 mov CX,32 ; CX <- число основн. шагов call gost ; шаг простой замены mov CX,BP ; CX <- старшее слово S2 mov BP,SP ; BP <- стековый кадр ; Использование сгенерированного блока гаммы les SI,tar[BP] ; DS:SI<-адрес назначения xor DI,ES:[SI] ; Гаммируем xor CX,ES:2[SI] ; 8-байтный xor AX,ES:4[SI] ; блок xor DX,ES:6[SI] ; данных xchg ES:[SI],DI ; меняем xchg ES:2[SI],CX ; его с xchg ES:4[SI],AX ; блоком xchg ES:6[SI],DX ; шифротекста xchg AX,DI ; обмен значениями xchg DX,CX ; S1 <--> S2 add word ptr tar[BP],8; коррекция указателя dec word ptr len[BP] ; коррекция счетчика jnz circle ; на генерацию нового блока ; заносим новое значение синхропосылки на его место ; (это нужно для обработки массива данных частями) lds SI,syn[BP] ; DS:SI -> синхропосылка mov [SI],AX ; заносим новые mov 2[SI],DX ; значения S1,S2 mov 4[SI],DI ; на их mov 6[SI],CX ; место !!! ; Восстановление регистров из стэка pop DI pop SI pop DS pop BP ret gammaLD endp end ;------------------------------------------------------ ; Выработка имитоприставки для массива данных согласно ; алгоритму ГОСТ 28147-89 ; Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ;------------------------------------------------------ ; Параметры при вызове передаются в стэке : ; Смещение Размер П А Р А М Е Т Р ;NEAR FAR ; 2 4 4 FAR-адрес ключа ; 6 8 4 FAR-адрес исходной комбинации ; 10 12 4 FAR-адрес таблицы замен ; 14 16 4 FAR-адрес области назначения ; 18 20 2 число сворачиваемых блоков ;------------------------------------------------------ ; При выходе: адрес области данных и контрольная комби- ; нация содержат скорректированные параметры, счетчик=0 ; DX:AX содержит младшее двойное слово контрольной ; комбинации, используемое обычно как имитоприставка - ; соответствует возврату типа Item (=unsigned long). ;------------------------------------------------------ ; .model large,C .code $gost extrn gost:near imito proc public imito ; вычисляем смещение параметров в стэке a=8 ; 4 регистра в стэке IF (TYPE imito) EQ 0FFFEh a=a+2 ; если gamma - far-процедура ENDIF ; Задаем смещение аргументов в стэке ; key= 2+a syn= 6+a chg= 10+a tar= 14+a len= 18+a ; ; Сохранение регистров согласно соглашениям Turbo C push BP push DS ; это нужно не всегда ! push SI push DI ; Загружаем значение комбинации от прошлого раза mov BP,SP ; настройка стэкового кадра lds SI,syn[BP] ; DS:SI -> синхропопылка mov AX,[SI] ; AX <= младшее слово S1 mov DX,2[SI] ; DX <= старшее слово S1 mov DI,4[SI] ; DI <= младшее слово S2 mov CX,6[SI] ; CX <= старшее слово S2 lds BX,chg[BP] ; DS:BX <- адрес табл.замен ; Добавляем блок данных circle: les SI,tar[BP] ; DS:SI<-адрес назначения xor AX,ES:[SI] ; Гаммируем xor DX,ES:2[SI] ; 8-байтный xor DI,ES:4[SI] ; блок xor CX,ES:6[SI] ; данных ; Готовим регистры и вызываем цикл 32-З les SI,key[BP] ; ES:SI <- адрес ключа mov BP,CX ; BP <- старшее слово S2 mov CX,16 ; CX <- число основн. шагов call gost ; шаг простой замены mov CX,BP ; CX <- старшее слово S2 mov BP,SP ; BP <- стековый кадр add word ptr tar[BP],8; коррекция указателя dec word ptr len[BP] ; коррекция счетчика jnz circle ; на генерацию нового блока ; заносим новое значение комбинации на его место ; (это нужно для обработки массива данных частями) les SI,syn[BP] ; DS:SI -> синхропосылка mov ES:[SI],AX ; заносим новые mov ES:2[SI],DX ; значения S1,S2 mov ES:4[SI],DI ; на их mov ES:6[SI],CX ; место !!! ; Восстановление регистров из стэка pop DI pop SI pop DS pop BP ret imito endp end /*----------------------------------------------------- Построение расширенной таблицы замен (1024 Байт) из таблицы замен (128 Байт) алгоритма ГОСТ 28147-89. Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ----------------------------------------------------- Параметры при вызове: source - адрес таблицы замен в исходном формате target - адрес области для расширенной таблицы ----------------------------------------------------- */ #pragma inline #include // FP_SEG,FP_OFF void ExpCht (void far *source, void far *target) { // Настройка регистров для работы П/П asm push DS _DS= FP_SEG (source); _SI= FP_OFF (source); _ES= FP_SEG (target); _DI= FP_OFF (target); asm { cld // направление просмотра // Цикл по блокам таблицы замен mov CX,4 // загрузить счетчик блоков } blocks: asm { mov BX,SI // BX<-адрес начала линии add BX,10h // старших байтов блока // Цикл по линиям блока push CX // сохранить счетчик блоков mov CX,16 // загрузить счетчик линий } lines: asm { push SI // сохр. указ. текущ. блока mov AH,[BX] // AH <- старший полубайт push CX // сохранить счетчик линий mov CL,4 // сдвиг полубайта на место shl AH,CL // старшего полубайта // Цикл по байтам линии mov CX,16 // загрузить счетчик байтов } bytes: asm { lodsb // загрузить очередной байт or AL,AH // добавить старший полубайт stosb // ... и записать результат loop bytes // цикл по байтам линни // Проверка цикла по линиям pop CX // восстанов. счетчик линий pop SI // восст. указат. тек. блока inc BX // продвинуть указатель байт loop lines // цикл по строкам таблицы // Проверка цикла по блокам pop CX // восстанов. счетчик блоков add SI,20h // продвинуть указат. блока loop blocks // цикл по блокам } asm pop DS return ; } /*----------------------------------------------------- Построение расширеннго ключа зашифрования (128 байт) из ключа (32 байта) криптоалгоритма ГОСТ 28147-89. Copyright (C) 1992-1994 Винокуров А.Ю., г. Москва. ----------------------------------------------------- Параметры при вызове: source - FAR-адрес ключа в исходном формате target - FAR-адрес области для расширения ключа Схема расширения 3+1: 3 раза вперед, 1 раз назад ----------------------------------------------------- */ #pragma inline #include void ExpKey31 (void far *source, void far *target) { // Настройка регистров для работы П/П asm push DS _DS= FP_SEG (source); _SI= FP_OFF (source); _ES= FP_SEG (target); _DI= FP_OFF (target); asm { cld // направление просмотра ; Три прямых блока mov CX,16 // копировать rep movsw // первый sub SI,32 // блок mov CX,16 // копировать rep movsw // второй sub SI,32 // блок mov CX,16 // копировать rep movsw // третий блок ; один обратный блок mov CX,8 // счетчик двойных слов } xlp: asm { sub SI,4 // указатель двойн. слова mov AX,[SI] // загрузить младш. слово stosw // ... и запомнить его mov AX,2[SI]// загрузить старш. слово stosw // ... и запомнить его loop xlp // цикл по двойным словам pop DS } return ; }/*---------------------------------------------------- gost.h -- описания данных и прототиипы функций шиф- рования. ---------------------------------------------------- Версия 1.00 от 25.06.94, (c) 1994 Винокуров А.Ю. ---------------------------------------------------- */ typedef unsigned long Item; // элемент данных typedef struct { Item low,high; } CrBlock; void ExpCht ( // Расширение таблицы замен void far *source, // область исходной ТЗ void far *target); // область расширенной ТЗ void ExpKey31 ( // Расширение ключа '3+1' void far *source, // область исходного ключа void far *target); // область расширен. ключа void ExpKey33 ( // Расширение ключа '3+3' void far *source, // область исходного ключа void far *target); // область расширен. ключа void ExpKey13 ( // Расширение ключа '1+3' void far *source, // область исходного ключа void far *target); // область расширен. ключа void gamma ( // Гаммирование данных void far *key, // адрес ключа void far *synchro, // адрес синхропосылки void far *xcht, // адрес таблицы замен void far *data, // адрес гаммируемых данных unsigned short blocks);// число шифруемых блоков void gammaLE( // Зашифрование-гаммир. с ОС void far *key, // адрес ключа void far *synchro, // адрес синхропосылки void far *xcht, // адрес таблицы замен void far *data, // адрес гаммируемых данных unsigned short blocks);// число шифруемых блоков void gammaLD( // Расшифрование-гаммир. с ОС void far *key, // адрес ключа void far *synchro, // адрес синхропосылки void far *xcht, // адрес таблицы замен void far *data, // адрес гаммируемых данных unsigned short blocks);// число шифруемых блоков void simple( // Шифрование простой заменой void far *key, // адрес ключа void far *data, // адрес шифруемых данных void far *xcht, // адрес таблицы замен unsigned short blocks);// число шифруемых блоков Item imito ( // Вычисление имитоприставки void far *key, // адрес ключа void far *combine, // адрес начальной комбинации void far *xcht, // адрес таблицы замен void far *data, // адрес гаммируемых данных unsigned short blocks);// число блоков /*---------------------------------------------------- cryptor.c -- исходный текст программы шифрования файлов. ---------------------------------------------------- Версия 1.00 от 25.06.94, (c) 1994 Винокуров А.Ю. ---------------------------------------------------- Эта программа специально составлена для публикации в журнале - см. там описание применения. ---------------------------------------------------- */ #include // open, filelength #include // O_RDONLY #include // MAXPATH #include // toupper #include // strtoul #include // printf #include // setmem #include "gost.h" // Данные и прототипы ГОСТа // размер буфера обмена - должен быть кратен 8 #define BUFFER_SIZE 8192 // Глобальные статические данные unsigned _stklen=BUFFER_SIZE+4096; // размер стэка typedef enum { O_K_=0, // все тип-топ errDoNotMatch, // несовпадение имитоприставки errInvalidFlag, // неверный флаг вызова программы errBadSynchro, // неверно задана синхропосылка errBadImito, // неверно задана имитоприставка errTooFiewParm, // мало параметров вызова errTooManyParm, // много параметров вызова errBadKey, // плохой файл ключа errBadXCHT, // плохой файл с таблицей замен errInvalidOper, // неверная операция errSourceFailure, // ошибка на файле-источнике errTargetFailure, // ошибка на файле-приемнике errRenameFailure, // ошибка при переименовании errDeleteFailure // ошибка при удалении исх. файла } errList; unsigned char chtab[1024]; Item Key[32]; // развернутый ключ Item Synchro[2]= // синхропосылка { 0UL,0UL }; Item Imito[2]= { 0UL,0UL }; Item _Imito; errList code=O_K_; // код выхода int BackLink= 0; // шифровать с ОС int ShowImito= 0; // показать имитоприставку int CheckImito=0; // проверить имитоприставку int Operation= 0; // зашифрование int ParmCount= 0; // счетчик параметров int Deletion= 0; // удаление исходника char *KeyFile= NULL;// файл ключа char *ChtFile= NULL;// файл таблицы замен char *InFile= NULL;// исходный файл char *OutFile= NULL;// файл результата // Прототипы функций errList setParam (int argc, char **argv); errList SignalError (errList errType, char *errPlace); errList loadCht (void); errList loadKey (void); errList execute (void); // Главная программа модуля errList main(int argc, char *argv[]) { unsigned short i; printf("Программа шифрования данных с помощью " "криптографического алгоритма ГОСТ 28147-89\n" "Составил А.Ю. Винокуров, июнь 1994 года," " свободное использование и копирование\n"); // Этот цикл строит тривиальную таблицу замен for (i=0; i<1024; i++) chtab[i]=i; // Удалите его, если будете инициализировать chtab return (code=setParam(argc,argv))!=O_K_ ? code : !InFile ? SignalError(errTooFiewParm,NULL) : (ChtFile && loadCht() != O_K_) ? SignalError(errBadXCHT,ChtFile) : (KeyFile && loadKey() != O_K_) ? SignalError(errBadKey,KeyFile) : execute(); } // установка режимов согласно флагам вызова errList setParam(int argc, char **argv) { for ( ; ++argv,--argc; ) // просмотр аргументов { char *c; if (**argv=='/') // ключ командной строки switch (toupper(*(*argv+1))) // выбор по букве { case 'D': Deletion=1; break; case 'B': BackLink=1; break; case 'N': BackLink=0; break; case 'K': KeyFile=*argv+2;break; case 'C': ChtFile=*argv+2;break; case 'S': if (Synchro[0]=strtoul(*argv+2,&c,16),*c) return SignalError(errBadSynchro,*argv+2),1; break; case 'I': if (*(*argv+2)) if (_Imito=strtoul(*argv+2,&c,16),*c) return SignalError(errBadImito,*argv+2); else CheckImito=ShowImito=1; else ShowImito=1; break; default: return SignalError(errInvalidFlag,*argv); } else switch(ParmCount++) // другой аргумент { default: return SignalError(errTooManyParm,*argv); case 0: // декодируем функцию if (*(*argv+1)) // не одна буква return SignalError(errInvalidOper,*argv); switch(toupper(**argv)) // что за буква ? { default: // ошибка return SignalError(errInvalidOper,*argv); case 'D': Operation=1;// расшифрование case 'E':; // зашифрование } break; case 1: // определяем источник InFile=*argv; break; case 2: // определяем приемник OutFile=*argv; } } return O_K_; } // Загрузка таблицы замен errList loadCht(void) { int handle,FileSize; unsigned char buffer[128]; if ((handle=open(ChtFile,O_RDONLY))==-1 || ((FileSize=filelength(handle)) != 128 && FileSize != 1024) || read(handle, FileSize==128 ? buffer : chtab,FileSize)==-1) return errBadKey; if (FileSize == 128) ExpCht(buffer,chtab); close(handle); return O_K_; } // Загрузка ключа errList loadKey(void) { int handle,FileSize; unsigned char buffer[32]; if ((handle=open(KeyFile,O_RDONLY))==-1 || ((FileSize=filelength(handle)) != 32 && FileSize != 128) || read(handle, FileSize==32 ? (void*) buffer : (void*) Key, FileSize)==-1) return errBadKey; if (FileSize==32) ExpKey31(buffer,Key); close(handle); return O_K_; } // Осуществление шифрования errList execute(void) { int inHandle,outHandle,same; long FileSize; char buffer[BUFFER_SIZE]; // подготовка файлов simple(Key,Synchro,chtab,1); if (same=!OutFile) OutFile="$$$$$$$$.$$$"; if((inHandle=open(InFile,O_RDONLY|O_BINARY))==-1 || (FileSize=filelength(inHandle))== -1) return SignalError(errSourceFailure,InFile); if((outHandle=open(OutFile, O_WRONLY|O_CREAT|O_BINARY))==-1) return SignalError(errTargetFailure,OutFile); printf("%sшифрование файла %s\n", Operation ? "Рас" : "За", InFile); // цикл шифрования for ( ; FileSize>0 ; FileSize-=BUFFER_SIZE) { unsigned short quant=min(BUFFER_SIZE,FileSize), blocks=(quant+sizeof(CrBlock)-1)/sizeof(CrBlock); if (read(inHandle,buffer, quant) == -1) return SignalError(errSourceFailure,InFile); if (!Operation && ShowImito) { if (FileSize % 8) setmem(buffer+FileSize,8-FileSize % 8,0); imito (Key,Imito,chtab,buffer,blocks); } (BackLink ? Operation ? gammaLD : gammaLE : gamma) (Key,Synchro,chtab,buffer,blocks); if (Operation && ShowImito) { if (FileSize % 8) setmem(buffer+FileSize,8-FileSize % 8,0); imito (Key,Imito,chtab,buffer,blocks); } if (write(outHandle,buffer, quant) == -1) return SignalError(errTargetFailure,OutFile); } // завершающие действия close(inHandle); close(outHandle); if(ShowImito) { printf("Имитоприставка"); if(CheckImito) printf(" %s совпадает !\n", Imito[1]==_Imito ? "" : " НЕ "); else printf("=%lx\n",Imito[1]); } if (Deletion || same) { if (unlink(InFile)==-1) return SignalError(errDeleteFailure,InFile); if (same && rename(OutFile,InFile)==-1) return SignalError(errRenameFailure,InFile); } return O_K_; } // Выдача сообщения об ошибке errList SignalError(errList errType, char *errPlace) { char *errText[]= { "Неверный флаг вызова рограммы - %s\n", "Неверно задана синхропосылка - %s\n", "Неверно задана имитоприставка - %s\n", "Необходим код функции и имя шифруемого файла\n", "Лишний параметр вызова - %s\n", "Неверно задан файл с ключом - %s\n", "Неверно задан файл с таблицей замен - %s\n", "Неверно задана выполняемая операция - %s " "(нужно E или D)\n", "Ошибка на исходном файле - %s\n", "Ошибка на файле результата - %s\n", "Невозможно переименовать файл $$$$$$$$.$$$ в %s\n", "Невозможно удалить файл %s\n" }; printf(errText[errType-2],errPlace); return errType; } Листинг 11 .AUTODEPEND # Определения транслятора, ассемблера, компоновщика CC = bcc +CRYPTOR.CFG TASM = TASM /MX /ZI /O TLINK = tlink # НЕявные правила .c.obj: $(CC) -c {$< } .cpp.obj: $(CC) -c {$< } # Определенные символы EXE_dependencies = \ cryptor.obj \ expcht.obj \ expkey31.obj \ gost.obj \ simple.obj \ gamma.obj \ gammald.obj \ gammale.obj \ imito.obj # Явные правила cryptor.exe: cryptor.cfg $(EXE_dependencies) $(TLINK) /v/x/c/LC:\BC\LIB @&&| c0c.obj+ cryptor.obj+ expcht.obj+ expkey31.obj+ gost.obj+ simple.obj+ gamma.obj+ gammald.obj+ gammale.obj+ imito.obj cryptor # no map file emu.lib+ mathc.lib+ cc.lib | # Индивидуальные зависимости cryptor.obj: cryptor.c expcht.obj: expcht.c expkey31.obj: expkey31.c gost.obj: gost.asm $(TASM) GOST.ASM,GOST.OBJ simple.obj: simple.asm $(TASM) SIMPLE.ASM,SIMPLE.OBJ gamma.obj: gamma.asm $(TASM) GAMMA.ASM,GAMMA.OBJ gammald.obj: gammald.asm $(TASM) GAMMALD.ASM,GAMMALD.OBJ gammale.obj: gammale.asm $(TASM) GAMMALE.ASM,GAMMALE.OBJ imito.obj: imito.asm $(TASM) IMITO.ASM,IMITO.OBJ # *Compiler Configuration File* cryptor.cfg: cryptor.mak copy &&| -mc -C -v -y -IC:\BC\INCLUDE -LC:\BC\LIB | cryptor.cfg