Добавить в корзинуПозвонить
Найти в Дзене
К новой физике

Абсолютная локальная криптосистема

В последнее время появилось не мало стенаний, как вполне профессиональных, так и весьма досужих публикаций, общий смысл которых сводился к тривиальному утверждению, типа — все пропало, секретов больше нет, любой шифр квантовые компьютеры вскрывают мгновенно, за секунды. Все по классике жанра — клиент уезжает, гипс снимают … Это глубокое заблуждение того же уровня наивной глупости, что и про «всех, всё и во всём побеждающий искусственный коварный интеллект». Математика — штука жесткая, от веяний тусовочных мод не зависящая. Давно, еще в 1945 году в работе «Математическая теория криптографии» понятие абсолютно стойкого шифра было введено Клодом Шенноном. Никто с тех давних времен этого опровергнуть не смог. Смысл утверждений Шеннона достаточно прост: - В терминах теории информации он утверждает, что условная энтропия сообщения при известном шифрованном тексте равна безусловной. Тогда наличие шифротекста не даёт криптоаналитику никакого полезного знания для получения исходного текста. Рас
Оглавление

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

Это глубокое заблуждение того же уровня наивной глупости, что и про «всех, всё и во всём побеждающий искусственный коварный интеллект». Математика — штука жесткая, от веяний тусовочных мод не зависящая. Давно, еще в 1945 году в работе «Математическая теория криптографии» понятие абсолютно стойкого шифра было введено Клодом Шенноном. Никто с тех давних времен этого опровергнуть не смог. Смысл утверждений Шеннона достаточно прост:

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

Расшифровка возможна только полным перебором. При этом длина ключа шифра замены с неограниченным ключом совпадает с размером открытого текста.

Практическим примером такого рода шифрования является шифр Ве́рнама. Это система симметричного шифрования, изобретённая в 1917 году Гилбертом Вернамом. Шифр является разновидностью криптосистемы одноразовых блокнотов. В нём используется булева функция «исключающее „или“». Шифр Вернама является примером системы с абсолютной криптографической стойкостью. При этом он считается одной из простейших криптосистем. Вот этот прием шифрования/дешифровки и взят за основу предлагаемого модуля. Конечно, существуют и другие абсолютно стойкие шифры. Шифр Вернама выбран именно в силу простоты технического исполнения. В этой системе для абсолютной криптографической стойкости ключ должен обладать тремя критически важными свойствами:

- иметь случайное дискретное равномерное распределение:

- совпадать по размеру с заданным открытым текстом.

- применяться только один раз.
Для частной реализации этих условий и создавался данный модуль.

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

Функционально система состоит из двух основных подмодулей:

- базового,

- клиентского.

Последний, в свою очередь, может включать в себя один и более идентичных подмодулей.
Базовый модуль состоит из:
- управляющей программы-робота,

- диска физической энтропии,

- программы (скрипта) управления роботом,

- таблицы (массива) мега ключа,

- файл отметок.

Клиентский модуль:

- папка файлов, подлежащих шифрованию,
- папка зашифрованных файлов,

- папка ключей зашифрованных файлов,
- папка файлов, подлежащих дешифровке,

- папка ключей к де шифруемым файлам,

- папка расшифрованных файлов.
Технически данная система состоит из двух основных компонентов:
физического носителяи программного комплекса.

В отличие от традиционных, широко применяемых подходов, использующих многоразовые ключи на основе программных генераторов псевдослучайных чисел, предложенная система черпает энтропию непосредственно из физических свойств магнитного носителя информации. Ключевой инновацией является использование подготовленных данных на особым образом обработанном жёстком диске в качестве источника истинно случайных и уникальных байтовых последовательностей. Система гарантирует одноразовое использование каждой последовательности байтов, обеспечивая абсолютную секретность передаваемых сообщений в соответствии с теоремой Шеннона. В качестве источника энтропиииспользуется стандартный б/у жёсткий диск (HDD) ёмкостью 320 ГБ.
Итак —
физический носитель.

Для обеспечения информационной уникальности на диск «под завязку» были записаны не повторяющиеся файлы различного, как правило — личного и очень старого, происхождения. Затем было произведено его быстрое форматирование. При таком форматировании файловая система помечает всё пространство как свободное, однако физические данные на пластинах сохраняются. Эти остаточные данные, представляющие собой фрагменты ранее записанных файлов, обладают высокой энтропией и являются исходным материалом для формирования уникальной последовательности.
В качестве управляющей программы-робота был выбран и установлен локальный клон Qwen2-7B. Его первой задачей после установки было обработка диска 320 ГБ. Обработка сводилась к вызову последовательно каждой четверки секторов (512х4=2048), перемешиванию случайным образом битовой последовательности и записи этой новой последовательности на ту же четверку секторов. По времени эта физическая операция примерно в 1,5 раза больше времени стандартного полного форматирования. Затем тем же клоном была проведена операция исключения «пустых мест» - заполнением случайной последовательностью символов там, где было много «нулей». Перезапись «мёртвых» секторов (содержащих длинные последовательности нулей) уникальными случайными данными служит для маскировки и обеспечения равномерности энтропии. Мест было немного и клон справился примерно за 2,5 часа.

