Task: Chaocipher


C++: #include <iostream>

enum class Mode {
    ENCRYPT,
    DECRYPT,
};

const std::string L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const std::string R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";

std::string exec(std::string text, Mode mode, bool showSteps = false) {
    auto left = L_ALPHABET;
    auto right = R_ALPHABET;
    auto eText = new char[text.size() + 1];
    auto temp = new char[27];

    memset(eText, 0, text.size() + 1);
    memset(temp, 0, 27);

    for (size_t i = 0; i < text.size(); i++) {
        if (showSteps) std::cout << left << ' ' << right << '\n';
        size_t index;
        if (mode == Mode::ENCRYPT) {
            index = right.find(text[i]);
            eText[i] = left[index];
        } else {
            index = left.find(text[i]);
            eText[i] = right[index];
        }
        if (i == text.size() - 1) break;

        

        for (int j = index; j < 26; ++j) temp[j - index] = left[j];
        for (int j = 0; j < index; ++j) temp[26 - index + j] = left[j];
        auto store = temp[1];
        for (int j = 2; j < 14; ++j) temp[j - 1] = temp[j];
        temp[13] = store;
        left = temp;

        

        for (int j = index; j < 26; ++j) temp[j - index] = right[j];
        for (int j = 0; j < index; ++j) temp[26 - index + j] = right[j];
        store = temp[0];
        for (int j = 1; j < 26; ++j) temp[j - 1] = temp[j];
        temp[25] = store;
        store = temp[2];
        for (int j = 3; j < 14; ++j) temp[j - 1] = temp[j];
        temp[13] = store;
        right = temp;
    }

    return eText;
}

int main() {
    auto plainText = "WELLDONEISBETTERTHANWELLSAID";
    std::cout << "The original plaintext is : " << plainText << "\n\n";
    std::cout << "The left and right alphabets after each permutation during encryption are :\n";
    auto cipherText = exec(plainText, Mode::ENCRYPT, true);
    std::cout << "\nThe ciphertext is : " << cipherText << '\n';
    auto plainText2 = exec(cipherText, Mode::DECRYPT);
    std::cout << "\nThe recovered plaintext is : " << plainText2 << '\n';

    return 0;
}






Python: 



def main():
    
    lalpha = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
    ralpha = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
    msg = "WELLDONEISBETTERTHANWELLSAID"

    print("L:", lalpha)
    print("R:", ralpha)
    print("I:", msg)
    print("O:", do_chao(msg, lalpha, ralpha, 1, 0), "\n")
    
    do_chao(msg, lalpha, ralpha, 1, 1)

def do_chao(msg, lalpha, ralpha, en=1, show=0):
    msg = correct_case(msg)
    out = ""    
    if show:
        print("="*54)        
        print(10*" " + "left:" + 21*" " + "right: ")
        print("="*54)        
        print(lalpha, ralpha, "\n")
    for L in msg:
        if en:
            lalpha, ralpha = rotate_wheels(lalpha, ralpha, L)
            out += lalpha[0]
        else:
            ralpha, lalpha = rotate_wheels(ralpha, lalpha, L)
            out += ralpha[0]
        lalpha, ralpha = scramble_wheels(lalpha, ralpha)
        if show:
            print(lalpha, ralpha)            
    return out
    
def makealpha(key=""):
    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    z = set()
    key = [x.upper() for x in (key + alpha[::-1])
           if not (x.upper() in z or z.add(x.upper()))]
    return "".join(key)

def correct_case(string):
    return "".join([s.upper() for s in string if s.isalpha()])

def permu(alp, num):
    alp = alp[:num], alp[num:]
    return "".join(alp[::-1])

def rotate_wheels(lalph, ralph, key):
    newin = ralph.index(key)
    return permu(lalph, newin), permu(ralph, newin)    

def scramble_wheels(lalph, ralph):
    
    
    lalph = list(lalph)
    lalph = "".join([*lalph[0],
                    *lalph[2:14],
                    lalph[1],
                    *lalph[14:]])
    
    
    
    
    ralph = list(ralph)
    ralph = "".join([*ralph[1:3],
                     *ralph[4:15],
                     ralph[3],
                     *ralph[15:],
                     ralph[0]])
    return lalph, ralph

main()