【Java】实施FaceTel网络
【概要】
DES是一种常见的密钥加密方式,它使用了一个称为费斯噩尔网络的结构。
简单来说,DES是使用了一个称为轮函数的函数和异或运算的加密方式。
DES规定了输入明文为64位,密钥长度为56位等规定,但是由于本次只是为了尝试实现费斯噩尔网络,所以排除了这样的限制。
[参考] 在维基百科上对Feistel结构的解释
以下是所列代码,已经上传到GitHub的以下链接中。
feistelNetwork
请点击以下链接查看。
package main;
import common.AbstractEncryption;
import encryption.Decryption;
import encryption.Encryption;
public class Main {
// ラウンド回数
public static int ROUND_EXEC_TIME = 3;
// ラウンド関数で使用する秘密鍵
// ラウンド関数はビットシフト演算をしているため、8よりも小さい数を指定しなければ暗号化ができない
// 攻撃者に解読されないようにするため、この鍵は秘密にしなければならない
private static int[] SECRET_KEY = {2, 3, 6};
public static void main(String[] args) {
// 秘密データ
String secretData = "testcase";
AbstractEncryption encryption = new Encryption();
AbstractEncryption decryption = new Decryption();
// 暗号化
String encryptionData = encryption.execEncryption(secretData, SECRET_KEY);
// 復号化
String deryptionData = decryption.execEncryption(encryptionData, SECRET_KEY);
System.out.println("暗号化データ:" + encryptionData);
System.out.println("復号化データ:" + deryptionData);
}
}
package common;
import main.Main;
/**
* 暗号化と復号化の両方を受け持つクラス
* @author nobu
*
*/
public abstract class AbstractEncryption {
/**
* 暗号化と復号化を実行する
* @param secretData 秘密データ
* @param key 秘密鍵
*/
public String execEncryption(String secretData, int key[]) {
String left = secretData.substring(0, secretData.length() / 2);
String right = secretData.substring(secretData.length() / 2, secretData.length());
// 左側の文字列データ、暗号化されたデータを入れるための変数
byte leftArray[][];
// 左側の文字は秘密データの文字数が偶数、奇数の場合を考慮している
if (secretData.length() % 2 == 0) {
leftArray = new byte[Main.ROUND_EXEC_TIME + 1][left.length()];
} else {
leftArray = new byte[Main.ROUND_EXEC_TIME + 1][left.length() + 1];
}
// 右側の文字列データ、暗号化されたデータを入れるための変数
byte rightArray[][] = new byte[Main.ROUND_EXEC_TIME + 1][right.length()];
// 入力値の初期化
for (int i = 0; i < left.length(); i++) {
leftArray[0][i] = (byte) left.charAt(i);
}
for (int i = 0; i < right.length(); i++) {
rightArray[0][i] = (byte) right.charAt(i);
}
// 暗号化, 復号化
for (int i = 0; i < Main.ROUND_EXEC_TIME; i++) {
for (int j = 0; j < right.length(); j++) {
rightArray[i + 1][j] = encryption(leftArray[i][j], rightArray[i][j], key, i);
leftArray[i + 1][j] = rightArray[i][j];
}
// 最終ラウンドでは、左右を交換しないため、既に交換済みのデータを元に戻す
if (i == Main.ROUND_EXEC_TIME - 1) {
byte tmp[];
tmp = leftArray[i + 1];
leftArray[i + 1] = rightArray[i + 1];
rightArray[i + 1] = tmp;
}
}
String returnData = "";
for (int i = 0; i < right.length(); i++) {
returnData = returnData + String.valueOf((char) leftArray[Main.ROUND_EXEC_TIME][i]);
}
for (int i = 0; i < right.length(); i++) {
returnData = returnData + String.valueOf((char) rightArray[Main.ROUND_EXEC_TIME][i]);
}
return returnData;
}
/**
* 暗号化
* @param left 左側のデータ
* @param right 右側のデータ
* @param key 秘密鍵
* @param roundNumber
* @return 暗号化の結果
*/
abstract protected byte encryption(byte left, byte right, int[] key, int roundNumber);
/**
* ラウンド関数、秘密鍵で指定された値だけ右シフトする
* @param right 右側データ
* @param key 秘密鍵
* @return ラウンド関数の結果
*/
protected byte roundFunction(byte right, int key) {
return (byte) (right << key);
}
}
package encryption;
import common.AbstractEncryption;
/**
* 暗号化クラス
* @author nobu
*
*/
public class Encryption extends AbstractEncryption {
@Override
protected byte encryption(byte left, byte right, int[] key, int roundNumber) {
return (byte) (left ^ roundFunction(right, key[roundNumber]));
}
}
package encryption;
import common.AbstractEncryption;
import main.Main;
/**
* 復号化クラス
* @author nobu
*
*/
public class Decryption extends AbstractEncryption {
@Override
protected byte encryption(byte left, byte right, int[] key, int roundNumber) {
return (byte) (left ^ roundFunction(right, key[Main.ROUND_EXEC_TIME - roundNumber - 1]));
}
}
【执行结果】这是“testcase”字符串加密和解密后的结果。※加密数据已经乱码了。
暗号化データ:8ᄀᅠᆪiヒe
復号化データ:testcase
###【参考书籍】
《密码技术入门 第3版》