Tags: vigener 

Rating:

# Vigenere (crypto 100)

###ENG
[PL](#pl-version)

In the task we get a ciphertext:

```
LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ
```

And information that this is Vigener Cipher with alphabet:

```
ABCDEFGHIJKLMNOPQRSTUVWXYZ{}
```

And the md5 of plaintext is `f528a6ab914c1ecf856a1d93103948fe`

We of course know the flag prefix `SECCON{` so we can instantly recover the prefix of the key:

```python
def get_key_prefix(alphabet, ct, known_pt):
result = ""
for i in range(len(known_pt)):
plain = known_pt[i]
cipher = ct[i]
key = alphabet[alphabet.index(cipher) - alphabet.index(plain)]
result += key
return result
```

which gives us `VIGENER`

Next we can just brute-force the missing 4 bytes of the key:

```python
def decode(alphabet, ct, key):
result = ""
for i in range(len(ct)):
c = ct[i]
k = key[i % len(key)]
if k != "?":
p = alphabet[alphabet.index(c) - alphabet.index(k)]
else:
p = "?"
result += p
return result

def worker(data):
c, alphabet, ct, key = data
key += c
for suffix in itertools.product(alphabet, repeat=4):
new_key = key + "".join(suffix)
pt = decode(alphabet, ct, new_key)
if hashlib.md5(pt).hexdigest() == "f528a6ab914c1ecf856a1d93103948fe":
print(pt)
return pt

def main():
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ{}"
ct = "LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ"
key_prefix = get_key_prefix(alphabet, ct, "SECCON{")
print('key prefix ', key_prefix)
print(brute(worker, [(c, alphabet, ct, key_prefix) for c in alphabet]))

if __name__ == '__main__':
freeze_support()
main()
```

Which gives us almost instantly `SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}`

###PL version

W zadaniu dostajemy zaszyfrowany tekst:

```
LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ
```

I informacje że to szyfr Vigenera z alfabetem:

```
ABCDEFGHIJKLMNOPQRSTUVWXYZ{}
```

Mamy też md5 plaintextu: `f528a6ab914c1ecf856a1d93103948fe`

I oczywiście znamy prefix flagi `SECCON{` więc możemy od razu odzyskać prefix klucza:

```python
def get_key_prefix(alphabet, ct, known_pt):
result = ""
for i in range(len(known_pt)):
plain = known_pt[i]
cipher = ct[i]
key = alphabet[alphabet.index(cipher) - alphabet.index(plain)]
result += key
return result
```

co daje nam `VIGENER`

Następnie możemy brute-forcować brakujące 4 bajty klucza:

```python
def decode(alphabet, ct, key):
result = ""
for i in range(len(ct)):
c = ct[i]
k = key[i % len(key)]
if k != "?":
p = alphabet[alphabet.index(c) - alphabet.index(k)]
else:
p = "?"
result += p
return result

def worker(data):
c, alphabet, ct, key = data
key += c
for suffix in itertools.product(alphabet, repeat=4):
new_key = key + "".join(suffix)
pt = decode(alphabet, ct, new_key)
if hashlib.md5(pt).hexdigest() == "f528a6ab914c1ecf856a1d93103948fe":
print(pt)
return pt

def main():
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ{}"
ct = "LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ"
key_prefix = get_key_prefix(alphabet, ct, "SECCON{")
print('key prefix ', key_prefix)
print(brute(worker, [(c, alphabet, ct, key_prefix) for c in alphabet]))

if __name__ == '__main__':
freeze_support()
main()
```

Co od razu daje nam `SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ}`

Original writeup (https://github.com/p4-team/ctf/tree/master/2016-12-10-seccon-2016-quals/vigenere).