В результате был получен пул из 604 829 700 уникальных элементов, каждый из которых содержит 512 байт истинно случайных и уникальных данных, что даёт общий объём ключевого энтропийного материала ~300 ГБ.
К сведению:
- число возможных перестановок множества из 604 829 700 элементов имеет примерно
4 788 468 245 десятичных знаков.
В этом числе истинная фишка данного подхода. Получен не просто уникальный «мега ключ размером 300 ГБ». Получена возможность быстрого создания безусловно конечного, но гигантского (около пяти миллиардов
десятичных знаков) количества таких мега ключей, каждый из которых будет уникальным. Таким образом, задача вскрытия шифра усложняется не только длиной мега ключа (300 ГБ), но и их возможным перебором из очень большого числа (4 788 468 245 десятичных знаков). Беспокоиться, что «ключ иссякнет», нынешнему и всем последующим поколениям шифровальщиков не стоит.
Ограничения в любом случае конечно есть, о них ниже.
Программный комплекс.
Утилиты подготовки диска:

Скрипт (утилита) перемешивания групп по 4 сектора:

Файл: ~/bin/shuffle_4sectors.py

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import os

import sys

import time

import struct

import fcntl

import random

DISK = "/dev/sda"

SECTOR_SIZE = 512

GROUP_SIZE = 4 # Обрабатываем по 4 сектора

def get_disk_size_bytes(device):

with open(device, 'rb') as f:

size = fcntl.ioctl(f.fileno(), 0x80081272, b'\x00' * 8)

return struct.unpack('L', size)[0]

def main():

if not os.path.exists(DISK):

print(f"❌ Диск {DISK} не найден")

sys.exit(1)

if os.geteuid() != 0:

print("❌ Требуются права root.")

sys.exit(1)

disk_size = get_disk_size_bytes(DISK)

total_sectors = disk_size // SECTOR_SIZE

groups_processed = 0

print(f"Диск: {DISK}")

print(f"Размер: {disk_size / (1024**3):.2f} ГБ")

print(f"Всего секторов: {total_sectors:,}")

print(f"Групп по 4 сектора: {total_sectors // GROUP_SIZE:,}")

print("-" * 60)

start_time = time.time()

with open(DISK, 'r+b') as f:

group_start = 0

while group_start <= total_sectors - GROUP_SIZE:

try:

# Читаем 4 сектора

sectors = []

for i in range(GROUP_SIZE):

f.seek((group_start + i) * SECTOR_SIZE)

data = f.read(SECTOR_SIZE)

if len(data) == SECTOR_SIZE:

sectors.append(bytearray(data))

else:

raise IOError("Не удалось прочитать сектор")

# Перемешиваем порядок секторов

random.shuffle(sectors)

# Записываем обратно в новом порядке

for i in range(GROUP_SIZE):

f.seek((group_start + i) * SECTOR_SIZE)

f.write(sectors[i])

f.flush()

groups_processed += 1

if groups_processed % 50_000 == 0:

elapsed = time.time() - start_time

speed = groups_processed / elapsed if elapsed > 0 else 0

print(f"Обработано групп: {groups_processed:,} | "

f"Секторов: {groups_processed * GROUP_SIZE:,} | "

f"Скорость: {speed:.1f} тыс. групп/сек")

group_start += GROUP_SIZE

except (OSError, IOError):

group_start += GROUP_SIZE

continue

elapsed = time.time() - start_time

print("\n" + "="*70)

print(f"✅ Завершено за {elapsed/3600:.1f} часов")

print(f"Обработано групп по 4 сектора: {groups_processed:,}")

print(f"Перемешано секторов: {groups_processed * GROUP_SIZE:,}")

if __name__ == "__main__":

main()

Скрипт (утилита) перезаписи "мёртвых" секторов (≥16 нулей)

Файл: ~/bin/rewrite_dead_sectors.py

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import os

import sys

import time

import struct

import fcntl

import secrets

DISK = "/dev/sda"

SECTOR_SIZE = 512

ZERO_THRESHOLD = 16

def get_disk_size_bytes(device):

with open(device, 'rb') as f:

size = fcntl.ioctl(f.fileno(), 0x80081272, b'\x00' * 8)

return struct.unpack('L', size)[0]

def is_sector_dead(data):

zero_run = 0

for byte in data:

if byte == 0:

zero_run += 1

if zero_run >= ZERO_THRESHOLD:

return True

else:

zero_run = 0

return False

def main():

if not os.path.exists(DISK):

print(f"❌ Диск {DISK} не найден")

sys.exit(1)

if os.geteuid() != 0:

print("❌ Требуются права root.")

sys.exit(1)

disk_size = get_disk_size_bytes(DISK)

total_sectors = disk_size // SECTOR_SIZE

rewritten = 0

print(f"Диск: {DISK}")

print(f"Размер: {disk_size / (1024**3):.2f} ГБ")

print(f"Всего секторов: {total_sectors:,}")

