[*] -  SecureInfo.eu, /Crypto/adfgvx-crypt.py

Back


#!/usr/bin/env python3
##from:chatGPT
import sys
import argparse
import math

ADFGVX = 'ADFGVX'

def build_polybius_square(key):
    alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    seen = set()
    square_key = ''.join([c for c in key.upper() if c not in seen and not seen.add(c)])
    remaining = ''.join([c for c in alphabet if c not in square_key])
    full_key = square_key + remaining

    square = {}
    rev_square = {}
    i = 0
    for r in ADFGVX:
        for c in ADFGVX:
            digraph = r + c
            char = full_key[i]
            square[char] = digraph
            rev_square[digraph] = char
            i += 1
    return square, rev_square

def columnar_transposition(text, key):
    num_cols = len(key)
    num_rows = math.ceil(len(text) / num_cols)
    padded_text = text.ljust(num_cols * num_rows, 'X')

    matrix = [padded_text[i:i+num_cols] for i in range(0, len(padded_text), num_cols)]

    key_order = sorted(list(enumerate(key)), key=lambda x: x[1])
    result = ''
    for idx, _ in key_order:
        result += ''.join(row[idx] for row in matrix)
    return result

def inverse_columnar_transposition(ciphertext, keyword):
    num_cols = len(keyword)
    num_rows = math.ceil(len(ciphertext) / num_cols)
    padded_len = num_rows * num_cols
    padded_cipher = ciphertext.ljust(padded_len, 'X')

    sorted_key = sorted(list(enumerate(keyword)), key=lambda x: x[1])
    col_order = [idx for idx, _ in sorted_key]

    columns = [''] * num_cols
    k = 0
    for col in col_order:
        col_len = num_rows
        columns[col] = padded_cipher[k:k+col_len]
        k += col_len

    plaintext = ''
    for i in range(num_rows):
        for col in range(num_cols):
            if i < len(columns[col]):
                plaintext += columns[col][i]
    return plaintext

def adfgvx_encrypt(plaintext, transposition_key, square_key):
    plaintext = ''.join(plaintext.strip().upper().replace(' ', '').replace('\n', ''))
    square, _ = build_polybius_square(square_key)

    # Substitution
    polybius_text = ''.join(square[c] for c in plaintext if c in square)

    # Transposition
    return columnar_transposition(polybius_text, transposition_key)

def adfgvx_decrypt(ciphertext, transposition_key, square_key):
    ciphertext = ''.join(ciphertext.strip().upper().split())
    _, rev_square = build_polybius_square(square_key)

    # Inverse Transposition
    intermediate = inverse_columnar_transposition(ciphertext, transposition_key)

    # Reverse Polybius
    plaintext = ''
    for i in range(0, len(intermediate), 2):
        digraph = intermediate[i:i+2]
        if len(digraph) == 2 and digraph in rev_square:
            plaintext += rev_square[digraph]
    return plaintext

def main():

    parser = argparse.ArgumentParser(description="ADFGVX encryptor/decryptor")
    parser.add_argument('-k', '--key', required=False, help='Transposition key')
    parser.add_argument('-s', '--square', required=False, help='Polybius square key')
    parser.add_argument('-m', '--mode', choices=['encrypt', 'decrypt'], required=True, help='Mode')
    parser.add_argument('file', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help='Input file or STDIN')
    args = parser.parse_args()

    data = args.file.read()

    key="ADFGVX"
    square="ADFGVX"

    try:
      key = args.key.upper()
    except:
      pass

    try:
      square = args.square.upper()
    except:
      pass

    if args.mode == 'encrypt':
        result = adfgvx_encrypt(data, key.upper(), square.upper())
    else:
        result = adfgvx_decrypt(data, key.upper(), square.upper())
    print(result)

if __name__ == "__main__":
    main()
⬆️ Top
admin