# 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:
```pythondef 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:
```pythondef 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:
```pythondef 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:
```pythondef 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}`