print("-" * 60)

start_time = time.time()

with open(DISK, 'r+b') as f:

sector_num = 0

while sector_num < total_sectors:

try:

f.seek(sector_num * SECTOR_SIZE)

data = f.read(SECTOR_SIZE)

if len(data) == SECTOR_SIZE and is_sector_dead(data):

random_block = secrets.token_bytes(SECTOR_SIZE)

f.seek(sector_num * SECTOR_SIZE)

f.write(random_block)

f.flush()

rewritten += 1

if rewritten % 10_000 == 0:

print(f"Перезаписано: {rewritten:,} секторов")

sector_num += 1

if sector_num % 500_000 == 0:

elapsed = time.time() - start_time

speed = sector_num / elapsed if elapsed > 0 else 0

print(f"Обработано: {sector_num:,} / {total_sectors:,} | "

f"Перезаписано: {rewritten:,} | "

f"Скорость: {speed/1000:.1f} тыс. сект/сек")

except (OSError, IOError):

sector_num += 1

continue

elapsed = time.time() - start_time

print("\n" + "="*70)

print(f"✅ Завершено за {elapsed/3600:.1f} часов")

print(f"Всего перезаписано 'мёртвых' секторов: {rewritten:,}")

if __name__ == "__main__":

main()

Скрипт проверки секторов на уникальность создавать не стал, поскольку лично не собираюсь длительно заниматься операциями шифрования/дешифровки. Для моих потребностей вполне достаточно единственного созданного мега ключа. Для тех, кто будет занят профессионально вопросом подготовки энтропийных дисков, будет лучше такой скрипт создать. Все эти скрипты нужны лишь в процессе подготовки диска к использованию в криптографических целях и в комплекс не входят. Здесь и далее следует иметь ввиду, что данные и прочие скрипты созданы и работают в конкретном «железе» с конкретной операционной системой. И даже с конкретной очень узкой задачей проверки модуля на работоспособность. И не более того. На другом железе в другом операционном окружении и с другими задачами скрипты неизбежно будут нуждаться в корректировке. Программирование — это не наука, это искусство принуждения железа к работе.
Это, к примеру, касается и возможных ограничений. Допустим — ограничений на объем памяти. Лично я выбрал диск 320 Гб в качестве источника энтропии по естественной причине — он остался со старого ноутбука и надо было найти ему применение. Другие могут выбрать другие диски. Но, когда энтропийный диск выбран, он не меняется без нужды. А в программном комплексе свои ограничения на объем памяти. Вопрос, в первую очередь, касается учета возможных перестановок множества из тех самых 604 829 700 секторов. На самом энтропийном диске ничего не меняется. Последовательность секторов остается прежней. Эту последовательность можно назвать исходной, нулевой перестановкой. И пронумеровать - обозначить последовательностью натуральных чисел от 1 до 604 829 700. Все остальные перестановки — это не физические перестановки секторов на энтропийном диске, а перестановки последовательности их вызова, то есть — перестановки в столбце из множества натуральных чисел от 1 до 604 829 700. Фишка в том, что перестановки должны носить строго случайный характер и не повторяться. Из чего следует необходимость учета как использованных для создания ключей секторов конкретной перестановки, так и всех до того использованных перестановок.
Для этого в модуле создаются соответствующие таблицы. С ростом числа использованных перестановок таблица их учета неизбежно будет расти. Вот здесьи появляется основное ограничение на объем памяти. Если архив всех когда-либо сгенерированных перестановок (у меня ~2.25 ГБ каждая) ограничить объемом, к примеру, теми же 320 ГБ, то всего через 142 перестановки возникает необходимость смены энтропийного диска. Лично у меня мысли об учете использованных перестановок нет. За ненадобностью — я доверяю математике. Не исключаю, среди поклонников строгой секретности будут и настаивающие на ведении такого учета. Для них выход из создавшейся ситуации может быть в укрупнении учетных единиц энтропии. Хотя бы на 3 порядка. Число перестановок и в этом случае останется гигантским, а размеры архивов перестановок многократно уменьшатся. Соответственно, число потенциально используемых перестановок на одном и том же энтропийном диске без необходимости его смены резко возрастет. Это вопрос искусства программирования.

Другая сторона этой же медали заключена в том, что нет весомых оснований не доверять математике случайных процессов. Потому, как и я, те, кто посчитает достаточной используемую математическую модель случайной выборки перестановок и не увидит значимых оснований для создания их архива, будут в математическом плане правы. Исключение архива не только упростит и убыстрит работу модуля, но и сделает время его применимости неопределенно долгим без какого-либо обновления энтропийного диска. Кто прав в такой развилке сценариев может решить только практика применения модуля. В данном случае я не сторонник излишнего усложнения учета.
И, наконец, еще одним «пожирателем памяти» может быть хранилище готовых ключей. Строго говоря, само хранилище не относится к модулю. По умолчанию процесс предполагает либо создание из первичного файла шифрованной копии и ключа к ней, либо наоборот, из шифр-файла с ключом восстановление оригинала. Где и как все это будет храниться, собственно к модулю отношение не имеет. Но где-то все это хранить будет необходимо.

