Криптон. Оживляем «криптографический танк» из девяностых

Приветствую всех!

Не так давно я рассказывал про построенный на базе «гражданского» девайса портативный шифратор ‭«Электроника МК-85С‭». Самое время поведать миру о ещё одном, не менее значимом, но чуть менее известном девайсе — отечественном криптопроцессоре «Блюминг-1», а также об алгоритме, который он реализовывал.

Криптон. Оживляем «криптографический танк» из девяностых

Итак, в сегодняшней статье рассмотрим ещё одного представителя российской шифровальной техники — построенную на данном чипе плату шифрования ‭«Криптон‭». Узнаем, как работает эта штука и где она применялась. Заодно посмотрим на её софт и попробуем что-то зашифровать. Как водится, будет много интересного.

❯ Суть такова

История данного устройства началась в середине семидесятых годов, когда начал разрабатываться алгоритм ГОСТ 28147-89 (он же ‭«Магма-2‭»), по принципу работы напоминающий DES. Создавался он в ходе проекта по разработки криптографических систем защиты информации на ЭВМ Единой системы. Требования, предъявлявшиеся к нему, были крайне высокими: предполагалось, что шифровать им будут информацию высокой степени секретности, причём сам алгоритм секретным был быть не должен.

В 1987 году было создано и устройство шифрования — криптопроцессор ‭«Блюминг-1‭», реализующий данный алгоритм. Примечателен он тем, что стал первым отечественным однокристальным шифратором, давшим начало развития целой области средств защиты информации у нас.

Криптон. Оживляем «криптографический танк» из девяностых

А вот и построенная на базе данного чипа плата «Дебют-3». Существовало три версии: «1» для ЭВМ ДВК, «2» — для Системы малых ЭВМ, «3» — для PC с шиной ISA.

Криптон. Оживляем «криптографический танк» из девяностых
Криптон. Оживляем «криптографический танк» из девяностых

Плата «Криптон-3», дальнейшее развитие платы «Дебют» (ввиду того, что СМ ЭВМ и ДВК были выведены из эксплуатации, «Криптон-1» и «Криптон-2» так и не суждено было появиться). Следом за ней вышла более продвинутая «Криптон-4». Выпускались они зеленоградским предприятием «ANCUD» (что означало «Angstrem custom design»). Несмотря на довольно похожее название, к ранее упоминавшемуся АНКОРТу отношения оно не имеет.

Небольшой прикол:

Есть у меня любовь к поиску и документированию ошибок и опечаток в объявлениях, на сайтах и где-то ещё. Чем глупее ошибка и чем серьёзнее место обнаружения — тем веселее. Сайт ANCUD здесь тоже отличился аж тройным неправильным описанием одного и того же слова…

Криптон. Оживляем «криптографический танк» из девяностых

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

Криптон. Оживляем «криптографический танк» из девяностых

Снова «Криптон-3», но в несколько другом исполнении. Увы, я общался с товарищем, кому удалось её достать, но запустить её не удалось…

❯ Обзор оборудования

Про эти платы не удалось найти практически никакой информации. Даже при банальном поиске «Криптон-4» обнаруживается мало чего. Так что сейчас немного развеем завесу тайны.

Криптон. Оживляем «криптографический танк» из девяностых

Перво-наперво идёт сама плата «Криптон-4». Рассмотрим её поподробнее. По центру два базовых матричных кристалла Н1515ХМ1, обеспечивающих связь шифропроцессоров с компьютером. Слева от них в опечатанной панельке ПЗУшка, в которой содержится BIOS устройства. Ещё левее два диода в стеклянных корпусах. Это 2Г401 — специализированные германиевые диоды, предназначенные для использования в генераторах шума. Как нетрудно догадаться, здесь на них выполнен аппаратный генератор случайных чисел. Потенциометры на плате, вероятно, служат для его подстройки (хотя, конечно, могу ошибаться, никакой информации на этот счёт я не нашёл). Над БМК находятся два чипа КБ1 — те самые шифропроцессоры. Возле планки нераспаянный разъём DB9 для подключения считывателя смарт-карт. В правом верхнем углу ещё одна ПЗУшка — КР556РТ11. В ней записан индивидуальный номер платы, написанный также на приклеенной к микросхеме бумажке. Номер этот используется для идентификации устройства программами: некоторый софт будет работать исключительно с той платой, для которой разрабатывался.

