Java

Javaで実装するシーザー暗号

シーザー暗号とは

概要

シーザー暗号とは単一換字式暗号のひとつで、文字列の各文字を辞書順に3文字分シフトして暗号文を作る暗号です。紀元前、共和制ローマ時代において最高権力者であったガイウス・ユリウス・カサエルが使っていた手法とされ、ユリウス・カサエルの英語読み「ジュリアス・シーザー」から、シーザー暗号と呼ばれています。

暗号手順

暗号化にはアルファベットを使用します。数字や記号を含むものを対象とした場合はこれとは異なる単一換字式暗号となるため解説から除外します。

前提として、本稿では「左に3文字」が鍵となるような暗号化で解説します。

アルファベットの文字列を一文字ずつ、アルファベット順の3つ前の文字になるように3文字シフトします。「D」は「A」、「E」は「B」のように読み替え、「A」「B」「C」は一巡してそれぞれ「X」「Y」「Z」とします。

Javaをはじめとしたプログラムによる実装では、アルファベットをASCIIコードで扱うと楽に処理することができます。

文字10進数文字10進数
A65N78
B66O79
C67P80
D68Q81
E69R82
F70S83
G71T84
H72U85
I73V86
J74W87
K75X88
L76Y89
M77Z90

ASCIIコードで扱う場合は65〜90までの間で値を調整すればいいと考えられるため、単純な算術のみで表すことができます。

  1. アルファベットをASCIIコードとして扱う(例: A=65)
  2. アルファベットが0から始まるようにそれぞれ65を引く(例: A’=A-65=0)
  3. 3文字左にシフトする(例: A’-3=-3)
  4. 負数を除外するため26を足し、さらに26の剰余を求める(例: -3→23=X’)
  5. アルファベットが65から始まるようにそれぞれ65を足す(例: X=X’+65)

[aside type=”normal”]

負数の剰余を求める場合、言語により定義が異なるため注意しましょう。剰余の数学的な定義は2つあります。

  • 絶対値最小剰余(主にJava、C#などはこちらを用いる)
  • 最小非負剰余(主にPython、Rubyなどはこちらを用いる)

[/aside]

シーザー暗号の実装

前項の手順をそのまま反映すると以下のようになります。空白については詰めるのが一般的のようですので、今回は消去しました。

    public static final void main(String[] args) {

        //鍵
        final int key = -3;

        //暗号対象の文字列
        String source = "MAY THE SOURCE BE WITH YOU";

        //アルファベット以外は消去
        byte[] tmp = source.replaceAll("[^A-Z]", "").getBytes();
        byte[] buf = new byte[tmp.length];

        for (int i = 0; i < tmp.length; i++) {
            // シフトした文字がA(65)からZ(90)の間に収まるようにする
            int num = ((tmp[i] - 65) + key + 26) % 26;
            buf[i] = (byte) (num + 65);
        }

        System.out.println(new String(buf));
    }

結果

JXVQEBPLROZBYBTFQEVLR

鍵を+3にすれば元に戻ります(スペース以外)

MAYTHESOURCEBEWITHYOU

もっと簡単にしたい時

Apache Common Lang3 の StringUtils.replaceChars()を使うともっと簡単にできます。

[kanren postid=”83″]

ABOUT ME
sasakiyu
ひ弱で優しい少年だったが、デーモンと合体。 強大な力を得つつも人間の心を失わないデベルマンとなる。