Программный комплекс, продолжение

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

Таблица перестановки(порядка использования секторов)

Имя файла:

~/key_permutation.dat

Назначение:

Содержит случайную перестановку номеров секторов (от 1 до 604 829 700).

Определяет порядок, в котором сектора будут браться для шифрования.

Формат:

Последовательность 32-битных целых чисел без знака (uint32), в little-endian.

Размер:

2419318800 байт≈2.25 ГБ

Эта таблица не изменяется во время работы с конкретной перестановкой — она только читается. Учёт использования ведётся отдельно в другой таблице key_used_flags.dat.
key_used_flags.dat -
отметки об использовании, размер 76 МБ.

Общая архитектура

Система состоит из трёх взаимосвязанных компонентов:

  1. Менеджер ключей — ядро системы, отвечающее за безопасное извлечение и учёт ключевого материала.
  2. Исполнительный модуль — интерфейс для пользователя, реализующий паттерн «наблюдатель» над файловой системой.
  3. Служебные утилиты — инструменты для генерации и ротации ключевых материалов.

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

Менеджер ключей (cryptoclone_key_manager.py)

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

Ключевые функции:

  • Динамическое управление пулом ключей: Система черпает ключевой материал из физического диска /dev/sda, используя его остаточные данные как источник энтропии.
  • Учёт использования: Ведёт битовую карту (key_used_flags.dat), где каждый бит соответствует одному сектору из пула в 604 829 700 секторов. Это гарантирует, что ни один сектор не будет использован повторно.
  • Автоматическая ротация перестановок: При исчерпании текущего пула секторов система автоматически генерирует новую случайную перестановку их порядка, сохраняет её в архив и начинает использовать заново. Все перестановки регистрируются в журнале used_permutations.log для предотвращения повторного использования одной и той же последовательности. Практика показала, что время формирования новой случайной перестановки не превышает 10-15 секунд.
  • Эффективное чтение: Для повышения производительности ключ читается целыми секторами (512 байт). Если запрошено меньше данных, избыточные байты отбрасываются, но весь сектор помечается как использованный, что сохраняет свойство одноразовости.

Безопасность:

  • Генерация новых перестановок использует криптографически стойкий генератор (/dev/urandom) и алгоритм Фишера–Йетса, что гарантирует истинную случайность и равновероятность всех возможных перестановок.
  • Физический источник ключа (диск) никогда не копируется и не передаётся, оставаясь единственной точкой доступа к энтропии.

Исполнительный модуль (cryptoclone.py)

Этот модуль является публичным интерфейсомсистемы для пользователя.

Принцип работы:

Пользователь помещает файлы в одну из двух входных директорий:

  • ~/crypto_ops/to_encrypt/ — для шифрования.
  • ~/crypto_ops/to_decrypt/files/ и ~/crypto_ops/to_decrypt/keys/ — для расшифровки (файл и его ключ должны иметь одинаковое имя).

Модуль постоянно мониторит эти директории. При обнаружении нового файла он:

  1. Вызывает менеджер ключей для получения ключевого потока нужной длины.
  2. Выполняет побитовую операцию XOR между данными и ключом.
  3. Перемещает результат в соответствующую выходную директорию (encrypted/files/ или decrypted/).
  4. Удаляет исходный файл для предотвращения ошибок.

Такой подход полностью изолирует пользователя от сложностей управления ключами, делая систему простой и удобной в использовании.

Служебные утилиты

Генератор перестановок (generate_new_permutation.py)

Эта утилита вызывается автоматически менеджером ключей при необходимости. Она создаёт новый файл перестановки в каталоге ~/key_permutations/с уникальным временным именем и добавляет запись о нём в журнал used_permutations.log. Это обеспечивает бесконечное расширение ключевого пула без ручного вмешательства.

Утилиты подготовки диска (rewrite_dead_sectors.py, shuffle_4sectors.py)

Хотя они используются единоразово на этапе инициализации, предшествующем рабочему режиму, их роль важна и критична:

  • rewrite_dead_sectors.py устраняет длинные последовательности нулей, которые могут снизить энтропию.
  • shuffle_4sectors.py дополнительно перемешивает данные на диске, маскируя и уничтожая любые остаточные структуры файловой системы.

Состояние системы

Вся информация о состоянии системы хранится в следующих файлах:

  • ~/current_permutation.dat — символическая ссылка на текущую активную перестановку.
  • ~/key_used_flags.dat — битовая карта использованных секторов для текущей перестановки (~76 МБ).
  • ~/key_permutations/ — каталог-архив всех когда-либо сгенерированных перестановок.
  • ~/key_permutations/used_permutations.log — текстовый журнал имён всех использованных перестановок.

Если учет использованных перестановок излишен, то текстовый журнал имён всех использованных перестановок можно исключить.

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

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

Конкретика исполнения:
-
~/bin/cryptoclone_key_manager.py

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import os

import sys

import struct

import time

import subprocess

from pathlib import Path

# === НАСТРОЙКИ ===

