根据论文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;
}
}