Skip to main content

c1ph3r: writeup

Сслылка на задачу http://f8tasks.ru/challenges#c1ph3r-32

c1ph3r

CategoryCrypto
DifficultyEasy
CipherVigenere
Keycphr
Flagflag{v1g1n3r_c1ph3r}

Recon

Единственный артефакт задачи:

hahx{x1v1u3i_e1eo3i}

Структура сразу указывает на CTF-флаг: фигурные скобки, буквенно-цифровое содержимое, _ как разделитель. Прямого смысла в буквах нет — применено шифрование.

Гипотезы первого уровня:

  • ROT13 / Caesar — не дают осмысленного результата
  • Simple substitution — нет стандартных частотных паттернов
  • Vigenere — подозрение усиливается после анализа префикса

Known-plaintext entry point: в CTF флаг почти всегда начинается с flag{. Префикс шифротекста — hahx{ — ровно 4 буквы + {. Сопоставление с известным открытым текстом flag{ даёт 4 пары (cipher, plain), достаточных для восстановления ключа.


Known-Plaintext Attack: восстановление ключа

При шифровании Виженером каждая буква сдвигается на позицию соответствующей буквы ключа:

cipher_pos = (plain_pos + shift) mod 26

Из этого напрямую следует формула восстановления ключа:

shift    = (cipher_pos - plain_pos) mod 26
key_char = chr(shift + ord('a'))

Пример ручного расчёта для первой буквы:

cipher: 'h' → позиция 7  (a=0, b=1, ... h=7)
plain:  'f' → позиция 5
shift = (7 - 5) mod 26 = 2
key_char = chr(2 + ord('a')) = 'c'

То же самое для всех четырёх букв префикса:

#CipherПозицияPlainПозицияСдвигKey char
0h7f52c
1a0l1115p
2h7a07h
3x23g617r

Ключ: cphr

Ключ циклически повторяется на всю длину строки. Цифры (1, 3), {, } и _ шифрованию не подвергались — в шифротексте они стоят на своих исходных позициях.


Decryption

Расшифровка hahx{x1v1u3i_e1eo3i} ключом cphr:

Cipher:  h  a  h  x  {  x  1  v  1  u  3  i  _  e  1  e  o  3  i  }
Key:     c  p  h  r     c     p     h     r     c     p  h     c
Plain:   f  l  a  g  {  v  1  i  1  g  3  r  _  c  1  p  h  3  r  }

Результат: flag{v1g1n3r_c1ph3r}

Флаг самодокументируемый — содержимое прямо называет применённый шифр.


Automation

#!/usr/bin/env python3

FLAG = "hahx{x1v1u3i_e1eo3i}"
KEY = "cphr"


def vigenere_decrypt(value: str, key: str) -> str:
    result = []
    key_index = 0

    for char in value:
        if char.isalpha():
            shift = ord(key[key_index % len(key)]) - ord("a")
            base = ord("a") if char.islower() else ord("A")
            decoded = chr((ord(char) - base - shift) % 26 + base)
            result.append(decoded)
            key_index += 1
        else:
            result.append(char)

    return "".join(result)


def main() -> None:
    print(vigenere_decrypt(FLAG, KEY))


if __name__ == "__main__":
    main()
python3 solve.py
# flag{v1g1n3r_c1ph3r}

Key Takeaways

  1. Анализ паттернов. CTF-флаги следуют стандартному формату flag{...}. Умение читать структуру шифротекста и сопоставлять её с известным шаблоном — первый шаг к любому криптоанализу.

  2. Работа с ASCII. Шифр Виженера реализован через арифметику кодовых позиций символов (ord/chr). Понимание того, что буква — это число, критично для работы с текстовыми шифрами в коде.

  3. Автоматизация дешифровки. Ручной расчёт по таблице и скрипт на Python дают идентичный результат. Автоматизация необходима там, где ключ длиннее четырёх символов или шифротекст занимает тысячи строк.