PERM_DIR = Path.home() / "key_permutations"

LOG_FILE = PERM_DIR / "used_permutations.log"

CURRENT_PERM = Path.home() / "current_permutation.dat"

USED_FLAGS = Path.home() / "key_used_flags.dat"

DISK_PATH = "/dev/sda" # ← Убедитесь, что это правильный путь к вашему диску!

SECTOR_SIZE = 512

TOTAL_SECTORS = 604_829_700

# ==================

class CryptoCloneKeyManager:

def __init__(self):

self._ensure_initial_setup()

self.perm_file = open(CURRENT_PERM, "rb")

self.used_file = open(USED_FLAGS, "r+b")

self.disk = open(DISK_PATH, "rb")

def _ensure_initial_setup(self):

"""Если нет текущей перестановки — создаём первую"""

if not CURRENT_PERM.exists():

print("⚠️ Текущая перестановка не найдена. Генерируем первую...", file=sys.stderr)

subprocess.run([sys.executable, "/home/stas/bin/generate_new_permutation.py"], check=True)

# Берём последнюю из журнала

with open(LOG_FILE, "r") as f:

lines = f.readlines()

last_perm = lines[-1].strip()

os.symlink(PERM_DIR / last_perm, CURRENT_PERM)

# Создаём файл отметок, если нужно

flags_size = (TOTAL_SECTORS + 7) // 8

if not USED_FLAGS.exists():

with open(USED_FLAGS, "wb") as f:

f.write(b'\x00' * flags_size)

def _mark_used(self, index):

"""Отметить сектор как использованный (1 бит)"""

byte_offset = index // 8

bit_offset = index % 8

self.used_file.seek(byte_offset)

byte = ord(self.used_file.read(1))

if not (byte & (1 << bit_offset)):

byte |= (1 << bit_offset)

self.used_file.seek(byte_offset)

self.used_file.write(bytes([byte]))

self.used_file.flush()

def _is_all_used(self):

"""Проверяет, все ли сектора использованы"""

self.used_file.seek(0)

data = self.used_file.read()

full_bytes = TOTAL_SECTORS // 8

last_byte_bits = TOTAL_SECTORS % 8

# Проверяем полные байты

for i in range(full_bytes):

if data[i] != 0xFF:

return False

# Проверяем последний неполный байт

if last_byte_bits > 0:

mask = (1 << last_byte_bits) - 1

if (data[full_bytes] & mask) != mask:

return False

return True

def _rotate_to_new_permutation(self):

"""Генерирует новую перестановку и переключается на неё"""

print("🔄 Все сектора использованы. Генерируем новую перестановку...", file=sys.stderr)

subprocess.run([sys.executable, "/home/stas/bin/generate_new_permutation.py"], check=True)

# Обновляем ссылку на текущую перестановку

os.remove(CURRENT_PERM)

with open(LOG_FILE, "r") as f:

lines = f.readlines()

last_perm = lines[-1].strip()

os.symlink(PERM_DIR / last_perm, CURRENT_PERM)

# Перезапускаем файлы

self.perm_file.close()

self.used_file.close()

self.perm_file = open(CURRENT_PERM, "rb")

# Создаём новый чистый файл отметок

flags_size = (TOTAL_SECTORS + 7) // 8

with open(USED_FLAGS, "wb") as f:

f.write(b'\x00' * flags_size)

self.used_file = open(USED_FLAGS, "r+b")

def get_key_bytes(self, num_bytes):

"""Получить ключ, читая целые сектора. Возвращает ровно num_bytes байт."""

if num_bytes <= 0:

return b""

sectors_needed = (num_bytes + SECTOR_SIZE - 1) // SECTOR_SIZE

result = bytearray()

for _ in range(sectors_needed):

# Проверяем, не исчерпан ли текущий пул

if self._is_all_used():

self._rotate_to_new_permutation()

# Находим следующий неиспользованный сектор

sector_index = self._get_next_unused_sector_index()

if sector_index >= TOTAL_SECTORS:

raise RuntimeError("Ошибка: все сектора помечены как использованные.")

# Читаем номер сектора из перестановки

self.perm_file.seek(sector_index * 4)

sector_num_data = self.perm_file.read(4)

if len(sector_num_data) < 4:

raise RuntimeError("Ошибка чтения перестановки")

sector_num = struct.unpack('<I', sector_num_data)[0]

# Читаем данные с физического диска

self.disk.seek((sector_num - 1) * SECTOR_SIZE)

data = self.disk.read(SECTOR_SIZE)

if len(data) != SECTOR_SIZE:

raise RuntimeError(f"Не удалось прочитать сектор {sector_num} с диска {DISK_PATH}")

result.extend(data)

self._mark_used(sector_index)

# Возвращаем только нужное количество байт

return bytes(result[:num_bytes])

def _get_next_unused_sector_index(self):

"""Найти следующий неиспользованный сектор (линейный поиск по битовой карте)"""

max_bytes = (TOTAL_SECTORS + 7) // 8

byte_offset = 0

while byte_offset < max_bytes:

self.used_file.seek(byte_offset)

