26-04-2025
Pico CTF: Vigeneer
Шифр Виженера очень похож на шифр Цезаря, еще известном как ROT-13, ROT-14, etc.
Смысл у этого шифра похожий, но в отличие от шифра Цезаря, у него есть ключ. Например у нас есть слово "СЛОН", и мы хотим его зашифровать с помощью ключа "КЛЮЧ"
Таким образом, наши смещения будут чередоваться:
-
Смещаем букву "С" на позицию буквы "К" в алфавите (11, так как считаем букву "А" за 0), получаем позицию буквы С + позиция буквы К = 19 + 11 = 38 и берем по модулю длины алфавита, получается 5, а это буква Д
-
Далее по такой же схеме итерируем слово и ключ, в итоге получаем:
По заданию получаем cipher.txt
и ключ CYLAB
, по которому был зашифрован этот текст:
rgnoDVD{O0NU_WQ3_G1G3O3T3_A1AH3S_2951c89f}
Чтобы решить это задание, достаточно легкого скрипта на питоне, который будет по значению в таблице ASCII делать смещение согласно ключу.
Скучно.
Для разнообразия напишем такую программу на Rust:
use std::fs;
const ALPHABET_LENGTH: u8 = 26;
fn main() {
let file_path = "/home/svetsec/ctf/pico/vigenere/cipher.txt";
println!("In file {file_path}");
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
println!("With text:\n{contents}");
let key = "CYLAB";
let mut result: String = "".to_owned();
let mut added_non_alphebetical = 0;
for (i, char) in contents.chars().enumerate() {
if !char.is_alphabetic() {
added_non_alphebetical += 1;
result.push(char);
continue;
}
let is_uppercase = char.is_uppercase();
let base = if is_uppercase { b'A' } else { b'a' };
let alphabetic_order = char.to_ascii_lowercase() as u8 - b'a';
let shift = key
.chars()
.nth((i - added_non_alphebetical) % key.len())
.unwrap()
.to_ascii_lowercase() as u8
- b'a';
let shifted = (alphabetic_order as i8 - shift as i8).rem_euclid(ALPHABET_LENGTH as i8);
let new_char = (shifted + base as i8) as u8 as char;
result.push(new_char);
}
println!("{}", result)
}
и получаем ожидаемый результат с дельным советом и "солью" :)
picoCTF{D0NT_US3_V1G3N3R3_C1PH3R_2951a89h}