【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版》

广告
将在 10 秒后关闭
bannerAds