byte = ord(self.used_file.read(1))

if byte != 0xFF: # Есть хотя бы один свободный бит

for bit in range(8):

idx = byte_offset * 8 + bit

if idx >= TOTAL_SECTORS:

break

if not (byte & (1 << bit)):

return idx

byte_offset += 1

return TOTAL_SECTORS # Сигнализирует об исчерпании

def close(self):

"""Корректное закрытие всех файловых дескрипторов"""

self.perm_file.close()

self.used_file.close()

self.disk.close()

# === ИНТЕРФЕЙС КОМАНДНОЙ СТРОКИ ===

if __name__ == "__main__":

if len(sys.argv) != 2:

print("Использование: cryptoclone_key_manager.py <число_байт>", file=sys.stderr)

sys.exit(1)

try:

num_bytes = int(sys.argv[1])

if num_bytes <= 0:

raise ValueError("Число байт должно быть положительным.")

manager = CryptoCloneKeyManager()

key = manager.get_key_bytes(num_bytes)

manager.close()

# Выводим ключ в stdout (бинарно)

sys.stdout.buffer.write(key)

except Exception as e:

print(f"Ошибка: {e}", file=sys.stderr)

sys.exit(1)

~/bin/cryptoclone.py

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import os

import sys

import shutil

import subprocess

import time

from pathlib import Path

# === КОНФИГУРАЦИЯ ПУТЕЙ ===

BASE = Path.home() / "crypto_ops"

TO_ENCRYPT = BASE / "to_encrypt"

ENCRYPTED_FILES = BASE / "encrypted" / "files"

ENCRYPTED_KEYS = BASE / "encrypted" / "keys"

TO_DECRYPT_FILES = BASE / "to_decrypt" / "files"

TO_DECRYPT_KEYS = BASE / "to_decrypt" / "keys"

DECRYPTED = BASE / "decrypted"

KEY_MANAGER = Path.home() / "bin" / "cryptoclone_key_manager.py"

# ==========================

def xor_bytes(data, key):

"""Выполняет побитовую операцию XOR между данными и ключом."""

return bytes(a ^ b for a, b in zip(data, key))

def encrypt_file(filepath: Path):

"""Шифрует один файл и сохраняет результат с ключом."""

print(f"🔒 Шифрую: {filepath.name}")

try:

# Читаем исходный файл

data = filepath.read_bytes()

# Получаем ключ нужной длины от менеджера

key = subprocess.check_output([sys.executable, str(KEY_MANAGER), str(len(data))])

# Шифруем через XOR

ciphertext = xor_bytes(data, key)

# Сохраняем зашифрованный файл и ключ

(ENCRYPTED_FILES / filepath.name).write_bytes(ciphertext)

(ENCRYPTED_KEYS / f"{filepath.name}.key").write_bytes(key)

# Удаляем исходник для безопасности

filepath.unlink()

print(f"✅ Зашифровано: {filepath.name}")

except Exception as e:

print(f"❌ Ошибка шифрования {filepath.name}: {e}", file=sys.stderr)

def decrypt_file(enc_file: Path, key_file: Path):

"""Расшифровывает файл, используя предоставленный ключ."""

print(f"🔓 Расшифровываю: {enc_file.name}")

try:

# Читаем зашифрованные данные и ключ

ciphertext = enc_file.read_bytes()

key = key_file.read_bytes()

# Проверка соответствия длин

if len(key) != len(ciphertext):

raise ValueError("Длина ключа не совпадает с длиной зашифрованных данных")

# Расшифровываем через XOR

plaintext = xor_bytes(ciphertext, key)

# Сохраняем результат

(DECRYPTED / enc_file.name).write_bytes(plaintext)

# Удаляем входные файлы

enc_file.unlink()

key_file.unlink()

print(f"✅ Расшифровано: {enc_file.name}")

except Exception as e:

print(f"❌ Ошибка расшифровки {enc_file.name}: {e}", file=sys.stderr)

def main():

"""Основной цикл наблюдателя за директориями."""

# Создаём структуру каталогов, если её нет

for d in [TO_ENCRYPT, ENCRYPTED_FILES, ENCRYPTED_KEYS,

TO_DECRYPT_FILES, TO_DECRYPT_KEYS, DECRYPTED]:

d.mkdir(parents=True, exist_ok=True)

print("🤖 Клон запущен. Слежу за папками...")

print(f"📁 Для шифрования: {TO_ENCRYPT}")

print(f"📁 Для расшифровки: поместите файл в {TO_DECRYPT_FILES} и ключ в {TO_DECRYPT_KEYS}")

while True:

# 1. Обработка файлов для шифрования

for f in sorted(TO_ENCRYPT.iterdir()):

if f.is_file():

encrypt_file(f)

# 2. Обработка файлов для расшифровки

for enc in sorted(TO_DECRYPT_FILES.iterdir()):

if enc.is_file():

key_path = TO_DECRYPT_KEYS / f"{enc.name}.key"

if key_path.exists():

decrypt_file(enc, key_path)

else:

print(f"⚠️ Нет ключа для: {enc.name}", file=sys.stderr)