Криптон. Оживляем «криптографический танк» из девяностых
Криптон. Оживляем «криптографический танк» из девяностых

Дискеты с софтом.

Криптон. Оживляем «криптографический танк» из девяностых
Криптон. Оживляем «криптографический танк» из девяностых

А вот более старые версии софта. Что от чего, мне неведомо, досталось всё одной кучей.

Криптон. Оживляем «криптографический танк» из девяностых

Ещё один дистрибутив софта — LiteSign. В отличие от остальных дискет, эта в опечатанной коробочке (которую до меня уже, разумеется, открывали).

Криптон. Оживляем «криптографический танк» из девяностых

А вот более новая версия платы, уже на PCI. Чипы шифраторов изменили свои корпуса, вместо БМК теперь ПЛИС. Шумовые диоды также, очевидно, никуда не подевались. Разъём 4P4C, предназначенный для подключения ключа iButton.

Криптон. Оживляем «криптографический танк» из девяностых

На обратной стороне этикетка — изделие М-503Г. По сравнению с предыдущей платой, железка не такая уж и древняя.

Криптон. Оживляем «криптографический танк» из девяностых

На этом история данных устройств не заканчивается. Следующим шагом было избавление от керамических чипов шифраторов. Их обязанности были возложены на ПЛИС. Плата же получила название Криптон-8/PCI.

Криптон. Оживляем «криптографический танк» из девяностых

Последняя (если верить сайту ANCUD) версия — Криптон-10/PCI-E.

Криптон. Оживляем «криптографический танк» из девяностых

Параллельно с абонентскими шифраторами выпускаются и средства доверенной загрузки — Криптон-Замок.

❯ Инструкция и софт

Криптон. Оживляем «криптографический танк» из девяностых

Помимо платы и дискет мне достался мануал, который я не поленился отсканировать. Страниц в нём немного, так что я разместил его прямо тут.

Также я оцифровал все имеющиеся у меня дискеты и выложил файлы на old-dos.ru. Помимо этого прочесал архивы сайта ANCUD и все найденные материалы также залил туда.

❯ Первый запуск

Ну что же, время запускать!

Криптон. Оживляем «криптографический танк» из девяностых

В качестве тестового компа будем использовать вот такую плату на процессоре 386SX. Втыкаем в неё всё нужное железо и плату шифрования, и пробуем включать.

Криптон. Оживляем «криптографический танк» из девяностых

После прохождения POST запускается BIOS платы.

Криптон. Оживляем «криптографический танк» из девяностых

Хранилища ключей у неё нет, поэтому они подтягиваются при загрузке с дискет или считывателей смарт-карт, где остаются до отключения питания. Тестовые ключи (узел замены и главный ключ) находятся на комплектной дискете. Нужны они для запуска платы, если ни одного «боевого» ключа ещё не сгенерировано.

Криптон. Оживляем «криптографический танк» из девяностых

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

❯ Шифруем и расшифровываем

Криптон. Оживляем «криптографический танк» из девяностых

Теперь запускаем главный софт — crtools. По сути это и есть утилита для шифрования, далёкий предок всяческих «КриптоАРМ» и тому подобного ПО. Здесь достаточно выбрать нужный файл и запустить операцию из меню, после чего он будет зашифрован или расшифрован. Никаких кодов, секретных комбинаций кнопочек и тому подобных манипуляций, всё делается за пару секунд в несколько нажатий клавиш.

Криптон. Оживляем «криптографический танк» из девяностых

Параметры системы.

❯ Генератор ключей

Криптон. Оживляем «криптографический танк» из девяностых

В отличие от «Электроники МК-85С», где для генерации марканта надо было жмякать кнопку, или многих используемых сейчас систем, где требуется жмякать все клавиши и водить туда-сюда мышью для создания случайной последовательности, в «Криптоне» есть аппаратный датчик случайных чисел, что позволяет генерировать эти ключи практически моментально. Также для дополнительной защиты свежесозданный ключ можно защитить паролем.

❯ ЭЦП и неожиданный облом

Следующей на очереди идёт программа CryptonSign, предназначавшаяся для цифровой подписи.

Криптон. Оживляем «криптографический танк» из девяностых

