「暗号/Enigma用プログラム」の編集履歴(バックアップ)一覧はこちら
暗号/Enigma用プログラム - (2010/05/03 (月) 23:33:07) の1つ前との変更点
追加された行は緑色になります。
削除された行は赤色になります。
//java/linenumber
//このページはwikiのソースコードモードで作られています.
//プログラム以外の部分はコメントアウトするようにしましょう.
//プログラムの改変は,(直接書き換えず)そのプログラムの後に付け足すのがいいでしょう.
//結局ローター改変できなかったため、お茶をにごします。
//この前練習がてら作ったスタキュレーのコード(Slide)とカエサル暗号のコード(Caesar)です。
//RSAとかのアルゴリズム(?)もwikiに書いておきますね。
/*
・スタキュレー
スライドする数をxとすると、平文の文字列から0,x,2x,…1,x+1,2x+1,…2,x+2,2x+2,…という順番に文字を取っていく。
ex) x=3でabcdefghi→adgbehcfi
*/
//MayFes.javaで保存、実行すればテストできる。
import java.io.*;
abstract class Code{
int ln; //length of plaintxt
String plaintxt; //平文
abstract String encode(); //暗号化
abstract String decode(String str); //復号化 引数は暗号文
}
class Slide extends Code{
int num; //how many steps does it slide
Slide(int x, String str){
num = x;
ln = str.length();
plaintxt = str;
}
public String encode(){
StringBuffer ciphertxt = new StringBuffer();
int pointa = 0;
int start = 0;
int times = 0;
while(times != ln){
times ++;
if(pointa >= ln){
start++;
pointa = start;
}
ciphertxt.append(plaintxt.charAt(pointa));
pointa = num+pointa;
}
return ciphertxt.toString().toUpperCase();
}
public String decode(String str){
String ciphertxt = str;
int ln_deco = str.length();
char[] plaintxt_array = new char[ln_deco];
StringBuffer plaintxt2 = new StringBuffer();
int pointa = 0;
int start = 0;
int times = 0;
while(times != ln_deco){
if(pointa >= ln_deco){
start++;
pointa = start;
}
plaintxt_array[pointa] = ciphertxt.charAt(times);
pointa = pointa+num;
times ++;
}
for(int i = 0; i < ln_deco; i++){
plaintxt2.append(plaintxt_array[i]);
}
return plaintxt2.toString().toLowerCase();
}
}
class Caesar extends Code{
int sn; //slide number
Caesar(int k, String str){
sn = k;
ln = str.length();
plaintxt = str;
}
String encode(){
StringBuffer ciphertxt = new StringBuffer(); //暗号文
for(int i = 0; i < ln; i++){
ciphertxt.append((char)((int)'a'+((int)plaintxt.charAt(i)-(int)'a'+sn)%26));
}
return ciphertxt.toString().toUpperCase();
}
String decode(String str){
String ciphertxt = str.toLowerCase();
int ln_deco = str.length();
StringBuffer plaintxt2 = new StringBuffer();
for(int i = 0; i < ln_deco; i++){
plaintxt2.append((char)((int)'z'-((int)'z'-(int)ciphertxt.charAt(i)+sn)%26));
}
return plaintxt2.toString();
}
}
public class MayFes{
public static void main(String[] args) throws IOException{
//下の2行はコマプロで入力した文をstrにするためのコード
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
Slide c = new Slide(3, str);
Caesar cc = new Caesar(5, str);
System.out.println(c.encode());
System.out.println(c.decode(c.encode()));
System.out.println(cc.encode());
System.out.println(cc.decode(cc.encode()));
}
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/////////////////////ENIGMA////////////////////////////
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/*
簡易説明(初期設定らへんについて 動かし方については[class Enigma]の前で説明)
メモリは6つ(使う文字もa~f)として説明する。
ローターは最初から3つ一気に定義しちゃう。一周したら次が1メモリ動くのが楽に作れるから。
ポインタ3つはそれぞれのローターにたいして一つずつ。
ポインタの位置はインスタンスを作る際に設定します。
ちょこちょこ末尾にでてくる1,2,3の数字はどのローターに対してのメソッドかを示しています。
[numbers]はいくつローターを通るといくつズレるのかを設定してある。
[Rotor]のインスタンスを作る際にローターの構造を設定する。
その際、アルファベットで設定。
たとえば、設定をbdecfaとしたら
a→b(+1) a→b
b→d(+2) b→c→d
c→e(+2) c→d→e
d→c(+5) d→e→f→a→b→c
e→f(+1) e→f
f→a(+1) f→a
なので、numbersには{1,2,2,5,1,1}が記憶される。
一回ローターが回ると、いくつズレるかが1つずつ下にいき、
a→ b(+1)
b→ c(+1)
c→ e(+2)
d→ f(+2)
e→ d(+5)
f→ a(+1)
という変換がされるようになっている。
[reflecter]は最初から定義済み。変えるときはめんどくさいけど一つずつ設定してください。(コピペしてもらえれば70行目らへん) (このページだと202行目)
ローターを通る時はめんどくさいので最初に[set_input]で文字を数字に変えて全部数字でやってます。[get_output]で最後に数字を文字にもどしています。
*/
class Rotor{
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[6];
int[] numbers2 = new int[6];
int[] numbers3 = new int[6];
int[] reflecter = new int[6];
int[] input;
int[] output;
String out;
int l; //平分の長さ
//////////////////////////////////////////////////////////////////////
//////////////////どれだけズレるのかを配列に記憶させる////////////////
//////////////////reflecterは今は最初から設定する/////////////////////
//////////////////////////////////////////////////////////////////////
Rotor(String str1,String str2, String str3){
for(int i =0; i < 6; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + 6;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + 6;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + 6;
//////////////////////////////////////////////////////////////
////////////////reflecterの設定はここ/////////////////////////
//////////////////////////////////////////////////////////////
reflecter[0] = 5;
reflecter[1] = 4;
reflecter[2] = 3;
reflecter[3] = 2;
reflecter[4] = 1;
reflecter[5] = 0;
}
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = x;
pointa2 = y;
pointa3 = z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
pointa1++;
if(pointa1 == 6){
pointa1 = 0;
pointa2++;
if(pointa2 == 6){
pointa2 = 0;
pointa3++;
if(pointa3 == 6){
pointa3 = 0;
}
}
}
}
////////////////////////////////////////////////////////////////
////////// goで行きの変換 backで帰りの変換////////////////////
//////////////////reflecterは今はすでに設定されているとする/////
////////////////////////////////////////////////////////////////
int go1(int x){
int y = x-pointa1;
if(y < 0) y = 6-(pointa1-x);
int z = x+numbers1[y];
if(z >= 6) z = z-6;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = 6-(pointa2-x);
int z = x+numbers2[y];
if(z >= 6) z = z-6;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = 6-(pointa3-x);
int z = x+numbers3[y];
if(z >= 6) z = z-6;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
///////////////////////////////////////////////////////////////
//////////ここまでで準備終了///////////////////////////////////
//////////以下文章が入ってきた動作/////////////////////////////
///////////////////////////////////////////////////////////////
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
pointa_forward();
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
void run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
System.out.println(out);
}
}
/*
簡易説明(どうやって動かすか)
だいたい下の通りですが、まずは[Rotor]のインスタンスを作ります。
その際に、ローターの設定を行ってください。(アルファベットの意味については冒頭の簡易説明参照)
ポインタはローターのインスタンスを作った際の初期設定では(0,0,0)になっています。
変えたいときは[pointa_set()]をつかってください。
pointa_set(1,2,3)とでもやれば
pointa1→1
pointa2→2
pointa3→3
とセットされます。
[pointa_reset()]で初期設定にも戻せます。
あとは[run(入力)]で出力がコマプロに出るようになっています。
[out]が出力のString形式になっています。
下で実際に動かした様子を見てみると、(実行してみてください)
fdcbea→cebcaf
が最初に実行されます。
手に入れたcebcafを入力しても
cebcaf→afeafd
となり最初の文字列が復元できません。
[pointa_reset()]でポインタをもとに戻して実行すると
cebcaf→fdcbea
となり今度はうまくいきます。
次にポインタを(3,4,2)にセットしてもう一度fdcbeaを入力してみましょう。
fdcbea→ebeefc
とさっきとは違う文字列が得られました。
もう一度ポインタを(3,4,2)にセットしなおして、ebeefcを入力すると
ebeefc→fdcbea
と復元できます。
*/
public class Enigma{
public static void main(String[] args){
Rotor r = new Rotor("fadecb","cadbef","ebdcfa");
r.run("fdcbea");
r.run("cebcaf");
r.pointa_reset();
r.run("cebcaf");
r.pointa_set(3,4,2);
r.run("fdcbea");
r.pointa_set(3,4,2);
r.run("ebeefc");
}
}
////////////////////////////////////Enigma ここまで
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/////////////////////ENIGMA ver1.1/////変更byうぇぶ////
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
//主な変更点 modの導入,26変数化へ
// pointa_setを変更 文字がa=0,b=2,…,z=25に対応するように.
// pointa_forwardを変更 アプレット版通りの挙動
// set_outputを変更 pointa_forwardを最初に実行する.
// run()を変更 平文->暗号文という出力に.
//今後の課題 Rotor1,Rotor2の繰り上がり条件の一般化 (pointa_forward)
class Rotor{
int mod = 26;
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[mod];
int[] numbers2 = new int[mod];
int[] numbers3 = new int[mod];
int[] reflecter = new int[mod];
int[] input;
int[] output;
String out;
int l; //平分の長さ
//////////////////////////////////////////////////////////////////////
//////////////////どれだけズレるのかを配列に記憶させる////////////////
//////////////////reflecterは今は最初から設定する/////////////////////
//////////////////////////////////////////////////////////////////////
Rotor(String str1,String str2, String str3){
for(int i =0; i < mod; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + mod;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + mod;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + mod;
//////////////////////////////////////////////////////////////
////////////////reflecterの設定はここ/////////////////////////
//////////////////////////////////////////////////////////////
//ReflecterBの設定
reflecter[0] = 24 ;
reflecter[1] = 17 ;
reflecter[2] = 20 ;
reflecter[3] = 7 ;
reflecter[4] = 16 ;
reflecter[5] = 18 ;
reflecter[6] = 11 ;
reflecter[7] = 3 ;
reflecter[8] = 15 ;
reflecter[9] = 23 ;
reflecter[10] = 13 ;
reflecter[11] = 6 ;
reflecter[12] = 14 ;
reflecter[13] = 10 ;
reflecter[14] = 12 ;
reflecter[15] = 8 ;
reflecter[16] = 4 ;
reflecter[17] = 1 ;
reflecter[18] = 5 ;
reflecter[19] = 25 ;
reflecter[20] = 2 ;
reflecter[21] = 22 ;
reflecter[22] = 21 ;
reflecter[23] = 9 ;
reflecter[24] = 0 ;
reflecter[25] = 19 ;
}
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = mod - x;
pointa2 = mod - y;
pointa3 = mod - z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
//RotorをRotorIII,RotorII,RotorIの順にセットした時のポインタの挙動(うぇぶ)
//アプレット版の挙動を再現している. Rotorを他の順にするときは22と4の数字を変える.
if(pointa2 == 22){ //RotorIIの繰り上がりの数22 (eの数字4,mod-4=22)
pointa2--;
pointa3--;
if(pointa3 < 0){
pointa3 = pointa3 + mod;
}
}
pointa1--;
if(pointa1 < 0){
pointa1 = pointa1 + mod;
}
if(pointa1 == 4){ //RotorIIIの繰り上がりの数22 (wの数字22,mod-22=4)
pointa2--;
if(pointa2 < 0){
pointa2 = pointa2 + mod;
}
}
}
////////////////////////////////////////////////////////////////
////////// goで行きの変換 backで帰りの変換////////////////////
//////////////////reflecterは今はすでに設定されているとする/////
////////////////////////////////////////////////////////////////
int go1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x+numbers1[y];
if(z >= mod) z = z-mod;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x+numbers2[y];
if(z >= mod) z = z-mod;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x+numbers3[y];
if(z >= mod) z = z-mod;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
///////////////////////////////////////////////////////////////
//////////ここまでで準備終了///////////////////////////////////
//////////以下文章が入ってきた動作/////////////////////////////
///////////////////////////////////////////////////////////////
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
pointa_forward();
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
void run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
System.out.println(str + " -> " +out);
}
}
/*
簡易説明(どうやって動かすか)
だいたい下の通りですが、まずは[Rotor]のインスタンスを作ります。
その際に、ローターの設定を行ってください。(アルファベットの意味については冒頭の簡易説明参照)
ポインタはローターのインスタンスを作った際の初期設定では(0,0,0)になっています。
変えたいときは[pointa_set()]をつかってください。
pointa_set(1,2,3)とでもやれば
pointa1→1
pointa2→2
pointa3→3
とセットされます。
[pointa_reset()]で初期設定にも戻せます。
あとは[run(入力)]で出力がコマプロに出るようになっています。
[out]が出力のString形式になっています。
下で実際に動かした様子を見てみると、(実行してみてください)
fdcbea→cebcaf
が最初に実行されます。
手に入れたcebcafを入力しても
cebcaf→afeafd
となり最初の文字列が復元できません。
[pointa_reset()]でポインタをもとに戻して実行すると
cebcaf→fdcbea
となり今度はうまくいきます。
次にポインタを(3,4,2)にセットしてもう一度fdcbeaを入力してみましょう。
fdcbea→ebeefc
とさっきとは違う文字列が得られました。
もう一度ポインタを(3,4,2)にセットしなおして、ebeefcを入力すると
ebeefc→fdcbea
と復元できます。
*/
public class Enigma{
public static void main(String[] args){
Rotor r = new Rotor("bdfhjlcprtxvznyeiwgakmusqo",
"ajdksiruxblhwtmcqgznpyfvoe",
"ekmflgdqvzntowyhxuspaibrcj");
//Rotorの設定 上から順にRotorIII,RotorII,RotorI
//pointa初期設定x=23,d=3,h=7
r.pointa_set(23,3,7);
r.run("abc");
r.pointa_set(23,3,7);
r.run("azy");
r.pointa_set(23,3,7);
r.run("aaa");
r.pointa_set(23,3,7);
r.run("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
r.pointa_set(23,3,7);
r.run("kqg");
}
}
/////////////////////////////////Enigma ver1.1 ここまで
//////////////////ver.1.2用。なんかうまくいかない。
int[] srebmun1 = new int[mod]; //numbersの逆関数的なもの
int[] srebmun2 = new int[mod];
int[] srebmun3 = new int[mod];
srebmun1[(int)str1.charAt(i)-(int)'a'] = mod - numbers1[i];
srebmun2[(int)str2.charAt(i)-(int)'a'] = mod - numbers2[i];
srebmun3[(int)str3.charAt(i)-(int)'a'] = mod - numbers3[i];
int bback1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x + srebmun1[y];
if(z >= mod) z = z-mod;
return z;
}
int bback2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x + srebmun2[y];
if(z >= mod) z = z-mod;
return z;
}
int bback3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x + srebmun3[y];
if(z >= mod) z = z-mod;
return z;
}
}
////////////////////////////////////////////////////////////////////
/////////////////////////ENIGMA IN GUI//////////////////////////////
////////////////////////////////////////////////////////////////////
/*
使い方説明。
正味な話、くみっしゅの完コピなので頑張ってコードを読めばわかるんじゃないかな?
とか思わないでください。
今回は見やすくしようだなんて微塵も思っていないので。
とりあえず、下に
Browser.java
Browser.html
のプログラムを置いてあるのでそのままコピペしてください。
あとはコマプロで
javac Browser.java
appletviewer Browser.html
と打てばおしまい!!簡単!!って覚えてるか。
んで、変にhtmlのところとかでサイズを変えなければ
・aaaaaaaaaaaって書いてある四角が1つ
・アルファベットがごちゃごちゃしている四角が3つ
・K,E,Yって書いてある四角が1つずつ
・GoボタンとSetボタン
・でっかい四角が2つ
以上のものがあるはず。
・aaaaaaaaaaaaaって書いてあるところ
ここ平文を入れる。
注意点としては、平文に小文字アルファベット以外のものが入っているとうんともすんともいわない。
ピリオド、空白ですらダメ。どうにかしたほうがいいかも。
・アルファベットがごちゃごちゃしているところ
この子たちはローターの構造を表している。前回のEnigmaでRotorの構造を決定するときの文字列をそのまま入れてくれればOK。
特に注意点はないし、この状況でネットのapplet版とそろっているらしい。うぇぶがやってくれました。
・K,E,Yって書いてあるところ
ここにpointa1,2,3の番号を入れる。
applet版のデフォルトは(23,3,7)らしい。
注意点として、文字は入れないこと。いちいちKEYの文字は消さないと動かないよ。(気に入らなかったら変えますね)
・Goボタン
これをおして暗号化
・Setボタン
ローターやポインタの位置を変えたいのなら書きこんだあとにSetボタンを押してくれないと意味がないからね。
Setしてあげてね。
・でっかい四角
ここに出力される。
*/
///////////////////////////////////////////////////////
///////////////////全体の流れ(一番大事)//////////////
///////////////////////////////////////////////////////
/*
まずは必ずポインタ(K,E,Yの部分)の数字を決めてセットすること。それをしないと動かない。
そして平文には小文字アルファベットしか入れない。
Goボタンを押せば、左の四角に暗号化された文が、右には最後の文字を変換したときの変換規則とポインタの位置がでてきます。
Setボタンを押さない限り、ポインタの位置はずれ続けます。
同じ文字列でも2回連続でGoボタンおしたら暗号文は変わるってことね。
そのかわり暗号文をコピペして、ポインタのところは変えずにSet→Goとすればもとの平文がよみがえるはずです。(あたりまえだけど)
例外処理は僕の手に負えないところなので、基本的に予想外のことが起きたらうんともすんともいわなくなりますが、
なにかミスを見っけたら教えてください。
直しといてくれると泣いて喜んじゃうよ?
*/
//Browser.java
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
class Rotor{
int mod = 26;
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[mod];
int[] numbers2 = new int[mod];
int[] numbers3 = new int[mod];
int[] reflecter = new int[mod];
int[] input;
int[] output;
String out;
int l; //平分の長さ
Rotor(String str1,String str2, String str3){
for(int i =0; i < mod; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + mod;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + mod;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + mod;
}
reflecter[0] = 24 ;
reflecter[1] = 17 ;
reflecter[2] = 20 ;
reflecter[3] = 7 ;
reflecter[4] = 16 ;
reflecter[5] = 18 ;
reflecter[6] = 11 ;
reflecter[7] = 3 ;
reflecter[8] = 15 ;
reflecter[9] = 23 ;
reflecter[10] = 13 ;
reflecter[11] = 6 ;
reflecter[12] = 14 ;
reflecter[13] = 10 ;
reflecter[14] = 12 ;
reflecter[15] = 8 ;
reflecter[16] = 4 ;
reflecter[17] = 1 ;
reflecter[18] = 5 ;
reflecter[19] = 25 ;
reflecter[20] = 2 ;
reflecter[21] = 22 ;
reflecter[22] = 21 ;
reflecter[23] = 9 ;
reflecter[24] = 0 ;
reflecter[25] = 19 ;
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = mod - x;
pointa2 = mod - y;
pointa3 = mod - z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
if(pointa2 == 22){ //RotorIIの繰り上がりの数22 (eの数字4,mod-4=22)
pointa2--;
pointa3--;
if(pointa3 < 0){
pointa3 = pointa3 + mod;
}
}
pointa1--;
if(pointa1 < 0){
pointa1 = pointa1 + mod;
}
if(pointa1 == 4){ //RotorIIIの繰り上がりの数22 (wの数字22,mod-22=4)
pointa2--;
if(pointa2 < 0){
pointa2 = pointa2 + mod;
}
}
}
int go1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x+numbers1[y];
if(z >= mod) z = z-mod;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x+numbers2[y];
if(z >= mod) z = z-mod;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x+numbers3[y];
if(z >= mod) z = z-mod;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
pointa_forward();
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
String run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
return out;
}
}
/////////////////////////////////Enigma ver1.1 ここまで
class MyTextField extends TextField{
MyTextField(Browser br,String str){
super(str,50);
br.add(this);
}
}
class MyTextFieldRotor1 extends TextField{
MyTextFieldRotor1(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldRotor2 extends TextField{
MyTextFieldRotor2(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldRotor3 extends TextField{
MyTextFieldRotor3(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldKey1 extends TextField{
MyTextFieldKey1(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextFieldKey2 extends TextField{
MyTextFieldKey2(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextFieldKey3 extends TextField{
MyTextFieldKey3(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextArea extends TextArea{
MyTextArea(Browser br){
super("",20,40,TextArea.SCROLLBARS_BOTH);
setEditable(true);
setFont(new Font("Helvetica",Font.PLAIN,12));
br.add(this);
}
}
class MyTextArea2 extends TextArea{
MyTextArea2(Browser br){
super("",20,35,TextArea.SCROLLBARS_BOTH);
setEditable(true);
setFont(new Font("Helvetica",Font.PLAIN,12));
br.add(this);
}
}
abstract class MyButton extends Button implements ActionListener{
final Browser browser;
MyButton(Browser br,String name){
super(name);
browser = br;
browser.add(this);
addActionListener(this);
}
abstract public void actionPerformed(ActionEvent e);
}
class MyGoButton extends MyButton{
MyGoButton(Browser br){
super(br,"Go");
}
public void actionPerformed(ActionEvent e){
browser.go();
}
}
class MySetButton extends MyButton{
MySetButton(Browser br){
super(br, "Set");
}
public void actionPerformed(ActionEvent e){
browser.set();
}
}
public class Browser extends Applet {
MyTextArea myTextArea;
MyTextArea2 myTextArea2;
MyTextField myTextField;
MyTextFieldKey1 myTextFieldKey1;
MyTextFieldKey2 myTextFieldKey2;
MyTextFieldKey3 myTextFieldKey3;
MyTextFieldRotor1 myTextFieldRotor1;
MyTextFieldRotor2 myTextFieldRotor2;
MyTextFieldRotor3 myTextFieldRotor3;
Rotor rotor;
void go(){
myTextArea.append(rotor.run(myTextField.getText())+"\n\n");
myTextArea2.append("abcdefghijklmnopqrstuvwxyz k e y\n"+rotor.run("abcdefghijklmnopqrstuvwxyz")+" "+rotor.pointa1+" "+rotor.pointa2+" "+rotor.pointa3+"\n");
}
void set(){
rotor = new Rotor(myTextFieldRotor1.getText(),myTextFieldRotor2.getText(),myTextFieldRotor3.getText());
String keyStr1 = myTextFieldKey1.getText();
int key1 = Integer.parseInt(keyStr1);
String keyStr2 = myTextFieldKey2.getText();
int key2 = Integer.parseInt(keyStr2);
String keyStr3 = myTextFieldKey3.getText();
int key3 = Integer.parseInt(keyStr3);
rotor.pointa_set(key1, key2, key3);
}
public void init(){
myTextField = new MyTextField(this, "aaaaaaaaaaa");
myTextFieldRotor1 = new MyTextFieldRotor1(this, "bdfhjlcprtxvznyeiwgakmusqo");
myTextFieldRotor2 = new MyTextFieldRotor2(this, "ajdksiruxblhwtmcqgznpyfvoe");
myTextFieldRotor3 = new MyTextFieldRotor3(this, "ekmflgdqvzntowyhxuspaibrcj");
myTextFieldKey1 = new MyTextFieldKey1(this, "K");
myTextFieldKey2 = new MyTextFieldKey2(this, "E");
myTextFieldKey3 = new MyTextFieldKey3(this, "Y");
new MyGoButton(this);
new MySetButton(this);
myTextArea = new MyTextArea(this);
myTextArea2 = new MyTextArea2(this);
}
public static void main(String[] args) {
Browser br = new Browser();
br.init();
Frame fr = new Frame();
fr.add("Center", br);
fr.setSize(400,300);
fr.setVisible(true);
}
}
//Browser.html
<html>
<title> Browser
</title>
<body>
<applet code = "Browser.class" width=700 height=450>
</applet>
</body>
</html>
//java/linenumber
//699行目からEnigma in GUI のコードがあります。(new!!)
//このページはwikiのソースコードモードで作られています.
//プログラム以外の部分はコメントアウトするようにしましょう.
//プログラムの改変は,(直接書き換えず)そのプログラムの後に付け足すのがいいでしょう.
//結局ローター改変できなかったため、お茶をにごします。
//この前練習がてら作ったスタキュレーのコード(Slide)とカエサル暗号のコード(Caesar)です。
//RSAとかのアルゴリズム(?)もwikiに書いておきますね。
/*
・スタキュレー
スライドする数をxとすると、平文の文字列から0,x,2x,…1,x+1,2x+1,…2,x+2,2x+2,…という順番に文字を取っていく。
ex) x=3でabcdefghi→adgbehcfi
*/
//MayFes.javaで保存、実行すればテストできる。
import java.io.*;
abstract class Code{
int ln; //length of plaintxt
String plaintxt; //平文
abstract String encode(); //暗号化
abstract String decode(String str); //復号化 引数は暗号文
}
class Slide extends Code{
int num; //how many steps does it slide
Slide(int x, String str){
num = x;
ln = str.length();
plaintxt = str;
}
public String encode(){
StringBuffer ciphertxt = new StringBuffer();
int pointa = 0;
int start = 0;
int times = 0;
while(times != ln){
times ++;
if(pointa >= ln){
start++;
pointa = start;
}
ciphertxt.append(plaintxt.charAt(pointa));
pointa = num+pointa;
}
return ciphertxt.toString().toUpperCase();
}
public String decode(String str){
String ciphertxt = str;
int ln_deco = str.length();
char[] plaintxt_array = new char[ln_deco];
StringBuffer plaintxt2 = new StringBuffer();
int pointa = 0;
int start = 0;
int times = 0;
while(times != ln_deco){
if(pointa >= ln_deco){
start++;
pointa = start;
}
plaintxt_array[pointa] = ciphertxt.charAt(times);
pointa = pointa+num;
times ++;
}
for(int i = 0; i < ln_deco; i++){
plaintxt2.append(plaintxt_array[i]);
}
return plaintxt2.toString().toLowerCase();
}
}
class Caesar extends Code{
int sn; //slide number
Caesar(int k, String str){
sn = k;
ln = str.length();
plaintxt = str;
}
String encode(){
StringBuffer ciphertxt = new StringBuffer(); //暗号文
for(int i = 0; i < ln; i++){
ciphertxt.append((char)((int)'a'+((int)plaintxt.charAt(i)-(int)'a'+sn)%26));
}
return ciphertxt.toString().toUpperCase();
}
String decode(String str){
String ciphertxt = str.toLowerCase();
int ln_deco = str.length();
StringBuffer plaintxt2 = new StringBuffer();
for(int i = 0; i < ln_deco; i++){
plaintxt2.append((char)((int)'z'-((int)'z'-(int)ciphertxt.charAt(i)+sn)%26));
}
return plaintxt2.toString();
}
}
public class MayFes{
public static void main(String[] args) throws IOException{
//下の2行はコマプロで入力した文をstrにするためのコード
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
Slide c = new Slide(3, str);
Caesar cc = new Caesar(5, str);
System.out.println(c.encode());
System.out.println(c.decode(c.encode()));
System.out.println(cc.encode());
System.out.println(cc.decode(cc.encode()));
}
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/////////////////////ENIGMA////////////////////////////
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/*
簡易説明(初期設定らへんについて 動かし方については[class Enigma]の前で説明)
メモリは6つ(使う文字もa~f)として説明する。
ローターは最初から3つ一気に定義しちゃう。一周したら次が1メモリ動くのが楽に作れるから。
ポインタ3つはそれぞれのローターにたいして一つずつ。
ポインタの位置はインスタンスを作る際に設定します。
ちょこちょこ末尾にでてくる1,2,3の数字はどのローターに対してのメソッドかを示しています。
[numbers]はいくつローターを通るといくつズレるのかを設定してある。
[Rotor]のインスタンスを作る際にローターの構造を設定する。
その際、アルファベットで設定。
たとえば、設定をbdecfaとしたら
a→b(+1) a→b
b→d(+2) b→c→d
c→e(+2) c→d→e
d→c(+5) d→e→f→a→b→c
e→f(+1) e→f
f→a(+1) f→a
なので、numbersには{1,2,2,5,1,1}が記憶される。
一回ローターが回ると、いくつズレるかが1つずつ下にいき、
a→ b(+1)
b→ c(+1)
c→ e(+2)
d→ f(+2)
e→ d(+5)
f→ a(+1)
という変換がされるようになっている。
[reflecter]は最初から定義済み。変えるときはめんどくさいけど一つずつ設定してください。(コピペしてもらえれば70行目らへん) (このページだと202行目)
ローターを通る時はめんどくさいので最初に[set_input]で文字を数字に変えて全部数字でやってます。[get_output]で最後に数字を文字にもどしています。
*/
class Rotor{
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[6];
int[] numbers2 = new int[6];
int[] numbers3 = new int[6];
int[] reflecter = new int[6];
int[] input;
int[] output;
String out;
int l; //平分の長さ
//////////////////////////////////////////////////////////////////////
//////////////////どれだけズレるのかを配列に記憶させる////////////////
//////////////////reflecterは今は最初から設定する/////////////////////
//////////////////////////////////////////////////////////////////////
Rotor(String str1,String str2, String str3){
for(int i =0; i < 6; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + 6;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + 6;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + 6;
//////////////////////////////////////////////////////////////
////////////////reflecterの設定はここ/////////////////////////
//////////////////////////////////////////////////////////////
reflecter[0] = 5;
reflecter[1] = 4;
reflecter[2] = 3;
reflecter[3] = 2;
reflecter[4] = 1;
reflecter[5] = 0;
}
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = x;
pointa2 = y;
pointa3 = z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
pointa1++;
if(pointa1 == 6){
pointa1 = 0;
pointa2++;
if(pointa2 == 6){
pointa2 = 0;
pointa3++;
if(pointa3 == 6){
pointa3 = 0;
}
}
}
}
////////////////////////////////////////////////////////////////
////////// goで行きの変換 backで帰りの変換////////////////////
//////////////////reflecterは今はすでに設定されているとする/////
////////////////////////////////////////////////////////////////
int go1(int x){
int y = x-pointa1;
if(y < 0) y = 6-(pointa1-x);
int z = x+numbers1[y];
if(z >= 6) z = z-6;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = 6-(pointa2-x);
int z = x+numbers2[y];
if(z >= 6) z = z-6;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = 6-(pointa3-x);
int z = x+numbers3[y];
if(z >= 6) z = z-6;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
///////////////////////////////////////////////////////////////
//////////ここまでで準備終了///////////////////////////////////
//////////以下文章が入ってきた動作/////////////////////////////
///////////////////////////////////////////////////////////////
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
pointa_forward();
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
void run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
System.out.println(out);
}
}
/*
簡易説明(どうやって動かすか)
だいたい下の通りですが、まずは[Rotor]のインスタンスを作ります。
その際に、ローターの設定を行ってください。(アルファベットの意味については冒頭の簡易説明参照)
ポインタはローターのインスタンスを作った際の初期設定では(0,0,0)になっています。
変えたいときは[pointa_set()]をつかってください。
pointa_set(1,2,3)とでもやれば
pointa1→1
pointa2→2
pointa3→3
とセットされます。
[pointa_reset()]で初期設定にも戻せます。
あとは[run(入力)]で出力がコマプロに出るようになっています。
[out]が出力のString形式になっています。
下で実際に動かした様子を見てみると、(実行してみてください)
fdcbea→cebcaf
が最初に実行されます。
手に入れたcebcafを入力しても
cebcaf→afeafd
となり最初の文字列が復元できません。
[pointa_reset()]でポインタをもとに戻して実行すると
cebcaf→fdcbea
となり今度はうまくいきます。
次にポインタを(3,4,2)にセットしてもう一度fdcbeaを入力してみましょう。
fdcbea→ebeefc
とさっきとは違う文字列が得られました。
もう一度ポインタを(3,4,2)にセットしなおして、ebeefcを入力すると
ebeefc→fdcbea
と復元できます。
*/
public class Enigma{
public static void main(String[] args){
Rotor r = new Rotor("fadecb","cadbef","ebdcfa");
r.run("fdcbea");
r.run("cebcaf");
r.pointa_reset();
r.run("cebcaf");
r.pointa_set(3,4,2);
r.run("fdcbea");
r.pointa_set(3,4,2);
r.run("ebeefc");
}
}
////////////////////////////////////Enigma ここまで
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/////////////////////ENIGMA ver1.1/////変更byうぇぶ////
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
//主な変更点 modの導入,26変数化へ
// pointa_setを変更 文字がa=0,b=2,…,z=25に対応するように.
// pointa_forwardを変更 アプレット版通りの挙動
// set_outputを変更 pointa_forwardを最初に実行する.
// run()を変更 平文->暗号文という出力に.
//今後の課題 Rotor1,Rotor2の繰り上がり条件の一般化 (pointa_forward)
class Rotor{
int mod = 26;
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[mod];
int[] numbers2 = new int[mod];
int[] numbers3 = new int[mod];
int[] reflecter = new int[mod];
int[] input;
int[] output;
String out;
int l; //平分の長さ
//////////////////////////////////////////////////////////////////////
//////////////////どれだけズレるのかを配列に記憶させる////////////////
//////////////////reflecterは今は最初から設定する/////////////////////
//////////////////////////////////////////////////////////////////////
Rotor(String str1,String str2, String str3){
for(int i =0; i < mod; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + mod;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + mod;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + mod;
//////////////////////////////////////////////////////////////
////////////////reflecterの設定はここ/////////////////////////
//////////////////////////////////////////////////////////////
//ReflecterBの設定
reflecter[0] = 24 ;
reflecter[1] = 17 ;
reflecter[2] = 20 ;
reflecter[3] = 7 ;
reflecter[4] = 16 ;
reflecter[5] = 18 ;
reflecter[6] = 11 ;
reflecter[7] = 3 ;
reflecter[8] = 15 ;
reflecter[9] = 23 ;
reflecter[10] = 13 ;
reflecter[11] = 6 ;
reflecter[12] = 14 ;
reflecter[13] = 10 ;
reflecter[14] = 12 ;
reflecter[15] = 8 ;
reflecter[16] = 4 ;
reflecter[17] = 1 ;
reflecter[18] = 5 ;
reflecter[19] = 25 ;
reflecter[20] = 2 ;
reflecter[21] = 22 ;
reflecter[22] = 21 ;
reflecter[23] = 9 ;
reflecter[24] = 0 ;
reflecter[25] = 19 ;
}
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = mod - x;
pointa2 = mod - y;
pointa3 = mod - z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
//RotorをRotorIII,RotorII,RotorIの順にセットした時のポインタの挙動(うぇぶ)
//アプレット版の挙動を再現している. Rotorを他の順にするときは22と4の数字を変える.
if(pointa2 == 22){ //RotorIIの繰り上がりの数22 (eの数字4,mod-4=22)
pointa2--;
pointa3--;
if(pointa3 < 0){
pointa3 = pointa3 + mod;
}
}
pointa1--;
if(pointa1 < 0){
pointa1 = pointa1 + mod;
}
if(pointa1 == 4){ //RotorIIIの繰り上がりの数22 (wの数字22,mod-22=4)
pointa2--;
if(pointa2 < 0){
pointa2 = pointa2 + mod;
}
}
}
////////////////////////////////////////////////////////////////
////////// goで行きの変換 backで帰りの変換////////////////////
//////////////////reflecterは今はすでに設定されているとする/////
////////////////////////////////////////////////////////////////
int go1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x+numbers1[y];
if(z >= mod) z = z-mod;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x+numbers2[y];
if(z >= mod) z = z-mod;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x+numbers3[y];
if(z >= mod) z = z-mod;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
///////////////////////////////////////////////////////////////
//////////ここまでで準備終了///////////////////////////////////
//////////以下文章が入ってきた動作/////////////////////////////
///////////////////////////////////////////////////////////////
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
pointa_forward();
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
void run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
System.out.println(str + " -> " +out);
}
}
/*
簡易説明(どうやって動かすか)
だいたい下の通りですが、まずは[Rotor]のインスタンスを作ります。
その際に、ローターの設定を行ってください。(アルファベットの意味については冒頭の簡易説明参照)
ポインタはローターのインスタンスを作った際の初期設定では(0,0,0)になっています。
変えたいときは[pointa_set()]をつかってください。
pointa_set(1,2,3)とでもやれば
pointa1→1
pointa2→2
pointa3→3
とセットされます。
[pointa_reset()]で初期設定にも戻せます。
あとは[run(入力)]で出力がコマプロに出るようになっています。
[out]が出力のString形式になっています。
下で実際に動かした様子を見てみると、(実行してみてください)
fdcbea→cebcaf
が最初に実行されます。
手に入れたcebcafを入力しても
cebcaf→afeafd
となり最初の文字列が復元できません。
[pointa_reset()]でポインタをもとに戻して実行すると
cebcaf→fdcbea
となり今度はうまくいきます。
次にポインタを(3,4,2)にセットしてもう一度fdcbeaを入力してみましょう。
fdcbea→ebeefc
とさっきとは違う文字列が得られました。
もう一度ポインタを(3,4,2)にセットしなおして、ebeefcを入力すると
ebeefc→fdcbea
と復元できます。
*/
public class Enigma{
public static void main(String[] args){
Rotor r = new Rotor("bdfhjlcprtxvznyeiwgakmusqo",
"ajdksiruxblhwtmcqgznpyfvoe",
"ekmflgdqvzntowyhxuspaibrcj");
//Rotorの設定 上から順にRotorIII,RotorII,RotorI
//pointa初期設定x=23,d=3,h=7
r.pointa_set(23,3,7);
r.run("abc");
r.pointa_set(23,3,7);
r.run("azy");
r.pointa_set(23,3,7);
r.run("aaa");
r.pointa_set(23,3,7);
r.run("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
r.pointa_set(23,3,7);
r.run("kqg");
}
}
/////////////////////////////////Enigma ver1.1 ここまで
//////////////////ver.1.2用。なんかうまくいかない。
int[] srebmun1 = new int[mod]; //numbersの逆関数的なもの
int[] srebmun2 = new int[mod];
int[] srebmun3 = new int[mod];
srebmun1[(int)str1.charAt(i)-(int)'a'] = mod - numbers1[i];
srebmun2[(int)str2.charAt(i)-(int)'a'] = mod - numbers2[i];
srebmun3[(int)str3.charAt(i)-(int)'a'] = mod - numbers3[i];
int bback1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x + srebmun1[y];
if(z >= mod) z = z-mod;
return z;
}
int bback2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x + srebmun2[y];
if(z >= mod) z = z-mod;
return z;
}
int bback3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x + srebmun3[y];
if(z >= mod) z = z-mod;
return z;
}
}
////////////////////////////////////////////////////////////////////
/////////////////////////ENIGMA IN GUI//////////////////////////////
////////////////////////////////////////////////////////////////////
/*
使い方説明。
正味な話、くみっしゅの完コピなので頑張ってコードを読めばわかるんじゃないかな?
とか思わないでください。
今回は見やすくしようだなんて微塵も思っていないので。
とりあえず、下に
Browser.java
Browser.html
のプログラムを置いてあるのでそのままコピペしてください。
あとはコマプロで
javac Browser.java
appletviewer Browser.html
と打てばおしまい!!簡単!!って覚えてるか。
んで、変にhtmlのところとかでサイズを変えなければ
・aaaaaaaaaaaって書いてある四角が1つ
・アルファベットがごちゃごちゃしている四角が3つ
・K,E,Yって書いてある四角が1つずつ
・GoボタンとSetボタン
・でっかい四角が2つ
以上のものがあるはず。
・aaaaaaaaaaaaaって書いてあるところ
ここ平文を入れる。
注意点としては、平文に小文字アルファベット以外のものが入っているとうんともすんともいわない。
ピリオド、空白ですらダメ。どうにかしたほうがいいかも。
・アルファベットがごちゃごちゃしているところ
この子たちはローターの構造を表している。前回のEnigmaでRotorの構造を決定するときの文字列をそのまま入れてくれればOK。
特に注意点はないし、この状況でネットのapplet版とそろっているらしい。うぇぶがやってくれました。
・K,E,Yって書いてあるところ
ここにpointa1,2,3の番号を入れる。
applet版のデフォルトは(23,3,7)らしい。
注意点として、文字は入れないこと。いちいちKEYの文字は消さないと動かないよ。(気に入らなかったら変えますね)
・Goボタン
これをおして暗号化
・Setボタン
ローターやポインタの位置を変えたいのなら書きこんだあとにSetボタンを押してくれないと意味がないからね。
Setしてあげてね。
・でっかい四角
ここに出力される。
*/
///////////////////////////////////////////////////////
///////////////////全体の流れ(一番大事)//////////////
///////////////////////////////////////////////////////
/*
まずは必ずポインタ(K,E,Yの部分)の数字を決めてセットすること。それをしないと動かない。
そして平文には小文字アルファベットしか入れない。
Goボタンを押せば、左の四角に暗号化された文が、右には最後の文字を変換したときの変換規則とポインタの位置がでてきます。
Setボタンを押さない限り、ポインタの位置はずれ続けます。
同じ文字列でも2回連続でGoボタンおしたら暗号文は変わるってことね。
そのかわり暗号文をコピペして、ポインタのところは変えずにSet→Goとすればもとの平文がよみがえるはずです。(あたりまえだけど)
例外処理は僕の手に負えないところなので、基本的に予想外のことが起きたらうんともすんともいわなくなりますが、
なにかミスを見っけたら教えてください。
直しといてくれると泣いて喜んじゃうよ?
*/
//Browser.java
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
class Rotor{
int mod = 26;
int pointa1, pointa2, pointa3; //pointa = 0~25
int[] numbers1 = new int[mod];
int[] numbers2 = new int[mod];
int[] numbers3 = new int[mod];
int[] reflecter = new int[mod];
int[] input;
int[] output;
String out;
int l; //平分の長さ
Rotor(String str1,String str2, String str3){
for(int i =0; i < mod; i++){
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
numbers1[i] = (int)str1.charAt(i) - (int)'a'-i;
if(numbers1[i] < 0) numbers1[i] = numbers1[i] + mod;
numbers2[i] = (int)str2.charAt(i) - (int)'a'-i;
if(numbers2[i] < 0) numbers2[i] = numbers2[i] + mod;
numbers3[i] = (int)str3.charAt(i) - (int)'a'-i;
if(numbers3[i] < 0) numbers3[i] = numbers3[i] + mod;
}
reflecter[0] = 24 ;
reflecter[1] = 17 ;
reflecter[2] = 20 ;
reflecter[3] = 7 ;
reflecter[4] = 16 ;
reflecter[5] = 18 ;
reflecter[6] = 11 ;
reflecter[7] = 3 ;
reflecter[8] = 15 ;
reflecter[9] = 23 ;
reflecter[10] = 13 ;
reflecter[11] = 6 ;
reflecter[12] = 14 ;
reflecter[13] = 10 ;
reflecter[14] = 12 ;
reflecter[15] = 8 ;
reflecter[16] = 4 ;
reflecter[17] = 1 ;
reflecter[18] = 5 ;
reflecter[19] = 25 ;
reflecter[20] = 2 ;
reflecter[21] = 22 ;
reflecter[22] = 21 ;
reflecter[23] = 9 ;
reflecter[24] = 0 ;
reflecter[25] = 19 ;
}
void pointa_set(int x, int y, int z){ //ポインタをセットする
pointa1 = mod - x;
pointa2 = mod - y;
pointa3 = mod - z;
}
void pointa_reset(){ //ポインタを0に戻す
pointa1 = 0;
pointa2 = 0;
pointa3 = 0;
}
void pointa_forward(){ //ポインタを1つ進める
if(pointa2 == 22){ //RotorIIの繰り上がりの数22 (eの数字4,mod-4=22)
pointa2--;
pointa3--;
if(pointa3 < 0){
pointa3 = pointa3 + mod;
}
}
pointa1--;
if(pointa1 < 0){
pointa1 = pointa1 + mod;
}
if(pointa1 == 4){ //RotorIIIの繰り上がりの数22 (wの数字22,mod-22=4)
pointa2--;
if(pointa2 < 0){
pointa2 = pointa2 + mod;
}
}
}
int go1(int x){
int y = x-pointa1;
if(y < 0) y = mod-(pointa1-x);
int z = x+numbers1[y];
if(z >= mod) z = z-mod;
return z;
}
int back1(int x){
int i = 0;
while(go1(i) != x){
i++;
}
return i;
}
int go2(int x){
int y = x-pointa2;
if(y < 0) y = mod-(pointa2-x);
int z = x+numbers2[y];
if(z >= mod) z = z-mod;
return z;
}
int back2(int x){
int i = 0;
while(go2(i) != x){
i++;
}
return i;
}
int go3(int x){
int y = x-pointa3;
if(y < 0) y = mod-(pointa3-x);
int z = x+numbers3[y];
if(z >= mod) z = z-mod;
return z;
}
int back3(int x){
int i = 0;
while(go3(i) != x){
i++;
}
return i;
}
int reflect(int x){
return reflecter[x];
}
void set_input(String str){ //平文を入力 文字を数字に変えておく
l = str.length();
input = new int[l];
for(int i = 0; i < str.length(); i++){
input[i] = (int)str.charAt(i)-(int)'a';
}
}
void set_output(){ //ローターに通す 1→2→3→りふれくたー→3→2→1の順番
output = new int[l];
for(int i = 0; i < l; i++){
pointa_forward();
int x = go3(go2(go1(input[i])));
int y = back1(back2(back3(reflect(x))));
output[i] = y;
}
}
void get_output(){ //出力を数字から文字に戻す
StringBuffer str = new StringBuffer();
for(int i = 0; i < l; i++){
char x = (char)((int)'a'+output[i]);
str.append(x);
}
out = str.toString();
}
String run(String str){ //入力から出力までを一つにまとめる
set_input(str);
set_output();
get_output();
return out;
}
}
/////////////////////////////////Enigma ver1.1 ここまで
class MyTextField extends TextField{
MyTextField(Browser br,String str){
super(str,50);
br.add(this);
}
}
class MyTextFieldRotor1 extends TextField{
MyTextFieldRotor1(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldRotor2 extends TextField{
MyTextFieldRotor2(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldRotor3 extends TextField{
MyTextFieldRotor3(Browser br, String str){
super(str,26);
br.add(this);
}
}
class MyTextFieldKey1 extends TextField{
MyTextFieldKey1(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextFieldKey2 extends TextField{
MyTextFieldKey2(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextFieldKey3 extends TextField{
MyTextFieldKey3(Browser br, String str){
super(str,1);
br.add(this);
}
}
class MyTextArea extends TextArea{
MyTextArea(Browser br){
super("",20,40,TextArea.SCROLLBARS_BOTH);
setEditable(true);
setFont(new Font("Helvetica",Font.PLAIN,12));
br.add(this);
}
}
class MyTextArea2 extends TextArea{
MyTextArea2(Browser br){
super("",20,35,TextArea.SCROLLBARS_BOTH);
setEditable(true);
setFont(new Font("Helvetica",Font.PLAIN,12));
br.add(this);
}
}
abstract class MyButton extends Button implements ActionListener{
final Browser browser;
MyButton(Browser br,String name){
super(name);
browser = br;
browser.add(this);
addActionListener(this);
}
abstract public void actionPerformed(ActionEvent e);
}
class MyGoButton extends MyButton{
MyGoButton(Browser br){
super(br,"Go");
}
public void actionPerformed(ActionEvent e){
browser.go();
}
}
class MySetButton extends MyButton{
MySetButton(Browser br){
super(br, "Set");
}
public void actionPerformed(ActionEvent e){
browser.set();
}
}
public class Browser extends Applet {
MyTextArea myTextArea;
MyTextArea2 myTextArea2;
MyTextField myTextField;
MyTextFieldKey1 myTextFieldKey1;
MyTextFieldKey2 myTextFieldKey2;
MyTextFieldKey3 myTextFieldKey3;
MyTextFieldRotor1 myTextFieldRotor1;
MyTextFieldRotor2 myTextFieldRotor2;
MyTextFieldRotor3 myTextFieldRotor3;
Rotor rotor;
void go(){
myTextArea.append(rotor.run(myTextField.getText())+"\n\n");
myTextArea2.append("abcdefghijklmnopqrstuvwxyz k e y\n"+rotor.run("abcdefghijklmnopqrstuvwxyz")+" "+rotor.pointa1+" "+rotor.pointa2+" "+rotor.pointa3+"\n");
}
void set(){
rotor = new Rotor(myTextFieldRotor1.getText(),myTextFieldRotor2.getText(),myTextFieldRotor3.getText());
String keyStr1 = myTextFieldKey1.getText();
int key1 = Integer.parseInt(keyStr1);
String keyStr2 = myTextFieldKey2.getText();
int key2 = Integer.parseInt(keyStr2);
String keyStr3 = myTextFieldKey3.getText();
int key3 = Integer.parseInt(keyStr3);
rotor.pointa_set(key1, key2, key3);
}
public void init(){
myTextField = new MyTextField(this, "aaaaaaaaaaa");
myTextFieldRotor1 = new MyTextFieldRotor1(this, "bdfhjlcprtxvznyeiwgakmusqo");
myTextFieldRotor2 = new MyTextFieldRotor2(this, "ajdksiruxblhwtmcqgznpyfvoe");
myTextFieldRotor3 = new MyTextFieldRotor3(this, "ekmflgdqvzntowyhxuspaibrcj");
myTextFieldKey1 = new MyTextFieldKey1(this, "K");
myTextFieldKey2 = new MyTextFieldKey2(this, "E");
myTextFieldKey3 = new MyTextFieldKey3(this, "Y");
new MyGoButton(this);
new MySetButton(this);
myTextArea = new MyTextArea(this);
myTextArea2 = new MyTextArea2(this);
}
public static void main(String[] args) {
Browser br = new Browser();
br.init();
Frame fr = new Frame();
fr.add("Center", br);
fr.setSize(400,300);
fr.setVisible(true);
}
}
//Browser.html
<html>
<title> Browser
</title>
<body>
<applet code = "Browser.class" width=700 height=450>
</applet>
</body>
</html>
表示オプション
横に並べて表示:
変化行の前後のみ表示: