大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
1、SM4算法简介
中国国家密码管理局于2006年1月6日发布第7号公告,将我国无线局域网产品的加密算法确定为SM4算法(原SMS4)。这是国内官方公布的第一个商用密码算法。
SM4分组密码算法是一个迭代分钟密码算法,由加解密算法和密钥扩展算法组成,SM4分组密码算法采用非平衡Feistel结构,明文分组长度为128bit,密钥长度为128bit。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密算法与加密算法的结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
加密首先要生成一套加密密钥,从用户处获得一个128bit的初始密钥并将其分为4组,之后对应的与系统参数FK进行异或运算,之后将产生的结果进行32轮迭代(包含:与固定参数CKi的异或运算、S盒替换、循环移位、移位之后的异或运算)最后生成32个轮子密钥,每个轮子密钥32bit,分别供每一轮运算中使用。
SM4算法的S盒替换与AES算法中的S盒替换类似:输入的前4位为行号,后4位为列号,行列交叉点处的数值即为替换结果。
SM4算法的加密流程为首先从用户处获得128bit的明文,之后将明文分为4组,每组32bit,之后将其进过轮函数F变换,一共进行32轮次,最后再经过反序变换之后的到加密后的结果。
SM4中的合成置换T是一个可逆置换,由非线性变换 和线性变换L复合而成。其中是由4个并行的S盒代替构成。为国定的8bit输入和8bit输出的代替。并且非线性变换是线性变换L的输入。
在SM4算法中S盒是固定不变的,而且系统参数CKi的取值也是不变的,系统参数一共有32个。
SM4的解密过程与加密过程结构完全相同,不同的仅仅是轮秘钥的使用顺序。加密轮密钥的使用顺序是,
而解密时密钥的使用顺序为加密时候的反序:
2、密码算法程序各模块详细设计
2.1 核心模块主要实现算法的流程
图1 SM4加密算法流程示意图
图2 SM4密钥扩展算法流程图
3、核心模块的函数说明和实现方式
3.1 轮密钥扩展算法核心代码
private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) {
int r, mid;
int[] x = new int[4];
int[] tmp = new int[4];
for (int i = 0; i < 4; i++) {
//使用下面的语句,实现对初始秘钥的分组(分为4组)
tmp[0] = Key[0 + 4 * i] & 0xFF;
tmp[1] = Key[1 + 4 * i] & 0xff;
tmp[2] = Key[2 + 4 * i] & 0xff;
tmp[3] = Key[3 + 4 * i] & 0xff;
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
x[i]=Key[0+4*i]<<24|Key[1+4*i]<<16|Key[2+4*i]<<8|Key[3+4*i];
}
/*******************************
* 系统参数FK的取值(取值固定)
*******************************/
x[0] ^= 0xa3b1bac6; //Key (0)与FK(0)异或运算之后的结果
x[1] ^= 0x56aa3350; //Key (1)与FK(1)异或运算之后的结果
x[2] ^= 0x677d9197; //Key (2)与FK(2)异或运算之后的结果
x[3] ^= 0xb27022dc; //Key (3)与FK(3)异或运算之后的结果
for (r = 0; r < 32; r += 4) {
//实现K(r+1)、K(r+2)、K(r+3)与CK(i)的异或运算操作
mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
//调用函数ByteSub实现非线性变换
mid = ByteSub(mid);
// 将变换之后的结果与自身的循环左移13、23位做异或运算
rk[r + 0] = x[0] ^= L2(mid); // rk0=K4
//下面的操作与以上雷同
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
mid = ByteSub(mid);
rk[r + 1] = x[1] ^= L2(mid); // rk1=K5
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
mid = ByteSub(mid);
rk[r + 2] = x[2] ^= L2(mid); // rk2=K6
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
mid = ByteSub(mid);
rk[r + 3] = x[3] ^= L2(mid); // rk3=K7
}
//CryptFlag为1时进行加密操作,CryptFlag为0时进行解密操作
// 解密时轮密钥使用顺序:rk31,rk30,...,rk0,下面主要实现对上面生成的轮子秘钥的逆序作用
if (CryptFlag == DECRYPT) {
for (r = 0; r < 16; r++) {
mid = rk[r];
rk[r] = rk[31 - r];
rk[31 - r] = mid;
}
}
}
SM4的轮密钥扩展算法严格的按照SM4轮密钥扩展算法流程图来进行操作和变换演示。
3.2 SM4加密算法核心代码
/**********************************
* 功能说明:SM4加密算法实现
* 参数说明:Input 输入的明文
* Output 待输出的密文
* rk 轮密钥
***********************************/
void SMS4Crypt(byte[] Input, byte[] Output, int[] rk) {
int r, mid;
int[] x = new int[4];
int[] tmp = new int[4];
for (int i = 0; i < 4; i++) {
tmp[0] = Input[0 + 4 * i] & 0xff;
tmp[1] = Input[1 + 4 * i] & 0xff;
tmp[2] = Input[2 + 4 * i] & 0xff;
tmp[3] = Input[3 + 4 * i] & 0xff;
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
x[i]=(Input[0+4*i]<<24|Input[1+4*i]<<16|Input[2+4*i]<<8|Input[3+4*i]);}
/**************************************
* 进行32轮的加密变换操作
**************************************/
for (r = 0; r < 32; r += 4) {
mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0];
//X(r+1)、X(r+2)、X(r+3)与轮密钥进行异或运算
mid = ByteSub(mid); //S盒置换
x[0] = x[0] ^ L1(mid); // x4 //线性变换L
//下面的内容操作类似
mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1];
mid = ByteSub(mid);
x[1] = x[1] ^ L1(mid); // x5
mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2];
mid = ByteSub(mid);
x[2] = x[2] ^ L1(mid); // x6
mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3];
mid = ByteSub(mid);
x[3] = x[3] ^ L1(mid); // x7
}
// Reverse
/*******************
* 反序变换
*******************/
for (int j = 0; j < 16; j += 4) {
Output[j ] = (byte) (x[3 - j / 4] >>> 24 & 0xFF);
Output[j + 1] = (byte) (x[3 - j / 4] >>> 16 & 0xFF);
Output[j + 2] = (byte) (x[3 - j / 4] >>> 8 & 0xFF);
Output[j + 3] = (byte) (x[3 - j / 4] & 0xFF);
}
}
3.3 SM4解密算法核心代码
SM4的解密算法与加密算法类似,唯一不同之处就是使用的轮子密钥的顺序不同,SM4解密使用的轮子密钥与加密使用的轮子密钥正好顺序相反。在编码过程之中通过一个标志性数据——CryptFlag来确定是产生加密轮子密钥还是解密轮子密钥,当CryptFlag为1时进行加密操作,CryptFlag为0时进行解密操作。
4、程序测试
4.1 程序测试过程
在此次实验过程中为了简洁实现对编码的验证,采用直接在程序中加入代加密明文进行加密的方式,中间自动转换为16进制数据类型:
在控制台显示待加密明文与加密密钥以及加密轮密钥:
显示加密过程与加密结果:
将加密后的密文用于解密,验证程序的正确性:
解密轮密钥:
解密结果:
经过验证核实,表示正确无误,程序正确!
之后显示多分组加密结果的显示:
5、参考文献
[1] 张仕斌,万武南,张金全,孙宣东 《应用密码学》 西安电子科技大学出版社,2009.12
[2] 张健等 《密码学原理及应用技术》 清华大学出版,2011.08
[3] 国内一些技术博客
[4] 中国知网上的一些论文
[5] java帮助文档
源代码下载:https://download.csdn.net/download/fly_hps/10724893
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185639.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...