Однако при попытке её запустить меня ждала неудача: программа выдала ошибку о каком-то неверном номере.Помните ту ПЗУшку с номером платы? Да, именно для подобных целей она и используется. Просто поражает, насколько мелкосерийным было это производство: ПЗУ с уникальным номером, написанным на нём от руки, дистрибутив с софтом, уникальный для каждой платы. Судя по всему, использовался какой-то самописный генератор дистрибутивов, выдававший экзешник, залоченный на определённую плату, но не удивлюсь, если этот номер там и вовсе захардкожен, а для каждой платы софт пересобирали. Точные объёмы производства мне неведомы, но выпущено было буквально две-три тысячи плат, совсем немного по меркам компьютерного железа.

❯ LiteSign

Криптон. Оживляем «криптографический танк» из девяностых

Софт из коробочки тоже оказался непрост.

Криптон. Оживляем «криптографический танк» из девяностых

Помимо привязки к серийному номеру платы он также имеет защиту от копирования, не дающую установить его больше, чем на один ПК. Защита довольно типичная для тех лет: на магнитном диске лазером специально сделаны бэд-блоки, а софт при считывании проверяет их наличие.При установке программа удаляется с дискеты и записывается на винт, а при удалении — возвращается обратно. Что делать, если жёсткий диск сдохнет или окажется заражён вирусом, увы, не уточняется.

❯ Эмулятор и софт под Windows

Напоследок взглянем на то, какой софт существовал для работы с шифратором в среде Windows. Выпущен он уже куда позднее, нежели тот, что под DOS, также имеет защиту от копирования (на этот раз с помощью аппаратного ключа для LPT-порта) и сейчас доступен только в демо-версии по причине прекращения продаж и отсутствия «кряка». Впрочем, для того, чтобы увидеть его в работе, этого более чем достаточно.На случай, если платы нет, можно воспользоваться эмулятором (для Windows 9x/NT4.0/2000).

Криптон. Оживляем «криптографический танк» из девяностых

Первым делом ставим необходимый для работы всего софта Crypton API.

Криптон. Оживляем «криптографический танк» из девяностых

Теперь накатываем эмулятор, и всё, можно пробовать запускать ПО.

Криптон. Оживляем «криптографический танк» из девяностых

Помимо софта для шифрования отдельных файлов ANCUD также предоставлял и более специализированный, например, спецархиватор для почты ArcMail.

Криптон. Оживляем «криптографический танк» из девяностых

Но с ним, увы, не задалось: версия под Windows не запускалась, а под DOS — не видела ни эмулятор, ни настоящую плату. Пришлось переместиться на Windows 2000, где софт ожил.

Криптон. Оживляем «криптографический танк» из девяностых

Открываем параметры и устанавливаем путь для хранения ключей.

Криптон. Оживляем «криптографический танк» из девяностых

А вот и наш софт.

Криптон. Оживляем «криптографический танк» из девяностых
Криптон. Оживляем «криптографический танк» из девяностых

Другим ПО для Windows является «Криптон-Подпись», интегрирующийся прямо в контекстное меню.

❯ Криптон для программиста

Помимо использования штатного софта была возможность разрабатывать свой. Для этого существовал Crypton DK — набор библиотек и документации для разработки. Для того, чтобы оснастить свою программу возможностью аппаратного шифрования, достаточно было установить Crypton API и подключить прилагаемые к Crypton DK DLL-ки.

Пример использования каждой из функций Crypton DK:

