Skip to content

Latest commit

 

History

History
148 lines (112 loc) · 3.46 KB

File metadata and controls

148 lines (112 loc) · 3.46 KB

Vigenere (crypto 100)

###ENG PL

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:

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:

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:

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:

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}