![見出し画像](https://assets.st-note.com/production/uploads/images/37257345/rectangle_large_type_2_dfd2e1f0c64978ee161adb6c4cfd83f9.png?width=1200)
シフト暗号
概要
シーザー暗号は、単一換字式暗号の一種で文字列の各文字に3文字分シフトして暗号文を作ります。シフト暗号はこのシフト文字数を任意値にしたものとなります。
昨今では暗号化ではなく、言葉遊びとしてIBM→HALなどの一部有名な名前をROT1(シフト1)で作成している有名なケースがあります。
アルゴリズム
平文にはアルファベットを使用します。
アルファベット以外を暗号化対象とした場合は、これとは異なる暗号化を使用しなければいけないため、今回は使用しません。
上記のように「a」を「D」、「b」を「E」に平文を暗号化できたら成功です。
シーザー暗号を用いてアルファベットを暗号化する場合は、ASCIIコードを利用すると楽に処理することができます。
①アルファベットをASCIIコードとして扱う。
②アルファベットが0から始めるように65を引く。(A'=A-65=0)
③3文字左にシフトする。(A'-3=-3)
④負数を除外するため26(A-Zの個数)を足し、さらに26の剰余を求める。(-3→23=X')
⑤アルファベットが65から始まるようにそれぞれ65を足す。(X=X'+65)
プログラム
平文とキー値を空白区切りで入力し、暗号文を作成してみます。
アルゴリズムを基にプログラムを組み立ててみましょう。
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class sample {
static final int ALPHABET = 26;
static final int ASCII_A = 65;
public static void main(String[] args) {
// コマンドラインから平文とキーの取得
Scanner scan = new Scanner(System.in, StandardCharsets.US_ASCII);
String text = scan.next().replaceAll("[^A-Z]", "");
int key = scan.nextInt();
System.out.println("平文 :" + text);
byte[] temp = text.getBytes();
byte[] buf = new byte[text.length()];
for (int i=0; i<temp.length; i++) {
int num = (temp[i] - ASCII_A - key + ALPHABET) % ALPHABET;
buf[i] = (byte)(num + ASCII_A);
}
System.out.println("暗号文 :" + new String(buf));
}
}
では、「ABC 3」と入力してみましょう。
$ ABC 3
$ 平文 :ABC
$ 暗号文 :XYZ
まとめ
アルファベットは26文字なので、シフトする文字を13に設定すれば暗号化も復号も同じ鍵(シフト数)で可能となります。
但し、鍵空間が26文字のため総当たり攻撃を行えば容易に解読されてしまうため、シフトすることで作成されている暗号文も存在していたことを知識として身に着けておけば良いかと思います。