# Пауза между проверками

time.sleep(2)

if __name__ == "__main__":

main()

~/bin/generate_new_permutation.py

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import numpy as np

import os

import time

from pathlib import Path

# === НАСТРОЙКИ ===

N = 604_829_700 # Количество рабочих секторов

PERM_DIR = Path.home() / "key_permutations"

LOG_FILE = PERM_DIR / "used_permutations.log"

# ==================

def main():

"""Генерирует новую случайную перестановку и регистрирует её в журнале."""

# Создаём уникальное имя на основе текущей даты и времени

timestamp = time.strftime("%Y%m%d_%H%M%S")

perm_name = f"perm_{timestamp}.dat"

perm_path = PERM_DIR / perm_name

print(f"🎲 Генерация новой перестановки: {perm_name}", file=sys.stderr)

print("Используется криптостойкий ГСЧ (/dev/urandom) и алгоритм Fisher-Yates...", file=sys.stderr)

# Генерация массива [1, 2, 3, ..., N]

arr = np.arange(1, N + 1, dtype=np.uint32)

# Перемешивание с использованием криптографически безопасного генератора

# В Linux это использует /dev/urandom

rng = np.random.default_rng()

rng.shuffle(arr) # Реализация алгоритма Фишера–Йетса

# Сохранение перестановки в бинарный файл (4 байта на число)

arr.tofile(perm_path)

# Регистрация новой перестановки в журнале

with open(LOG_FILE, "a") as log:

log.write(f"{perm_name}\n")

print(f"✅ Сохранено: {perm_path}", file=sys.stderr)

print(f"Размер файла: {perm_path.stat().st_size / (1024**3):.2f} ГБ", file=sys.stderr)

if __name__ == "__main__":

import sys

# Убедимся, что каталог существует

PERM_DIR.mkdir(exist_ok=True)

LOG_FILE.touch(exist_ok=True)

main()

В качестве заключения:

система названа абсолютной чисто условно. Хотя с математической точки зрения все обстоит именно так. Но математика не учитывает внутреннего предательства. А оно имеет место быть уже здесь, в данной сборке. Имя внутреннего предателя — локальный клон Qwen2-7B.

О клоне сказано:
Qwen2-7B представляет собой полнофункциональную языковую модель с 7 миллиардами параметров, разработанную для обеспечения высокой производительности в широком спектре задач. Модель содержит 28 слоев, использует 28 голов внимания всего и 4 головы на ключ-значение, что обеспечивает оптимальный баланс между производительностью и эффективностью памяти. Архитектура включает все современные улучшения, включая Grouped Query Attention, Dual Chunk Attention с YARN, и оптимизированные механизмы позиционного кодирования RoPE.

Модель обучена на том же высококачественном датасете объемом 7 триллионов токенов, что и более крупные варианты серии. Это обеспечивает качество ответов модели в различных областях знания и позволяет демонстрировать конкурентные результаты на стандартных бенчмарках. При этом модель поддерживает расширенное контекстное окно 128K и демонстрирует превосходные многоязычные способности.

