Midori64 加解密的实现(Java代码)

根据论文Midori: A Block Cipher for Low Energy 我们通过Java实现了其加解密操作,想要了解midori算法的同学可以看我的另外一篇博文。–汪书北

(博文地址:https://blog.csdn.net/weixin_41596280/article/details/83240077)
(论文地址:https://link.springer.com/chapter/10.1007%2F978-3-662-48800-3_17

所有感悟都在代码中,欢迎大家与我一起分享改进。

package midori;

import java.util.ArrayList;
import java.util.Arrays;

import Sboxtools.getSbox;

public class midori64 {

	private static int[][] ai = {
			{ 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1 },
			{ 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
			{ 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1 },
			{ 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 },
			{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1 },
			{ 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 },
			{ 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 },
			{ 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
			{ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0 },
			{ 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1 },
			{ 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0 },
			{ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0 },
			{ 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0 },
			{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0 },
			{ 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
			{ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 },
			{ 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0 },
			{ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0 }

	};
	private static int[] Sbox = { 0xc, 0xa, 0xd, 3, 0xe, 0xb, 0xf, 7, 8, 9, 1,
			5, 0, 2, 4, 6 };

	// private static int[] key = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	private static int[] key = { 6, 8, 7, 0xd, 0xe, 0xd, 3, 0xb, 3, 0xc, 8, 5,
			0xb, 3, 0xf, 0x3, 5, 0xb, 1, 0, 0, 9, 8, 6, 3, 0xe, 2, 0xa, 8, 0xc,
			0xb, 0xf };

	public static void main(String[] args) {
		// 论文中给出的例子
		// Plaintext : 42c20fd3b586879e
		// Key : 687ded3b3c85b3f35b1009863e2a8cbf
		// Ciphertext : 66bcdc6270d901cd
		// 加密过程
		int[] x = { 4, 2, 0xc, 2, 0, 0xf, 0xd, 3, 0xb, 5, 8, 6, 8, 7, 9, 0xe }, r;
		r = midori64_en(x, key);
		System.out.println(Arrays.toString(r));
		// 解密过程
		int[] y = { 6, 6, 11, 12, 13, 12, 6, 2, 7, 0, 13, 9, 0, 1, 12, 13 };
		r = midori64_de(y, key);
		System.out.println(Arrays.toString(r));

	}

	/**
	 * 加密方法
	 * 
	 * @param x
	 *            输入
	 * @param key
	 * @return
	 */

	public static int[] midori64_en(int[] x, int[] key) {

		// 1.检查输入的x和key长度是否符合要求
		if (x.length != 16 || key.length != 32) {
			System.out
					.println("输入的x和key长度不符合要求!" + x.length + "-" + key.length);
			return null;
		}
		// 输入的x和key每个值必须都小于16, 如果大于16,就做模运算
		for (int i = 0; i < key.length; i++) {
			key[i] = key[i] % 16;
			if (i < 16) {
				x[i] = x[i] % 16;
			}
		}

		// 2.生成轮密钥
		int[][] roundKey = roundKeyGeneration(key);

		// 3.按照步骤加密
		// 3.1 S ← KeyAdd(X,WK)
		x = keyAdd(x, roundKey[15]);

		// 3.2 循环15轮
		for (int i = 0; i < 15; i++) {

			// S ← SubCell(S)
			x = subCell(x);
			// S ← ShuffleCell(S)
			x = shuffleCell(x);

			// S ← MixColumn(S)
			x = mixColumn(x);

			// S ← KeyAdd(S,RKi)
			x = keyAdd(x, roundKey[i]);// 注意roundKey是一个二维数组,roundKey[i]指的是第i行

		}
		// S ← SubCell(S)
		x = subCell(x);
		// Y ← KeyAdd(S,WK)
		x = keyAdd(x, roundKey[15]);
		return x;

	}

	/**
	 * 解密方法
	 * 
	 * @param y
	 *            输入
	 * @param key
	 * @return
	 */

	public static int[] midori64_de(int[] y, int[] key) {

		// 1.生成轮密钥
		int[][] roundKey = roundKeyGeneration(key);

		// 2.按照步骤解密
		// 2.1 S ← KeyAdd(Y,WK)
		y = keyAdd(y, roundKey[15]);
		// 2.2 循环15轮
		for (int i = 14; i >= 0; i--) {
			// S ← SubCell(S)
			y = subCell(y);
			// S ← KeyAdd(S,RKi)
			y = keyAdd(y, roundKey[i]);// 注意roundKey是一个二维数组,roundKey[i]指的是第i行

			// S ← MixColumn(S)
			y = mixColumn(y);
			// S ← InvShuffleCell(S)
			y = shuffleCell_1(y);

		}
		// S ← SubCell(S)
		y = subCell(y);
		// Y ← KeyAdd(S,WK)
		y = keyAdd(y, roundKey[15]);
		return y;

	}

	/**
	 * 生成轮密钥
	 * 
	 * @param key
	 *            密钥数组长度为32位,每个元素的值不大于15
	 * @return
	 */
	public static int[][] roundKeyGeneration(int[] key) {
		// 密钥规则:WK = K0 ⊕ K1 和 RKi = K(i mod 2)⊕ αi
		int[][] roundkey = new int[16][16];// 总共16轮,每轮密钥长度为16×4
		int klen = key.length;// 密钥数组长度
		int[] k0 = new int[16];
		int[] k1 = new int[16];
		// 获得WK 我们将WK的值放在二维数组中的最后一组哦 roundkey[15][i]
		for (int i = 0; i < klen / 2; i++) {// 取得密钥的前一半和后一半进行异或
			roundkey[15][i] = key[i] ^ key[i + klen / 2];// 每一个4bit值进行异或
			k0[i] = key[i];// 为k0赋值
			k1[i] = key[i + klen / 2];// 为k1赋值
		}

		// RKi = K(i mod 2)⊕ αi的计算
		for (int i = 0; i < 15; i++) {
			if (i % 2 == 0) {
				for (int j = 0; j < 16; j++) {
					roundkey[i][j] = k0[j] ^ ai[i][j];
				}

			} else if (i % 2 == 1) {
				for (int j = 0; j < 16; j++) {
					roundkey[i][j] = k1[j] ^ ai[i][j];
				}
			}

		}

		return roundkey;

	}

	/**
	 * 轮密钥加
	 * 
	 * @param x
	 *            输入数组
	 * @param k
	 *            密钥数组
	 * @return
	 */

	static int[] keyAdd(int[] x, int[] k) {
		int[] r = new int[16];
		for (int i = 0; i < 16; i++) {
			r[i] = x[i] ^ k[i];
		}
		return r;

	}

	/**
	 * 半字节代替
	 * 
	 * @param x
	 * @return
	 */
	static int[] subCell(int[] x) {
		int[] r = new int[16];
		for (int i = 0; i < Sbox.length; i++) {
			r[i] = Sbox[x[i]];
		}

		return r;
	}

	/**
	 * 行移位
	 * 
	 * @param x
	 * @return
	 */

	static int[] position = { 0, 10, 5, 15, 14, 4, 11, 1, 9, 3, 12, 6, 7, 13,
			2, 8 };

	static int[] shuffleCell(int[] x) {
		int[] r = new int[16];
		for (int i = 0; i < position.length; i++) {
			r[i] = x[position[i]];
		}

		return r;

	}

	/**
	 * 行移位 逆向
	 * 
	 * @param x
	 * @return
	 */

	static int[] position_1 = { 0, 7, 14, 9, 5, 2, 11, 12, 15, 8, 1, 6, 10, 13,
			4, 3 };

	static int[] shuffleCell_1(int[] x) {
		int[] r = new int[16];
		for (int i = 0; i < position_1.length; i++) {
			r[i] = x[position_1[i]];
		}

		return r;

	}

	/**
	 * 列混淆
	 * 
	 * @param x
	 * @return
	 */
	static int[] M = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };

	static int[] mixColumn(int[] x) {

		return matrixMult(M, x);
	}

	/**
	 * 两个矩阵相乘
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	static int[] matrixMult(int[] x, int[] y) {
		int[] r = new int[16];
		int temp;
		for (int i = 0; i < 16; i++) {
			temp = 0;
			for (int j = 0; j < 4; j++) {
				temp ^= x[4 * (i / 4) + j] * y[j + 4 * (i % 4)];
			}

			r[4 * (i % 4) + i / 4] = temp;

		}

		return r;

	}

}

猜你喜欢

转载自blog.csdn.net/weixin_41596280/article/details/88853056