ヴィジュネル暗号

pp.437-438
これでAVR Programming: Learning to Write Software for Hardware (Make: Technology on Your Time)は終わりにする。

アルファベットだけでなくスペース(0x20)からチルダ(0x7E)までを使うことにする。テキストはエンコードとデコードとで函数を分けているが、ここではひとつにまとめた。インウドゥ、ディーウドゥ。
f:id:ti-nspire:20200306071136p:plain

#include <iostream>

void Vigenere(unsigned char* text, const unsigned char* key, const unsigned char dir) {
    uint8_t textPos = 0;
    uint8_t keyPos = 0;

    const unsigned char topLetter = ' ';
    const unsigned char bottomLetter = '~';
    const uint8_t numOfLetters = (bottomLetter - topLetter + 1); // スペース(0x20)からチルダ(0x7E)までの95文字を使う。

    while (text[textPos]) { // 平文、暗号のどちらもnull文字の現れるまで変換を繰り返す。

        switch (dir) {
        case 'E':                                                            // 暗号化するとき:
            text[textPos] += (key[keyPos] - topLetter);                      // 鍵文字に応じて平文文字の文字コードを大きくする。
            if (text[textPos] > bottomLetter) text[textPos] -= numOfLetters; // 暗号化後の文字がチルダを超えたら、スペースまで戻してラップアラウンドする。
            break;
        case 'D':                                                           // 復号するとき:
            if (key[keyPos] > text[textPos]) text[textPos] += numOfLetters; // 暗号化後の文字がラップアラウンドしていたら、オーバーフローしていた元の位置へ戻す。
            text[textPos] -= (key[keyPos] - topLetter);                     // 鍵文字に応じて平文文字の文字コードを小さくする。
            break;
        default: break;
        }

        textPos++;                      // 次の平文(暗号)文字位置へ移る。
        if (!key[++keyPos]) keyPos = 0; // 次の鍵文字位置へ移るが、それがnull文字であったら先頭へ戻る。
    }
}

int main() {
    unsigned char text[] = "Our smart devices and projects will make our lives easier -- as long as we are as smart as they are.";
    const unsigned char key[] = "Written by Mike Senese";

    printf("平文        : %s\n", text);

    Vigenere(text, key, 'E'); printf("暗号化   : %s\n", text);
    Vigenere(text, key, 'E'); printf("さらに暗号化: %s\n", text);
    Vigenere(text, key, 'E'); printf("さらに暗号化: %s\n", text);

    Vigenere(text, key, 'D'); printf("復号    : %s\n", text);
    Vigenere(text, key, 'D'); printf("さらに復号  : %s\n", text);
    Vigenere(text, key, 'D'); printf("さらに復号  : %s\n", text);

    return 0;
}