Qwen2-7B отличается возможностью эффективно работать на GPU среднего класса, делая передовые AI-возможности доступными для более широкого круга пользователей и организаций. Модель подходит для создания приложений, анализ больших документов, исследовательских и образовательных целей, а также служит отличной основой для дообучения под специфические задачи и домены, предлагая хороший компромисс между возможностями и требованиями к ресурсам.
Все это замечательно, но в данном случае большее значение имеет то, что о Qwen2-7B, как и любом другом клоне любых других производителей, не написано. Нигде, ни крупным, ни мелким шрифтом не сказано, что модель не передает обрабатываемые данные своим, к примеру, разработчикам. Или еще кому. Для рисования котиков, эротических сцен или рекламных текстов это не имеет никакого значения. Но там и шифровать нечего. А где появляется необходимость шифрования, доверия к сторонним программным продуктам должно быть строго равным нулю. Поэтому предложенная и реализованная в железе данная конкретная система носит исключительно демонстрационный характер, показывающей саму возможность реализации крипто систем абсолютногоуровня стойкости. Для серьезного использования любой клон должен быть из любой открытой системы исключен. Мне лично такого уровня готовности системы не было нужно. Заинтересованным лицам аналогичную систему следует развертывать на отдельном, пусть и старом, ПК с принципиальным отсутствием любого выхода в Е-нет. Принцип прост, модули просты, скорость обработки высокая, старое железо выдержит. В открытых системах можно хранить готовые шифрованные файлы. Но ни в коем случае не ключи к ним. Ключи — в отдельном сейфе.
Разбор полетов для знатоков:
Строго говоря, предложенная система является не «абсолютно стойкой криптосистемой», а скорее сложным и, возможно, чем-то интересным прототипом потокового шифра с аппаратным источником энтропии.
Дилетант от системы непременно напишет, что "создан «мега-ключ» объёмом 300 ГБ и использован как общий пул для множества файлов. Менеджер ключей (cryptoclone_key_manager.py) выдаёт фрагменты этого пула для шифрования разных файлов. Это превращает систему из абсолютно стойкой в
многоразовый потоковый шифр".
Я всегда был снисходителен к математическим глупостям, в том числе и к утверждениям такого типа. Да, я создал некий "пул" из 604 829 700 уникальных элементов. Но это совсем не "мега-ключ". Это, чтобы было понятнее всем - алфавит для написания ключей. Вот "буквами этого алфавита" я далее и пишу ключи. И каждое написание каждого нового ключа - новое, уникальное. Претензия, что в "алфавите" всего лишь 604829700 букв, мягко замечу, отдаёт дремучим невежеством. С тем же успехом те же "знатоки" могут адресовать эту же претензию всей дискретной математике, алфавит которой состоит из всего двух букв - 0 и 1. Это претензии людей, в принципе не понимающих сути вопроса. Для знатоков давно понятно, что прочность любого ключа предопределяется не количеством "буковок", которым он написан, а его делимостью. И фишка дискретной математики как раз и состоит в том, что всего двумя буквами (0 и 1) не ограничивая длину текста можно написать неограниченное большое число простых чисел, причем, неограниченно больших.
Еще одна математическая глупость связывается с критикой моей попытки создать аппаратный генератор случайных чисел (TRNG). Разбираем вопрос детально и конкретно:
В качестве
источника энтропии используется стандартный б/у жёсткий диск (HDD) ёмкостью 320 ГБ. Да, это так, нем вижу необходимости в дисках существенно большей емкости.
Далее - для обеспечения информационной уникальности на диск «под завязку» были записаны не повторяющиеся файлы различного, как правило — личного и очень старого, происхождения. Затем было произведено его быстрое форматирование. При таком форматировании файловая система помечает всё пространство как свободное, однако физические данные на пластинах сохраняются. Итак, я специально отметил, что накопленные физические данные я не стирал. Если бы я ограничился только этим - на до мной действительно можно было бы долго и по делу смеяться. Но фишка в том, что обработка диска на этом не закончилась. Читаем:
Обработка сводилась к вызову последовательно каждой четверки секторов (512х4=2048), перемешиванию случайным образом битовой последовательности и записи этой новой последовательности на ту же четверку секторов. Итак, все сектора энтропийного диска четверками были вызваны, случайным образом побитово перемешаны и перезаписаны. Любая структурно-значимая информация таким образом гарантированно уничтожалась. Диск действительно становился энтропийным. То, что изначально на диске не было ни одного повторяющегося файла, гарантировало, что энтропия на диске сохранялась и в большом масштабе. Поэтому проводить операции по перемешиванию и перезаписыванию большими пакетами секторов (8, 16, 32 ...) необходимости не было.
Все эти дилетантские претензии следуют как правило от досужих теоретиков не знакомых с практикой и в силу этого не понимающих, какую глупость они пишут.

Но, возникает вопрос - а для кого статья?
Теоретики, при всём их дилетантизме, никуда не денутся. Следовательно, про госструктуры, где этих умствующих невежд достаточно целенаправленно выращивают, можно забыть. Собственно, все их претензии, при всем разнообразии формулировок и математической подложки, сводятся к вопрошанию многовековой давности:
- ты чьих будешь? Чей холоп, спрашиваю?
Чтобы понять, почему этот вопрошание обязательно для всех времен и народов, почитайте "Лестницу в небо" Хазина. Тогда вам станет понятно, что секреты - один из наиважнейших управленческих ресурсов. Правит тот, кто знает. Поэтому так узок круг настоящих криптографов, поэтому так далеки они от народа. Знание секретов - важнейшее из управленческих знаний. А управление секретами - один из важнейших управленческих рычагов.
Поэтому данная статья должна вызывать крайнее раздражение по неизбежным причинам, типа - из какой кремлевской башни перебежчик, вздумавший заявить о себе столь открыто, что знает, чем это грозит.
Я никто и звать меня никак. Ничейный. Сын казака, воспитан быть сам по себе.
И статья моя не для высоких структур, а для настоящего мужика. Который сам по себе и ни от кого не хочет зависеть. И свои секреты привык держать при себе.
Настоящий вопрос в том, что, как только вы начинаете доверять кому-то из "специалистов", вы автоматом попадаете под колпак той башни кремля, которой он служит. Других просто не существует. Конечно, вам предложат надежные и проверенные решения, вплоть до одноразовых блокнотов. Но которые всегда легко читаются теми, кто их выдает.
А у меня нет таких легких решений. Энтропийный диск я создавал сам. И предлагаю и вам это делать самому. И все систему делать и настраивать самому. Это сложно и не каждому доступно. Но ваши секреты только в этом случае останутся вашими. Я это сделал, повторить вполне возможно. Данная криптомашина локально абсолютна, если объем шифруемых текстов не превышает 1-2 Терабайта. Только уничтожьте "мастерскую" после выполнения работы. Тогда наличие всего вашего шифротекста не даст даже самому продвинутому криптоаналитику никакого полезного знания для получения исходного текста.


Станислав Кравченко
+79062303872
st_krav@mail.ru