Задать вопрос
  • Есть идея. Есть прехарденинг на гитхаб. Мне нужна оценка, обсуждение. С чего начать? Куда написать?

    CityCat4
    @CityCat4
    Жил да был черный кот за углом...
    Я человек ленивый, я попросил гугл (Gemini) проанализировать указанную репу.

    Вот ответ гугла:
    "Судя по описанию, изобрел классический велосипед с квадратными колесами. Его идея «двери с рисунком» — это обычный Challenge-Response протокол (запрос-ответ) на базе графического ключа, причем сильно уязвимый.Судя по его репозиторию, «прототип» написан на FastAPI и Redis, а логику ему генерировал ChatGPT. То есть человек без профильного образования в криптографии просто завернул старую концепцию в обертку современного веб-фреймворка.

    Его «уникальная» концепция — это S/KEY (алгоритм ОPIE) и одноразовые пароли (OTP), разработанные Беллом Лампортом еще в 1981 году, смешанные с концепцией графического пароля (Graphical Passwords / Pattern-based authentication) из начала 2000-х.
    Как это работает у него: Сервер дает картинку (grid_size, steps), пользователь по «секретному правилу» в голове строит маршрут (response) и отправляет его обратно. Сервер проверяет и удаляет этот challenge.
    В чем «новизна»? Ни в чем. Протоколы Challenge-Response используются в каждом первом токене аутентификации (например, в банковских приложениях или Blizzard Authenticator), только там вместо рисунка — время (TOTP) или счетчик (HOTP)."

    Гугл порекомендовал задать несколько вопросов :)

    Вопрос А: «Как ты защищаешься от атак по сторонним каналам (Side-Channel) и плечевого серфинга?
    »Если пользователь сидит в кафе, в метро или записывает экран, а камера над его плечом снимает, как он «молча смотрит на рисунок» и вводит ключ на экране — алгоритм полностью скомпрометирован. Хакеру даже не нужно брутфорсить. Он просто запишет видео ввода. В этом главная беда всех графических ключей, из-за чего от них отказываются в пользу биометрии.

    Вопрос Б: «Что происходит при атаке Man-in-the-Middle (Человек посередине)?
    »Он пишет: «Ты кидаешь ключ хакерам... Ключ больше не подходит».А если хакер перехватил трафик в момент отправки? Настоящая криптография (например, SRP — Secure Remote Password protocol) защищает от перехвата самого ответа в процессе. Если в системе хакер встанет между пользователем и сервером (MitM), он просто перехватит response до того, как тот долетит до сервера, подменит пакет и зайдет под видом пользователя, а пользователю вернет ошибку тайм-аута.

    Вопрос В: «Каков размер энтропии твоего правила?
    »Он заявляет про «60 триллионов дверей». Но человек — существо ленивое.Спросите его: если сетка (grid_size) имеет размер, например, 5х5 или 8х8, какова длина пути (steps)? Люди физически не способны запоминать сложные алгоритмы генерации путей в уме для каждой новой картинки. Они будут использовать простые правила: «проведи линию от верхнего левого котика к правому нижнему». Энтропия (хаотичность) человеческого выбора ничтожно мала. Компьютер подберет это «правило» по словарю за секунды.

    И последнее (это тоже текст гугла, но я в кои-то веки с ним согласен):
    То, что ChatGPT написал рабочий код на Python с интеграционными тестами и Docker-контуром, говорит лишь о том, что ChatGPT умеет настраивать Redis и FastAPI. Нейросеть не проверяла математическую стойкость алгоритма. ChatGPT просто реализовал логику: «прими данные — сверь с базой — удали из базы».

    Криптографическая стойкость кода от ChatGPT равна нулю, потому что языковые модели не умеют симулировать криптоанализ.
    Ответ написан
    2 комментария
  • Есть идея. Есть прехарденинг на гитхаб. Мне нужна оценка, обсуждение. С чего начать? Куда написать?

    Daemon23RUS
    @Daemon23RUS
    Есть 60 трл дверей и им соответствующих ключей. А правило изготовления - одно. На всю жизнь хватит.

    А есть U3S23H с производительностью 1160 ТH/s, он переберет Ваши "двери" за 0,05 секунды. А Вы про всю жизнь пишите. (Опустим алгоритмы, речь про порядки чисел)
    Уверены, что выбрали верную область для получения опыта ? Ведь все о чем Вы пишите - криптография. А для ее понимания нужно как минимум академическое образование (магистратура, аспирантура по криптографии, компьютерной безопасности и прикладной математике). На GPT не выехать (можно только заехать, и то в кукурузу)
    Ваша идея напоминает challenge-response аутентификацию, где по публичному "рисунку" и секретному правилу генерируется одноразовый ключ. Это отличный подход! Но безопасность зависит не только от количества "рисунков", а от сложности восстановления секретного правила по нескольким парам "рисунок - ключ", Размера секрета, Устойчивости правила к анализу (например, по 2-3 наблюдениям).
    К сожалению, самодельные криптографические алгоритмы почти всегда оказываются уязвимыми, даже если кажутся сложными. Напомнило "закон Шнейера".

    P.S. Подведу итог 2х дневного обсуждения:
    В частности устойчивость правила к анализу, выяснилось что достаточно 2х наблюдений. Я взял пример из комментария Егор Филимонов исключил пароль, оставил только матрицу и ответ
    исходный комментарий
    Вот: Я пользователь. Я выбрал пароль A1+A1; A1*A1; A1-A2(abs); A1*A2 (а мог бы меньше или больше действий и ячейки самые разные) и сохранил его. Начал работу. Получил вызов:
    1234

    A 0123
    B 4567
    C 8901
    D 2345

    В уме я вычислил: 0+0=0; 0*0=0; 0-1=1; 0*1=0
    И в поле ввода ввел полученный ключ: 0010 И получил доступ.

    На следующий день прихожу, начинаю работать и получаю новый вызов:
    1234

    A 9876
    B 5432
    C 1098
    D 7654

    решаю: 9+9=18; 9*9=81; 9-8=1; 9*8=72
    В окне ключа ввожу: 1881172 И получаю доступ.
    Do you understand now?

    И задал школьникам задачку на комбинаторику получил
    ответ
    Детали по разбиениям:0010
       [0, 0, 10] → 236,992 комбинаций
       [0, 0, 1, 0] → 48,278,656 комбинаций
    
    Детали по разбиениям:1881172
       [18, 8, 11, 72] → 82,944 комбинаций
       [18, 81, 1, 72] → 20,352 комбинаций
       [18, 81, 17, 2] → 18,816 комбинаций
       [1, 8, 8, 11, 72] → 13,188,096 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 81, 1, 72] → 3,235,968 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 81, 17, 2] → 2,991,744 комбинаций → исключено, за пределами 1й итерации
       [18, 8, 1, 1, 72] → 9,707,904 комбинаций → исключено, за пределами 1й итерации
       [18, 8, 1, 17, 2] → 8,975,232 комбинаций → исключено, за пределами 1й итерации
       [18, 8, 11, 7, 2] → 16,257,024 комбинаций → исключено, за пределами 1й итерации
       [18, 81, 1, 7, 2] → 3,988,992 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 8, 1, 1, 72] → 1,543,556,736 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 8, 1, 17, 2] → 1,427,061,888 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 8, 11, 7, 2] → 2,584,866,816 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 81, 1, 7, 2] → 634,249,728 комбинаций → исключено, за пределами 1й итерации
       [18, 8, 1, 1, 7, 2] → 1,902,749,184 комбинаций → исключено, за пределами 1й итерации
       [1, 8, 8, 1, 1, 7, 2] → 302,537,120,256 комбинаций → исключено, за пределами 1й итерации

    На основе этого ответа сегодня они написали программу (используя AI) и решили эту задачу,
    Операции: A1+A1 → A1*A1 → A1-A2 → A1*A2
    Результат
    ✅ Предварительная обработка завершена: 768 валидных операций.
    
     Проверяем разбиение: [18, 8, 11, 72]
       ❌ Нет операций для (0, 8)
    
     Проверяем разбиение: [18, 81, 1, 72]
       ✅ Все пары найдены. Проверяем комбинации...
    ✅ РЕШЕНИЕ НАЙДЕНО для разбиения [18, 81, 1, 72]
       Операции: A1+A1 → A1*A1 → A1-A2 → A1*A2
       mat1: [0, 0, 1, 0] → 0010
       mat2: [18, 81, 1, 72] → 1881172
    
    Process finished with exit code 0

    Программа на Python
    def find_operations_v2():
        # Матрицы
        mat1 = [
            [0, 1, 2, 3],
            [4, 5, 6, 7],
            [8, 9, 0, 1],
            [2, 3, 4, 5]
        ]
    
        mat2 = [
            [9, 8, 7, 6],
            [5, 4, 3, 2],
            [1, 0, 9, 8],
            [7, 6, 5, 4]
        ]
    
        # Единая функция для вычисления результата операции
        def apply_op(a, b, op):
            if op == 0:
                return a + b
            elif op == 1:
                return abs(a - b)
            else:  # op == 2
                return a * b
    
        # Все возможные операции: (r1,c1,r2,c2,op) → результаты (res1, res2)
        from collections import defaultdict
        all_ops = []  # список всех валидных операций
        result_map = defaultdict(list)  # (res1, res2) → операции
    
        for r1 in range(4):
            for c1 in range(4):
                for r2 in range(4):
                    for c2 in range(4):
                        for op in range(3):
                            res1 = apply_op(mat1[r1][c1], mat1[r2][c2], op)
                            res2 = apply_op(mat2[r1][c1], mat2[r2][c2], op)
                            if res1 > 81 or res2 > 81:
                                continue
                            all_ops.append((r1, c1, r2, c2, op))
                            result_map[(res1, res2)].append((r1, c1, r2, c2, op))
    
        print(f"✅ Предварительная обработка завершена: {len(all_ops)} валидных операций.")
    
        # Целевой результат для mat1
        target1 = [0, 0, 1, 0]
    
        # Возможные разбиения "1881172"
        possible_splits = [
            [18, 8, 11, 72],
            [18, 81, 1, 72],
            [18, 81, 17, 2]
        ]
    
        labels = "ABCD"
    
        # Перебираем все разбиения
        for target2 in possible_splits:
            print(f"\n Проверяем разбиение: {target2}")
            steps = list(zip(target1, target2))  # [(0,18), (0,8), (1,11), (0,72)] и т.д.
            candidates = []
            valid = True
            for t1, t2 in steps:
                key = (t1, t2)
                if key not in result_map:
                    print(f"   ❌ Нет операций для ({t1}, {t2})")
                    valid = False
                    break
                candidates.append(result_map[key])
            if not valid:
                continue
    
            print(f"   ✅ Все пары найдены. Проверяем комбинации...")
    
            # Перебираем все 4-операционные последовательности
            from itertools import product
            count = 0
            for ops_seq in product(*candidates):
                count += 1
                # Проверим результаты
                res1_check = []
                res2_check = []
                for (r1, c1, r2, c2, op) in ops_seq:
                    res1_check.append(apply_op(mat1[r1][c1], mat1[r2][c2], op))
                    res2_check.append(apply_op(mat2[r1][c1], mat2[r2][c2], op))
                if res1_check == target1 and res2_check == target2:
                    print(f"✅ РЕШЕНИЕ НАЙДЕНО для разбиения {target2}")
                    ops_str = []
                    for (r1, c1, r2, c2, op) in ops_seq:
                        cell1 = f"{labels[r1]}{c1+1}"
                        cell2 = f"{labels[r2]}{c2+1}"
                        op_char = "+" if op == 0 else "-" if op == 1 else "*"
                        ops_str.append(f"{cell1}{op_char}{cell2}")
                    print("   Операции:", " → ".join(ops_str))
                    print("   mat1:", res1_check, "→", ''.join(map(str, res1_check)))
                    print("   mat2:", res2_check, "→", ''.join(map(str, res2_check)))
                    return
    
            print(f"   ❌ Решений для этого разбиения не найдено.")
    
        print("\n❌ Ни одно разбиение не дало решения.")
    
    # Запуск
    find_operations_v2()


    P.S.S Мы честно решили вашу первую задачу - правило восстановлено по двум парам.
    Вы не оспорили решение - значит, система уязвима при 2 наблюдениях.

    Новая задача с 511427 и 1845 - логически невозможна:
    ---1  2  3  4    1  2  3  4
    --------------  ------------
    A [2, 7, 0, 4]	[1, 9, 4, 2]
    B [0, 3, 6, 5]	[5, 3, 0, 9]
    C [0, 7, 8, 3]	[4, 6, 2, 0]
    D [4, 5, 1, 2]	[1, 7, 8, 2]
    -----------------------------
          511427          1845

    Единственный допустимый вариант разбиения ключа 511427 -[5,11,42,7], так как:
    51 > 18 ->не может быть результатом сложения/вычитания, 51 = 3×17 или 1×51 -> оба множителя >9 -> невозможно при умножении,
    27 = 3×9 -> но в первой матрице нет цифры 9 -> невозможно, -> остаётся только [5,11,42,7].
    Но и здесь - проблема с 42:
    42 = 6×7 - единственный возможный вариант.
    В первой матрице: 6 есть (B3), 7 есть (A2, C2) -> возможно B3×A2 или B3×C2.
    Но во второй матрице: B3 = 0 -> операция умножения с B3 даёт 0.
    А в ответе 1845 - нуля нет. -> Противоречие.
    Утверждение, что правило одно - неверно.
    Если это ошибка - признайте.
    Если подтасовка - мы это видим.


    Честный анализ требует честных данных.
    У нас были одни - мы их разобрали.
    Теперь Вы предлагаете другие - но они не проходят проверку на реальность.
    Ответ написан
    44 комментария