///////////////////////////////////////////////////////////////// // Sample: testing Crypton API functions // (c) Ancud 1998 // -------------------------------------------------------------- // The sample shows using all the Crypton API functions ///////////////////////////////////////////////////////////////// #include <windows.h> #include <stdio.h> #include <conio.h> #include "..\..\INC\CryptLib.h" CRHANDLE hCR; // Handle to a crypton service #define TestBufSize 2048 // The size of the buffers for encryption/decryption and random tests char TestBuf1[TestBufSize]; // Buffers for encryption/decryption and random tests char TestBuf2[TestBufSize]; char TestBuf3[TestBufSize]; crSYNCHRO crSync; crKEY crKey1,crKey2; // Buffers for keys crIP crIP1,crIP2; // Buffers for imitoprefixes void // Almost obvious function ;) WriteRes(BOOL res) { if (res) printf(" \tOK\n"); else printf(" \tFALSE\n"); } void // Making equal buffers SetEqualBufs(char* Buf1,char* Buf2,int Size) { char j=35; int i; for (i=0; i<Size; i++) { *(Buf1+i)=j; *(Buf2+i)=j; j++; } } void // Making different buffers SetBufs(char* Buf1,char* Buf2,int Size) { char j=32; int i; for (i=0; i<Size; i++) { *(Buf1+i)=j; *(Buf2+i)=255-j; j++; } } void main() { printf("\nTest of Crypton API functions (c) Ancud 1998\n"); if (crInitCryptonLib()) // Don't forget to call this function // before using Crypton API functions { hCR=crInitService(); // Get a handle to the hardware service if (hCR) { BOOL res; if(crTestHardware(hCR)){ printf("Using DK with Crypton Hardware!\n"); }else printf("Using DK with Crypton Emulator!\n"); // crTestHardware printf("crTestHardware\t"); WriteRes(crTestHardware(hCR)); // crGetCryptonNumber printf("crGetCryptonNumber\t%i\n",crGetCryptonNumber(hCR)); // crRandom printf("crRandom\t"); SetEqualBufs(TestBuf1,TestBuf2,TestBufSize); res=crRandom(hCR,TestBufSize,TestBuf1); res&=(memcmp(TestBuf1,TestBuf2,TestBufSize)!=0); WriteRes(res); // crControlledRandom { crCTRLRANDOM TestBuf1,TestBuf2; printf("crControlledRandom"); SetEqualBufs(TestBuf1,TestBuf2,CTRLRANDOM_LEN); res=crControlledRandom(hCR,TestBuf1); res&=(memcmp(TestBuf1,TestBuf2,CTRLRANDOM_LEN)!=0); WriteRes(res); } // crSetK1 printf("crSetK1\t\t"); crRandom(hCR,CRYPTON_KEY_LEN,crKey1); WriteRes(crSetK1(hCR,crKey1)); // crSetK2 printf("crSetK2\t\t"); crRandom(hCR,CRYPTON_KEY_LEN,crKey1); WriteRes(crSetK2(hCR,crKey1)); // crSetK1onK2 printf("crSetK1onK2\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); res=crSetK1onK2(hCR,crKey1); res&=crGetK1onK2(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crGetK1onK2 printf("crGetK1onK2\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); crSetK1onK2(hCR,crKey1); res=crGetK1onK2(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crGetK2onK1 printf("crGetK2onK1\t"); crRandom(hCR,CRYPTON_KEY_LEN,crKey1); crSetK1(hCR,crKey1); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); res=crGetK2onK1(hCR,crKey1); res&=crGetK2onK1(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crSetK2onK3 printf("crSetK2onK3\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); res=crSetK2onK3(hCR,crKey1); res&=crGetK2onK3(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crGetK2onK3 printf("crGetK2onK3\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); crSetK2onK3(hCR,crKey1); res=crGetK2onK3(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crSetK1onK3 printf("crSetK1onK3\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); res=crSetK1onK3(hCR,crKey1); res&=crGetK1onK3(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crGetK1onK3 printf("crGetK1onK3\t"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); crSetK1onK3(hCR,crKey1); res=crGetK1onK3(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)==0); WriteRes(res); // crSetRandomK1onK3 printf("crSetRandomK1onK3"); SetEqualBufs(crKey1,crKey2,CRYPTON_KEY_LEN); res=crGetK1onK3(hCR,crKey1); res&=crSetRandomK1onK3(hCR); res&=crGetK1onK3(hCR,crKey2); res&=(memcmp(crKey1,crKey2,CRYPTON_KEY_LEN)!=0); WriteRes(res); // crGetIPforDataonK1 printf("crGetIPforDataonK1"); SetBufs(TestBuf1,TestBuf2,TestBufSize); SetBufs(crIP1,crIP2,CRYPTON_IP_LEN); res=crGetIPforDataonK1(hCR,TestBufSize,TestBuf1,crIP1); res&=crGetIPforDataonK1(hCR,TestBufSize,TestBuf1,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)==0); res&=crGetIPforDataonK1(hCR,TestBufSize,TestBuf2,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)!=0); WriteRes(res); // crGetIPforK1onK2 printf("crGetIPforK1onK2"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); SetBufs(crIP1,crIP2,CRYPTON_IP_LEN); crSetK1(hCR,crKey1); res=crGetIPforK1onK2(hCR,crIP1); res&=crGetIPforK1onK2(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)==0); crSetK1(hCR,crKey2); res&=crGetIPforK1onK2(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)!=0); WriteRes(res); // crGetIPforK2onK3 printf("crGetIPforK2onK3"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); SetBufs(crIP1,crIP2,CRYPTON_IP_LEN); crSetK2(hCR,crKey1); res=crGetIPforK2onK3(hCR,crIP1); res&=crGetIPforK2onK3(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)==0); crSetK2(hCR,crKey2); res&=crGetIPforK2onK3(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)!=0); WriteRes(res); // crGetIPforK2onK1 printf("crGetIPforK2onK1"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); SetBufs(crIP1,crIP2,CRYPTON_IP_LEN); crSetK2(hCR,crKey1); res=crGetIPforK2onK1(hCR,crIP1); res&=crGetIPforK2onK1(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)==0); crSetK2(hCR,crKey2); res&=crGetIPforK2onK1(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)!=0); WriteRes(res); // crGetIPforK1onK3 printf("crGetIPforK1onK3"); SetBufs(crKey1,crKey2,CRYPTON_KEY_LEN); SetBufs(crIP1,crIP2,CRYPTON_IP_LEN); crSetK1(hCR,crKey1); res=crGetIPforK1onK3(hCR,crIP1); res&=crGetIPforK1onK3(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)==0); crSetK1(hCR,crKey2); res&=crGetIPforK1onK3(hCR,crIP2); res&=(memcmp(crIP1,crIP2,CRYPTON_IP_LEN)!=0); WriteRes(res); // crGammaCodeonK1Ex printf("crGammaCodeonK1Ex"); SetEqualBufs(TestBuf1,TestBuf2,TestBufSize); crRandom(hCR,CRYPTON_SYNCHRO_LEN,crSync); res=crGammaCodeonK1Ex(hCR,TestBufSize,crSync,TestBuf1,TestBuf2); res&=(memcmp(TestBuf1,TestBuf2,TestBufSize)!=0); SetBufs(TestBuf1,TestBuf3,TestBufSize); res&=crGammaCodeonK1Ex(hCR,TestBufSize,crSync,TestBuf1,TestBuf2); res&=crGammaCodeonK1Ex(hCR,TestBufSize,crSync,TestBuf2,TestBuf3); res&=(memcmp(TestBuf1,TestBuf3,TestBufSize)==0); WriteRes(res); // crGammaRecoveryCodeonK1Ex printf("crGammaRecoveryCodeonK1Ex"); SetEqualBufs(TestBuf1,TestBuf2,TestBufSize); crRandom(hCR,CRYPTON_SYNCHRO_LEN,crSync); res=crGammaRecoveryCodeonK1Ex(hCR,TestBufSize,crSync,TestBuf1,TestBuf2); res&=(memcmp(TestBuf1,TestBuf2,TestBufSize)!=0); SetBufs(TestBuf1,TestBuf3,TestBufSize); res&=crGammaRecoveryCodeonK1Ex(hCR,TestBufSize,crSync,TestBuf1,TestBuf2); res&=crGammaRecoveryDecodeonK1Ex(hCR,TestBufSize,crSync,TestBuf2,TestBuf3); res&=(memcmp(TestBuf1,TestBuf3,TestBufSize)==0); WriteRes(res); crDoneService(hCR); // We don't need this handle any more } else printf("Error starting the service.\n"); crDoneCryptonLib(); // We aren't going to use Crypton API any more } else printf("Error initialization of the Crypton library.\n"); printf("\nPress any key...\n"); _getch(); }

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

Криптон. Оживляем «криптографический танк» из девяностых

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

❯ Что же в итоге?

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

Забавно, что в своё время даже существовали вирусы для ПК с такими платами. На сайте ANCUD упоминалась некая программа, которая якобы ускоряла шифрование файлов, тогда как на деле «Криптон» при её запуске и вовсе не использовался, а файлы защищались куда более слабым алгоритмом.Такие дела.

❯ Ссылки

Криптон. Оживляем «криптографический танк» из девяностых

Автор текста: MaFrance351

Больше интересных статей в нашем блоге на Хабре и телеграм-канале.

Облачные сервисы Timeweb Cloud — это реферальная ссылка, которая может помочь поддержать авторские проекты.

Хочешь стать автором (или уже состоявшийся автор) и есть, чем интересным поделиться (за вознаграждение) в рамках наших блогов — пиши сюда.

3131
11
4 комментария

во, интересное в свежем

2

Когда я вижу как ты шифруешь, малыш, ты меня волнуешь

1

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

Необходимо для ускорения шифрования (создавалось это ещё в эпоху ЕС ПЭВМ), а также для большей защищённости (ключи хранились в памяти платы и не могли быть извлечены).