シーザー暗号

シーザ暗号 - みずぴー日記 にインスパイヤされてシーザー暗号の暗号化と復号化を行ってみました。

awk には chr() 関数も ord() 関数も用意されていませんが、ASCII の範囲であれば gawk をインストールした時に /usr/share/awk/ord.awk などにインストールされますので、ここを使います。 gawk であればプラグマとして組み込めますが、nawk も想定して、ord.awk をほぼそのまま載せています。

#! /usr/local/bin/nawk -f
# caesar_cipher.awk
# シーザー暗号化、復号化します。
# usage: nawk -f caesar_cipher.awk

BEGIN {
    print encode_caesar_cipher("HAL", 1);       # エンコード
    print decode_caesar_cipher("IBM", 1);       # デコード
}

# encode_caesar_cipher(): シーザー暗号化
# in:   文字列 (str)
#       数値 (num)
# out:  文字列 (str) を数値 (num) だけシフトさせたシーザー暗号
function encode_caesar_cipher(str, num,     new_str, ord_num) {
    num_str = split(str, arr_str, "");

    for (i = 1; i <= num_str; i++) {
        ord_num = (ord(arr_str[i]) + num >= 90) ? \
                  (ord(arr_str[i]) + num) % 90 + 64 : \
                  ord(arr_str[i]) + num;
        new_str = new_str chr(ord_num);
    }

    return new_str;
}

# decode_caesar_cipher(): シーザー復号化
# in:   文字列 (str)
#       数値 (num)
# out:  文字列 (str) を数値 (num) だけシフトさせたシーザー複合
function decode_caesar_cipher(str, num,     new_str, ord_num) {
    num_str = split(str, arr_str, "");

    for (i = 1; i <= num_str; i++) {
        ord_num = (ord(arr_str[i]) - num <= 64) ? \
                  90 - 64 + (ord(arr_str[i]) - num) : \
                  ord(arr_str[i]) - num;
        new_str = new_str chr(ord_num);
    }

    return new_str;
}

# ord() と chr() 関数
# Ref.: /usr/share/awk/ord.awk
function _ord_init(    low, high, i, t) {
    low = sprintf("%c", 7)                  # BEL is ascii 7

    if (low == "\a") {                      # regular ascii
        low = 0;
        high = 127;
    } else if (sprintf("%c", 128 + 7) == "\a") {
        # ascii, mark parity
        low = 128;
        high = 255;
    } else {                                # ebcdic(!)
        low = 0;
        high = 255;
    }

    for (i = low; i <= high; i++) {
        t = sprintf("%c", i);
        _ord_[t] = i;
    }
}

function ord(str,    c) {
    _ord_init();
    # only first character is of interest
    c = substr(str, 1, 1);
    return _ord_[c];
}

function chr(c) {
    # force c to be numeric by adding 0
    return sprintf("%c", c + 0);
}

シーザー暗号として思いついたものが、『2001 年宇宙の旅』のコンピュータ HAL と IBM の関係だったので、これを例として用います。 (暗号でも何でもないかもしれませんが)

$ nawk -f caesar_cipher.awk
IBM
HAL

"HAL" が "IBM" に、"IBM" が "HAL" に変換されました。 この場合には 1 文字シフトになります。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png