← Back to Writeups
CUSTOMEasyCrypto

KeyForSolve - taipanbyte CTF

XESXOR9/10/20262 min read
#crypto#custom#easy#key_from_taskname#vigenere_decryption

KeyForSolve - taipanbyte CTF

Platform: taipanbyte | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-01-19 | Status: Solved Techniques: key_from_taskname, vigenere_decryption

Summary

Task: Decrypt a Vigenere-encoded ciphertext with format flag{...}. Solution: Recognize the task name "KeyForSolve" is literally the Vigenere key, apply standard Vigenere decryption using it to recover the flag.

KeyForSolve - taipanbyte CTF

Description

ppyl{i_iwowgc_qsmi_rvufjkxyv}

flag{}

Analysis

  1. The ciphertext ppyl{i_iwowgc_qsmi_rvufjkxyv} needs to decrypt to flag{...}
  2. The task name "KeyForSolve" is a hint that this IS the key for the Vigenere cipher
  3. The format ppyl -> flag confirms it's a Vigenere cipher (letter-by-letter substitution with key)
  4. Non-alphabetic characters ({, _, }) are preserved - classic Vigenere behavior

Solution

Key Insight

The task name "KeyForSolve" was the crucial hint - it literally IS the key needed to solve the Vigenere cipher. This is a common CTF pattern where the challenge name contains a hint to the solution. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Verification

Checking ppyl -> flag with key keyf:

  • p - k = f (15 - 10 = 5)
  • p - e = l (15 - 4 = 11)
  • y - y = a (24 - 24 = 0)
  • l - f = g (11 - 5 = 6)

Solve Script

python
#!/usr/bin/env python3
def vigenere_decrypt(ciphertext, key):
    result = []
    key_index = 0
    key = key.lower()
    
    for char in ciphertext:
        if char.isalpha():
            shift = ord(key[key_index % len(key)]) - ord('a')
            if char.isupper():
                decrypted = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
            else:
                decrypted = chr((ord(char) - ord('a') - shift) % 26 + ord('a'))
            result.append(decrypted)
            key_index += 1
        else:
            result.append(char)
    
    return ''.join(result)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

ciphertext = "ppyl{i_iwowgc_qsmi_rvufjkxyv}"
key = "keyforsolve"  # The task name is the key!

decrypted = vigenere_decrypt(ciphertext, key)
print(f"FLAG: {decrypted}")

Output

FLAG: flag{REDACTED}

Lessons Learned

  1. Always check the task name for hints - CTF authors love wordplay
  2. Vigenere cipher preserves non-alphabetic characters
  3. Known plaintext attack: if you know part of the plaintext, you can derive the key ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