目 录
第一章需求分析
1.1软件功能需求
1.2平台需求
1.3人员分工
第二章概要设计
2.1 软件开发平台
2.2 软件基本流程
2.3 UML图
第三章 程序详细设计
3.1 程序接口设计
3.2 SM2、3算法设计
3.3 SM4算法设计
3.4 UI设计

第四章 调试分析

4.1 出现问题及解决方案
第五章 结果测试
5.1 SM2\3测试结果
5.2 SM4 测试结果
5.3 软件整体测试

第六章总结与感想

6.1 总结与感想
6.2 未来展望

第七章附录
7.1 各部分代码及其注释

第一章 需求分析
1.1 软件需求分析

(1)要求使用SM4算法对明文进行加密。输入明文和任意长度密钥(仅包含数字和大小写英文),得到加密后密文。
(2)SM4算法进行解密,从SM2、3部分获得解密后的密钥,从用户获得密文,输出解密后明文。
(3)SM2、3算法从用户处得到SM4算法加密密钥,并用公钥对其进行加密,将加密后SM4密钥进行分发。
(4)用户将得到的加密后密钥传送给SM2、3算法,其进行解密后将SM4密钥传送给SM4算法。

1.2 平台需求

本软件基于安卓 6.0及其以后版本。

1.3 人员分工

负责部分:SM4算法
负责部分:SM2、3算法
负责部分:安卓平台主要框架及UI

第二章 概要设计
2.1 软件开发平台

本软件开发平台为Android Studio 4.1.1,Java 1.8.0_271,Java SDK

2.2 软件基本流程

2.3 UML图

(1)加密部分

在这里插入图片描述
(2)解密部分
在这里插入图片描述

第三章程序详细设计
3.1 程序接口设计
(1)SM4
a)public Encrypt(String plaintext, String MK)
以字符串形式输入明文和密钥,同时将生成的密文以字符串形式输出。
b)public Decrypt(String C, String MK)
以字符串形式输入密文和密钥,同时将生成的明文以字符串形式输出。
(2)SM2\3
a)public String KeyEncrypt(String pkey,ECPoint publicKey)
以字符串形式输入SM4对称密钥、以椭圆曲线上点形式输入SM2公钥,同时将生成的SM4对称密钥对应密文以字符串形式输出。
a)b)public String KeyDecrypt(String ckey,BigInteger privKey)
以字符串形式输入SM4对称密钥对应密文、以大整数形式输入SM2私钥,同时将生成的SM4对称密钥对应明文以字符串形式输出。
(3)UI和主程序框架
a)private void cfm_enk_key()
获取用户输入的密钥,并使用SM2对其进行加密,以便传输;解密与其类似,使用SM2对传输密钥进行解密,以便SM4的解密。
b)private void cfm_enc_p()
获取用户输入的明文,使用SM4对其进行加密,其中密钥为用户输入的密钥;解密与其类似,对用户输入的密文进行解密。
c)

3.2 SM2、3算法设计
(1)SM2原理:
(a)整体框架:
E为有限域Fp上的一条椭圆曲线,G为椭圆曲线上的基点,n为椭圆曲线的阶。安全性的依据是P=dG,通过d计算P点是容易的,但是通过P点计算d是困难的。因此,d为私钥,P点(Xp,Yp)为公钥。
(b)加密算法:
输入:长度为klen的比特串M, 公钥PB
输出:SM2结构密文比特串C
算法:
1) 产生随机数k, k的值从1到n-1;
2) 计算椭圆曲线点C1=[k]G=(x1,y1), 将C1转换成比特串;
3) 验证公钥PB, 计算S=[h] PB,如果S是无穷远点,出错退出;
4) 计算(x2,y2)=[k] PB
5) 计算t=KDF(x2||y2, klen), KDF是密钥派生函数,如果t是全0比特串,返回第1)步。
6) 计算C2=M⊕t
7) 计算C3=Hash(x2||M||y2)
8) 输出密文C=C1||C3||C2, C1和C3的长度是固定的,C1是64字节,C3是32字节,很方便C从中提取C1,C3和C2。
PS:7)中的Hash所用的就是SM3;KDF即密钥派生函数,具体步骤如下图所示。
在这里插入图片描述

(c)解密算法:

输入:SM2结构密文比特串C, 私钥dB
输出:明文M’
算法:
1) 从密文比特串C=C1||C3||C2中取出C1, 将C1转换成椭圆曲线上的点;
2) 验证C1, 计算S=[h] C1,如果S是无穷远点,出错退出;
3) 计算(x2,y2)=[dB] C1
4) 计算t=KDF(x2||y2, klen), KDF是密钥派生函数,如果t是全0比特串,出错退出。
5) 从C=C1||C3||C2中取出C2,计算M’= C2⊕t。
6) 计算u=Hash(x2||M’||y2),比较u是否与C3相等,不相等则退出。
7) 输出明文M’。
(d)证明:
根据加密算法有(x2,y2)=[k]PB、C1=[k]G;根据解密算法有(x2,y2)=[dB]C1;根据公钥私钥之间的关系有PB=[dB]G。所以[k]PB=[k][dB]G=[dB][k]G=[dB]C1。所以加密中(x2,y2)与解密中(x2,y2)相等,故可以成功解密。
(2)SM3原理:
(a)整体迭代过程
在这里插入图片描述

(b)消息扩展

在这里插入图片描述

(c)压缩函数

在这里插入图片描述

(d)生成散列值

在这里插入图片描述

(3)对SM4对称密钥加密流程:
在这里插入图片描述

(4)对SM4对称密钥密文解密流程:

在这里插入图片描述

3.3 SM4算法设计
(1)加密流程

在这里插入图片描述

(2)解密流程

在这里插入图片描述

(3)SM4原理
SM4算法是一种分组密码算法。其分组长度为128bit,密钥长度也为128bit。加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。SM4算法加/解密算法的结构相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。SM4算法的整体结构如图所示:

在这里插入图片描述

(4) 参数产生
A)字节由8位2进制数表示,字由32位2进制数表示;
B)S盒为固定的8bit输入和输出置换;
C)加密密钥长度为128bit,表示为MK=(MK0,MK1,MK2,MK3),其中MKi (i=0,1,2,3)为字。
D)轮密钥表示为rki(i=0,1,2…,31)为字。FK=(FK0,FK1,FK2,FK3)为系统参数,CK=(CK0,CK1,…,CK31)为固定参数,都为字。

(5)轮函数
整体的加密函数为:
在这里插入图片描述

其中T为一个合成置换,由非线性变换和线性变换复合而成。
非线性变换由4个平行的S盒构成,S盒的数据均采用16进制。
线性变换公式如下,其中B为非线性变换得到的字
在这里插入图片描述

(6)密钥扩展
已知加密密钥,系统参数FK=(FK0,FK1,FK2,FK3),固定参数CK=(CK0,CK1,…,CK31).
rki为轮密钥,轮密钥由加密密钥生成。
首先,
在这里插入图片描述

然后对i=0,1,2,…,31:
在这里插入图片描述

改变换与加密中的T变换基本相同,只是将其中的线性变换改为:
在这里插入图片描述
,由于系统参数个固定参数是已知的,轮密钥即可求得。

3.4 UI设计
(1)页面流程
在这里插入图片描述

(2)页面设计
在这里插入图片描述

第四章 调试分析

4.1 出现问题及解决方案
a)进行前端设计时,没有在AndroidManifest.xml里面注册Activity,导致实体机调试时闪退,注册之后即正常运行。
b)前端对SM2进行正确性调试时,没有注意密钥的格式,随意输入密钥导致程序退回上一个页面,回到代码中观察发现是密钥是固定65个字节的数据,按要求输入后可正常运行。
c)前端与后端SM2、SM4合并代码时出现编码错误,所有的中文都不能够被识别,最终将所有文件都改成UTF-8方式并对SM4中的处理进行修改后可正确加解密。
d)在SM4加密过程中,由于java不支持无符号类型,读取的中文字符显示为负数,在加解密时出现乱码问题。解决方案:对读入的中文字符进行哈希映射,将其范围映射至0~256范围内,在进行加密。解密后得到的值同样进行逆映射后得到明文。

第五章 结果测试
5.1 SM2\3测试结果
(1)加密测试
加密数据:中国地质大学 (武汉) 信息安全 张沛豪 密码学实验
得到密文:04A1D424971BC92671B2314CE8B0A302D5A3E8FDD4ED6319D83227FAF56397909
A307E76EA69099D507E86AE8290EC3F22554ADFA9F384EFC06167A66AAFC02B5C41A417F911286F90A18011F36A6393870570FA4D0BDEF508F0419337675FD4E1E3954A34C830309F346BF2415EDD45A86F22851FBCDBBA2325C95A15E0910EDF84B468E27421D53D9BAE49A11721C487C5
(2)解密测试
解密密文: 04A1D424971BC92671B2314CE8B0A302D5A3E8FDD4ED6319D83227FAF56397909
A307E76EA69099D507E86AE8290EC3F22554ADFA9F384EFC06167A66AAFC02B5C41A417F911286F90A18011F36A6393870570FA4D0BDEF508F0419337675FD4E1E3954A34C830309F346BF2415EDD45A86F22851FBCDBBA2325C95A15E0910EDF84B468E27421D53D9BAE49A11721C487C5
得到明文:中国地质大学 (武汉) 信息安全 张沛豪 密码学实验
(3)运行效果

在这里插入图片描述

5.2 SM4 测试结果
(1)加密测试
加密数据:中国地质大学 (武汉) 信息安全 朱靖宇 密码学实验
得到密文:50 237 238 112 121 73 110 11 176 80 59 105 124 194 184 217 233 76 191 240 175 12 196 16 47 185 102 207 247 13 206 46 118 202 143 182 139 229 159 89 90 150 29 80 244 207 147 170 236 126 21 13 5 111 222 252 53 221 66 9 48 222 11 77 116 179 216 4 72 113 54 215 43 152 178 43 231 221 103 13
(2)解密测试
解密密文:50 237 238 112 121 73 110 11 176 80 59 105 124 194 184 217 233 76 191 240 175 12 196 16 47 185 102 207 247 13 206 46 118 202 143 182 139 229 159 89 90 150 29 80 244 207 147 170 236 126 21 13 5 111 222 252 53 221 66 9 48 222 11 77 116 179 216 4 72 113 54 215 43 152 178 43 231 221 103 13
得到明文:中国地质大学 (武汉) 信息安全 朱靖宇 密码学实验
(3)截图

在这里插入图片描述

5.3 软件整体测试
(1) 开始界面
在这里插入图片描述

(2)加密部分
A)输入密钥并使用SM2、3进行加密
在这里插入图片描述

这里输入的密钥为zjy000408
产生的加密后密钥为:
044DFAEB431908E06BFB138F40DDAA4554ACAE94973F9DC09A869C2BEE284AAAA26C9D58AA97E4911E67D2D36F9711B6B54AFE677D670C337545D5349D1697762854F45E3DD174E379441CD1D2E3A948E42705387C14606284D56B2DE39FCFC9DFBBA5,04E79FB0F847761ABDC8BF2A417D93CDFE92A07A2352C0391C804E903582ED286D8E8DA2F1EA26AA64B9E320EEF6F1AE088EF57C49BACAEEDEA5D807F78276468921CAF534905B6A19AE45455FA284E44457EFCCE4A92CC14C1FA812DC200361141002,04EF9E9FF025EF176AD34425702EC93CACE9DF6C8EB29291C43984FC042133ADCA0E51E858571F23BDE39E1DF0406CBD7A7221DBF5AFA6F261A961ADC8868F62E9BE5BD81F2B98D3ABE3C2B9448149BC09AA220EE5F92C2D55F917C229C8224DFA6F16,049ECF7320DA5BDC7BF29842EAD4244D07B969D20B39453F28E2760C44CD64E533B420EA88E15BD2405833DA798B20DE8FF36503FD339149021B2C60E8E1AA80780E7F058F28ACAD1C70D64C8A0A30B3E058EF61174102634E1C6E895F758A2C1730D006

B)使用SM4对明文进行加密
在这里插入图片描述

这里得到的密文为:
147 198 250 65 112 112 124 210 103 145 123 167 95 48 179 130 56 237 183 146 170 143 180 1 66 77 126 184 113 133 231 189 39 155 156 31 52 135 79 253 28 32 7 117 91 237 54 139
(3)解密部分
A)登录界面
在这里插入图片描述

B) 输入收到密钥

在这里插入图片描述
C)进行解密
在这里插入图片描述

第六章 总结与感想

6.1 总结与感想
(1)李笑嫣:
在这次课程设计中,我主要负责的部分是安卓前端开发和整个代码框架的构建。刚开始接触安卓开始时,我感到又有趣又陌生,但是当我学着写下一个一个的按钮和输入框,解决了一个又一个问题之后,我逐渐熟练,快速完成了这部分的开发。
除了前端开发,我也学习了项目中用到的SM2、SM4算法,对这些算法的学习能够帮助我更加专业的对UI界面进行调整,使页面服务于功能。
(2)朱靖宇:
在本次课程设计中,我负责的是SM4算法部分,在该部分,我对SM4算法的原理以及应用进行了进一步学习,同时,自学了java编程方式,并且提高了字节的动手能力。
由于是第一次进行团队项目开发,所以在刚开始的时候对于醒目的具体需求以及各部分的接口存在一定程度的交流问题,并造成了一定程度的影响,比如对于中文加解密支持和明密文输入输出格式等一开始存在一定分歧,但是随着项目的推进,这些问题一一得到解决,并着实有效地锻炼了我们的合作能力和团队精神。
通过本次课程设计,让我更加深刻地了解了课本知识,和对以往知识的疏忽得以补充,充分锻炼了我的动手能力和代码能力,并对新的知识进行了学习。同时在与团队成员的合作过程中,团队合作能力得到了有效的锻炼。
6.2 未来展望

第七章 附录

7.1 各部分代码及其注释

(1)SM4部分
A)Encrypt类
import java.util.ArrayList;

public class Encrypt {
private String plaintext; //明文
private String[] MK; //轮密钥
public Encrypt(){

}

public Encrypt(String plaintext, String MK){
	Tools tool=new Tools();
	this.plaintext = plaintext;
	this.MK = tool.KeyGen(MK);
}


public String encryptEntrance(){
	KeyExpansion ke = new KeyExpansion();
	String[] rk = ke.wheelKey(MK); 
	Tools tool = new Tools();
	plaintext = tool.fillNumber(plaintext);//填充明文
	String C=new String();
	//System.out.printf("plaintext的长度为:%d\n",tool.length(plaintext));
	//System.out.printf("plaintext的内容为:%s\n",plaintext);
	byte[] plaintext_ = plaintext.getBytes();
	ArrayList<int[]> res = new ArrayList<int[]>();
	for(int n=0;n<tool.length(plaintext)/16;n++){
		ArrayList<int[]> t = new ArrayList<int[]>();
		ArrayList<int[]> t_ = new ArrayList<int[]>();
		ArrayList<int[]> tres = new ArrayList<int[]>();
		byte[] s = new byte[16];
		for (int i=n*16;i<(n+1)*16;i++) //截取明文
		{
			s[i%16]=plaintext_[i];
		}
		//System.out.printf("截取字符为%s\n",s);
		t_ = tool.ByteToList(s);
		for (int i=0;i<4;i++)
		{
			int[] tt=t_.get(i);
			for (int j=0;j<4;j++)
			{
				tt[j]=(tt[j]-127)*-1;
				//System.out.printf("%d ",tt[j]);
			}
			t.add(tt);
			//System.out.print('\n');
		}
		tres = encryptProcess(t.get(0),t.get(1),t.get(2),t.get(3),rk);
		res.add(tres.get(0));
		res.add(tres.get(1));
		res.add(tres.get(2));
		res.add(tres.get(3));
	}
	for (int i=0;i<res.size();i++)
	{
		int[] cc=res.get(i);
		//System.out.println(cc.length+' ');
		for (int j=0;j<cc.length;j++)
		{
			C+=Integer.toString(cc[j]);
			C+=' ';
		}
	}
	//System.out.println(C);
	return C;
}

//具体加密过程
ArrayList<int[]> encryptProcess(int[] n0, int[] n1, int[] n2,int[] n3, String[] rk){
if(n0.length!=4||n1.length!=4||n2.length!=4||n3.length!=4){
System.out.println(“encrypt输入错误”);
return null;
}
Tools tool = new Tools();
WheelFunction wf = new WheelFunction();
ArrayList<int[]> x = new ArrayList<int[]>();
x.add(n0);
x.add(n1);
x.add(n2);
x.add(n3);
//进行轮加密
for(int i=0;i<32;i++){
int[] trk = tool.HexToIntArray(rk[i]);
x.add(wf.F(x.get(i), x.get(i+1), x.get(i+2), x.get(i+3), trk));
}
ArrayList<int[]> res = new ArrayList<int[]>();
res.add(x.get(35));
res.add(x.get(34));
res.add(x.get(33));
res.add(x.get(32));
return res;
}

public String getPlaintext() {
	return plaintext;
}

public void setPlaintext(String plaintext) {
	this.plaintext = plaintext;
}

public String[] getMK() {
	return MK;
}

public void setMK(String[] mK) {
	MK = mK;
}

}
B)KeyExpansion类
public class KeyExpansion {
private String FK0 = “a3b1bac6”;
private String FK1 = “56aa3350”;
private String FK2 = “677d9197”;
private String FK3 = “b27022dc”;
private String[] CK = {“00070e15”,“1c232a31”,“383f464d”,“545b6269”,
“70777e85”,“8c939aa1”,“a8afb6bd”,“c4cbd2d9”,
“e0e7eef5”,“fc030a11”,“181f262d”,“343b4249”,
“50575e65”,“6c737a81”,“888f969d”,“a4abb2b9”,
“c0c7ced5”,“dce3eaf1”,“f8ff060d”,“141b2229”,
“30373e45”,“4c535a61”,“686f767d”,“848b9299”,
“a0a7aeb5”,“bcc3cad1”,“d8dfe6ed”,“f4fb0209”,
“10171e25”,“2c333a41”,“484f565d”,“646b7279”
};
String[] wheelKey(String[] MK){
Tools tool = new Tools();
BasicComponents bc = new BasicComponents();
String[] k = new String[36];
String[] rk = new String[32];
String tmk = tool.HexToStr(tool.HexToIntArray(MK[0]));
String tfk = tool.HexToStr(tool.HexToIntArray(FK0));
k[0] = tool.XOR(tmk, tfk);
tmk = tool.HexToStr(tool.HexToIntArray(MK[1]));
tfk = tool.HexToStr(tool.HexToIntArray(FK1));
k[1] = tool.XOR(tmk, tfk);
tmk = tool.HexToStr(tool.HexToIntArray(MK[2]));
tfk = tool.HexToStr(tool.HexToIntArray(FK2));
k[2] = tool.XOR(tmk, tfk);
tmk = tool.HexToStr(tool.HexToIntArray(MK[3]));
tfk = tool.HexToStr(tool.HexToIntArray(FK3));
k[3] = tool.XOR(tmk, tfk);
for(int i=0;i<32;i++){
String ts = “”;
ts = tool.XOR(k[i+1], k[i+2]);
ts = tool.XOR(ts, k[i+3]);
ts = tool.XOR(ts, tool.HexToStr(tool.HexToIntArray(CK[i])));
ts = tool.HexToStr(bc.T_1Change(tool.BinToIntArray(ts)));
ts = tool.XOR(k[i], ts);
k[i+4] = ts;
rk[i] = tool.IntArrayToStr(tool.BinToIntArray(ts));
}
return rk;
}
}
C)WheelFunction类
public class WheelFunction {

int[] F(int[] tn0, int[] tn1, int[] tn2, int[] tn3, int[] rk){
	/*if(tn0.length!=4||tn1.length!=4||tn2.length!=4||tn3.length!=4||rk.length!=4){
		System.out.println("�ֺ����������");
		return null;
	}*/
	Tools tool = new Tools();
	BasicComponents bc = new BasicComponents();
	String str = "";
	str = tool.XOR(tool.HexToStr(tn1), tool.HexToStr(tn2));
	str = tool.XOR(str, tool.HexToStr(tn3));
	str = tool.XOR(str, tool.HexToStr(rk));
	int[] res = new int[4];
	res = tool.BinToIntArray(str);
	res = bc.TChange(res);
	str = tool.HexToStr(res);
	str = tool.XOR(tool.HexToStr(tn0), str);
	res = tool.BinToIntArray(str);
	return res;
}

}
D)BasicComponents类
public class BasicComponents {
private int[][] SBOX={{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}
};

int S_Box(int n){
	int j = n%16;  
	int i = (n-j)/16;  
	int result = SBOX[i][j];
	return result;
}


int[] PIChange(int[] n1){
	int[] res = new int[4];
	for(int i=0;i<4;i++){
		res[i] = S_Box(n1[i]);
	}
	return res;
}


int[] LChange(int[] n1){
	Tools tool = new Tools();
	String res = "";
	String B = tool.HexToStr(n1);
	res = tool.XOR(B, tool.loopleftmove(B, 2));
	res = tool.XOR(res, tool.loopleftmove(B, 10));
	res = tool.XOR(res, tool.loopleftmove(B, 18));
	res = tool.XOR(res, tool.loopleftmove(B, 24));
	int[] result = tool.BinToIntArray(res);
	return result;
}


int[] TChange(int[] n1){
	int[] result = new int[4];
	result = PIChange(n1);
	result = LChange(result);
	return result;
}


int[] L_1Change(int[] n1){
	Tools tool = new Tools();
	String res = "";
	String B = tool.HexToStr(n1);
	res = tool.XOR(B, tool.loopleftmove(B, 13));
	res = tool.XOR(res, tool.loopleftmove(B, 23));
	int[] result = tool.BinToIntArray(res);
	return result;
}


int[] T_1Change(int[] n1){
	int[] result = new int[4];
	result = PIChange(n1);
	result = L_1Change(result);
	return result;
}	

}
E)Decrypt类
import java.util.ArrayList;

public class Decrypt {
private ArrayList<int[]> ciphertext; //密文
private String[] MK; //密钥

public Decrypt(String C, String MK){
	ArrayList<int[]> c=new ArrayList<int[]>();
	//int k=0;
	Tools tool = new Tools();
	int count=0;
	String ch=new String();
	int[] cc=new int[4];
	for (int i=0;i<C.length();i++)
	{
		if(count==4)
		{
			count=0;
			int[] temp = new int[4];
			for (int k=0;k<4;k++)
			{
				temp[k]=cc[k];
			}
			c.add(temp);
	//		System.out.printf("\n%d\n",c.size());
		}
		char cha=C.charAt(i);
		if (cha==' ')
		{
			cc[count]=(int)Integer.valueOf(ch);
		//	System.out.printf("%d ",cc[count]);
			ch="";
			count=count+1;
			continue;
		}
		ch+=cha;		
	}
	c.add(cc);

	this.ciphertext = c;
	this.MK = tool.KeyGen(MK);
}

//�������
public String decryptEntrance(){
	KeyExpansion ke = new KeyExpansion();
	String[] rk = ke.wheelKey(MK);  //计算轮密钥
	Tools tool = new Tools();
	ArrayList<byte[]> b = new ArrayList<byte[]>(); 
	String res = ""; 
	for(int n=0;n<ciphertext.size()/4;n++){
		ArrayList<int[]> tal = new ArrayList<int[]>();
		tal = decryptProcess(ciphertext.get(n*4),ciphertext.get(n*4+1),ciphertext.get(n*4+2),ciphertext.get(n*4+3),rk);
		byte[] Byte= tool.ListToByte(tal);
		for (int j=0;j<16;j++)
		{
			Byte[j]=(byte) (-1*Byte[j]+127);
		}
		b.add(Byte);
	}
	byte[] Byte = new byte[b.size()*16];
	for (int i = 0; i < b.size(); i++)
	{
		for (int j = 0; j < 16; j++)
		{
			Byte[i*16+j]=b.get(i)[j];
		}
	}
	res=new String(Byte);
	res = tool.restore(res);
	return res;
}



ArrayList<int[]> decryptProcess(int[] n0, int[] n1, int[] n2,int[] n3, String[] rk){
	if(n0.length!=4||n1.length!=4||n2.length!=4||n3.length!=4){
		System.out.println("decrypt输入错误");
		return null;
	}
	Tools tool = new Tools();
	WheelFunction wf = new WheelFunction();
	ArrayList<int[]> x = new ArrayList<int[]>();
	x.add(n0);
	x.add(n1);
	x.add(n2);
	x.add(n3);
	for(int i=0;i<32;i++){
		int[] trk = tool.HexToIntArray(rk[31-i]);
		x.add(wf.F(x.get(i), x.get(i+1), x.get(i+2), x.get(i+3), trk));
	}
	ArrayList<int[]> res = new ArrayList<int[]>();
	res.add(x.get(35));
	res.add(x.get(34));
	res.add(x.get(33));
	res.add(x.get(32));
	return res;
}


public void setCiphertext(ArrayList<int[]> ciphertext) {
	this.ciphertext = ciphertext;
}

public ArrayList<int[]> getCiphertext() {
	return ciphertext;
}

public String[] getMK() {
	return MK;
}

public void setMK(String[] mK) {
	MK = mK;
}

}
F)Tools类
import java.util.ArrayList;

public class Tools {
//将0到255之间int类型的数转换为8位二进制的String类型表示
public String IntToBin(int i){
/if(i<0||i>255){
System.out.println(“IntToStr输入错误”);
return null;
}
/
String str = “”;
for(int n=7;n>=0;n–){
int t = 1<<n; //1<<n等于2的n次方
if(i>=t){
str = str + “1”;
i = i-t;
}else{
str = str + “0”;
}
}
return str;
}

//把8位String类型的二进制表示转换为int类型的数
public int BinToInt(String str){
	/*if(str.length()!=8){
		System.out.println("BinToInt输入错误");
		return 0;
	}*/
	int result = 0;
	for(int i=0;i<8;i++){
		if(str.charAt(i)=='1'){
			result += 1<<(7-i);
		}
	}
	return result;
}

//把一个包含4个两位十六进制数的数组转换成32位(二进制表示)的字符串
public String HexToStr(int[] n1){
	String res = "";
	for(int i=0;i<n1.length;i++){
		res += IntToBin(n1[i]);
	}
	return res;
}

//将一个32位的比特串转换成一个int数组
public int[] BinToIntArray(String str){
	/*if(str.length()!=32){
		System.out.println("BinToIntArray输入错误");
		return null;
	}*/
	int[] result = new int[4];
	result[0] = BinToInt(str.substring(0, 8));
	result[1] = BinToInt(str.substring(8, 16));
	result[2] = BinToInt(str.substring(16, 24));
	result[3] = BinToInt(str.substring(24, 32));
	return result;
}

//循环左移n位方法
public String loopleftmove(String str,int n){
	/*if(n>32){
		return null;
	}*/
	String s1,s2,res;
	s1 = str.substring(0, n);
	s2 = str.substring(n,32);
	res = s2 + s1;
	return res;
}

//String类型的异或运算,相同为零,不同为一
public String XOR(String str1,String str2){
	/*if(str1.length()!=str2.length()){
		System.out.println("XOR方法输入错误,参数长度不同");
		return null;
	}*/
	String res = "";
	for(int i=0;i<this.length(str1);i++){
		if(str1.charAt(i)==str2.charAt(i)){
			res += "0";
		}else{
			res += "1";
		}
	}
	return res;
}	

public int[] XOR(int[] str1,int[] str2){
	/*if(str1.length()!=str2.length()){
		System.out.println("XOR方法输入错误,参数长度不同");
		return null;
	}*/
	int[] res =new int[str1.length];
	for(int i=0;i<str1.length;i++){
		if(str1[i]==str2[i]){
			res[i] = 0;
		}else{
			res[i] = 0;
		}
	}
	return res;
}	

//将String表示的4个两位十六进制数转换成一个int数组
public int[] HexToIntArray(String str){
	/*if(str.length()!=8){
		System.out.println("HexToIntArray输入错误");
		return null;
	}*/
	int[] res = new int[4];
	for(int i=0;i<4;i++){
		int sum = 0;
		if(str.charAt(2*i)>=48&&str.charAt(2*i)<=57){
			sum += (str.charAt(2*i)-48)*16;
		}else{
			sum += (str.charAt(2*i)-87)*16;
		}
		if(str.charAt(2*i+1)>=48&&str.charAt(2*i+1)<=57){
			sum += str.charAt(2*i+1)-48;
		}else{
			sum += str.charAt(2*i+1)-87;
		}
		res[i] = sum;
	}
	return res;
}

//将一个长度为4的int数组装换成String类型的十六进制表示
public String IntArrayToStr(int[] n1){
	/*if(n1.length!=4){
		System.out.println("IntArrayToStr输入错误");
		return null;
	}*/
	String res = "";
	for(int i=0;i<4;i++){
		res += IntToHex(n1[i]);
	}
	return res;
}

//将一个int数转换成一个两位的十六进制数
public String IntToHex(int i){
	String res = "";
	//第一位数是n,第二位是变换后的i
	int n=15;
	for(;n>=0;n--){
		if(n*16<=i){
			i = i-n*16;
			break;
		}
	}
	if(n>9){
		res = res + (char)(n+87);
	}else{
		res = res + n;
	}
	if(i>9){
		res = res + (char)(i+87);
	}else{
		res = res + i;
	}
	return res;
}

//若str不能整除16则用" "补齐位数
public String fillNumber(String str){
	int m = this.length(str)%16;
	if(m!=0){
		for(int n=0;n<(16-m%16);n++){
			str += " ";
		}
	}
	return str;
}

//若str末尾有" ",则将末尾的" "全都去掉
public String restore(String str){
	while(str.charAt(str.length()-1)==' '){
		str = str.substring(0, str.length()-1);
	}
	return str;
}

//将一个16位的字符串转化成4个长度为4的int数组存入ArrayList中
public ArrayList<int[]> StrToList(String str){
	/*if(this.length(str)!=16){
		System.out.println("StrToList输入错误");
		return null;
	}*/
	ArrayList<int[]> res = new ArrayList<int[]>();
	byte[] allstr = str.getBytes();
	//System.out.print(allstr.length);
	for(int n=0;n<4;n++){
		int[] t = new int[4];
		t[0] = allstr[n*4];
		t[1] = allstr[n*4+1];
		t[2] = allstr[n*4+2];
		t[3] = allstr[n*4+3];
		
		res.add(t);
	}
	return res;
}

public ArrayList<int[]> ByteToList(byte[] str){
	/*if(str.length!=16){
		System.out.println("StrToList输入错误");
		return null;
	}*/
	ArrayList<int[]> res = new ArrayList<int[]>();
	
	//System.out.print(allstr.length);
	for(int n=0;n<4;n++){
		int[] t = new int[4];
		t[0] = str[n*4];
		t[1] = str[n*4+1];
		t[2] = str[n*4+2];
		t[3] = str[n*4+3];
		
		res.add(t);
	}
	return res;
}
//将ArrayList中的数提出来转换为Byte数组
public byte[] ListToByte(ArrayList<int[]> al){
	byte[] res = new byte[16];
	for(int n=0;n<4;n++){
		int[] t = al.get(n);
		for(int i=0;i<4;i++){
			res[n*4+i] += t[i];
		}
	}
	return res;
}

//统计字符串长度 含中文
public int length(String value) {
    int valueLength = 0;
    String chinese = "[\u0391-\uFFE5]";
    /* 获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 */
    for (int i = 0; i < value.length(); i++) {
        /* 获取一个字符 */
        String temp = value.substring(i, i + 1);
        /* 判断是否为中文字符 */
        if (temp.matches(chinese)) {
            /* 中文字符长度为2 */
            valueLength += 3;
        } else {
            /* 其他字符长度为1 */
            valueLength += 1;
        }
    }
    return valueLength;
}

public String[] KeyGen(String s)
{
	int len=s.length();
	String c=new String();
	String[] C=new String[4];
	for (int i=0;i<len;i++)
	{
		char ch=s.charAt(i);
		if (ch>='0'&&ch<='9')
		{
			c+=ch;
			continue;
		}
		if (ch>='a'&&ch<='z')
		{
			ch=(char)((ch-'a')%16);
			if (0<=ch&&ch<=9)
				ch+='0';
			else
			{
				ch=(char)(ch-10+'a');
			}
			c+=ch;
		}
		if (ch>='A'&&ch<='F')
		{
			ch=(char)((ch-'A')%16);
			if (0<=ch&&ch<=9)
				ch+='0';
			else
			{
				ch=(char)(ch-10+'a');
			}
			c+=ch;
		}
	}
	int n=32/c.length()+1;
	for (int i=0;i<n;i++)
		c+=c;
	for (int i=0;i<4;i++)
		C[i]=c.substring(i*8,(i+1)*8);
	return C;
}

}
(2)SM2、3部分
A)SM2类实现
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;

import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;

/**

  • SM2公钥加密算法实现
    */
    public class SM2 {
    private static BigInteger n = new BigInteger(
    “FFFFFFFE” + “FFFFFFFF” + “FFFFFFFF” + “FFFFFFFF” + “7203DF6B” + “21C6052B” + “53BBF409” + “39D54123”, 16);
    private static BigInteger p = new BigInteger(
    “FFFFFFFE” + “FFFFFFFF” + “FFFFFFFF” + “FFFFFFFF” + “FFFFFFFF” + “00000000” + “FFFFFFFF” + “FFFFFFFF”, 16);
    private static BigInteger a = new BigInteger(
    “FFFFFFFE” + “FFFFFFFF” + “FFFFFFFF” + “FFFFFFFF” + “FFFFFFFF” + “00000000” + “FFFFFFFF” + “FFFFFFFC”, 16);
    private static BigInteger b = new BigInteger(
    “28E9FA9E” + “9D9F5E34” + “4D5A9E4B” + “CF6509A7” + “F39789F5” + “15AB8F92” + “DDBCBD41” + “4D940E93”, 16);
    private static BigInteger gx = new BigInteger(
    “32C4AE2C” + “1F198119” + “5F990446” + “6A39C994” + “8FE30BBF” + “F2660BE1” + “715A4589” + “334C74C7”, 16);
    private static BigInteger gy = new BigInteger(
    “BC3736A2” + “F4F6779C” + “59BDCEE3” + “6B692153” + “D0A9877C” + “C62A4740” + “02DF32E5” + “2139F0A0”, 16);
    private static ECDomainParameters ecc_bc_spec;
    private static int w = (int) Math.ceil(n.bitLength() * 1.0 / 2) - 1;
    private static BigInteger _2w = new BigInteger(“2”).pow(w);
    private static final int DIGEST_LENGTH = 32;

    private static SecureRandom random = new SecureRandom();
    private static ECCurve.Fp curve;
    private static ECPoint G;
    private boolean debug = false;

    public boolean isDebug() {
    return debug;
    }

    public void setDebug(boolean debug) {
    this.debug = debug;
    }

    /**

    • 以16进制打印字节数组
      */
      public static void printHexString(byte[] b) {
      for (int i = 0; i < b.length; i++) {
      String hex = Integer.toHexString(b[i] & 0xFF);
      if (hex.length() == 1) {
      hex = ‘0’ + hex;
      }
      System.out.print(hex.toUpperCase());
      }
      System.out.println();
      }

    public String getHexString(byte[] b) {
    String hex="";
    for (int i = 0; i < b.length; i++) {
    String tmp = Integer.toHexString(b[i] & 0xFF);
    if (tmp.length() == 1) {
    tmp = ‘0’ + tmp;
    }
    hex=hex+tmp;
    }
    hex=hex.toUpperCase();
    return hex;
    }

    public static byte[] toBytes(String str) {
    if(str == null || str.trim().equals("")) {
    return new byte[0];
    }

     byte[] bytes = new byte[str.length() / 2];
     for(int i = 0; i < str.length() / 2; i++) {
         String subStr = str.substring(i * 2, i * 2 + 2);
         bytes[i] = (byte) Integer.parseInt(subStr, 16);
     }
    
     return bytes;
    

    }

    /**

    • 随机数生成器
      */
      private static BigInteger random(BigInteger max) {

      BigInteger r = new BigInteger(256, random);
      // int count = 1;

      while (r.compareTo(max) >= 0) {
      r = new BigInteger(128, random);
      // count++;
      }

      // System.out.println("count: " + count);
      return r;
      }

    /**

    • 判断字节数组是否全0
      */
      private boolean allZero(byte[] buffer) {
      for (int i = 0; i < buffer.length; i++) {
      if (buffer[i] != 0)
      return false;
      }
      return true;
      }

    /**

    • 公钥加密
      */
      public byte[] encrypt(String input, ECPoint publicKey) {

      byte[] inputBuffer = input.getBytes();
      if (debug)
      printHexString(inputBuffer);

      byte[] C1Buffer;
      ECPoint kpb;
      byte[] t;
      do {
      /* 1 产生随机数k,k属于[1, n-1] */
      BigInteger k = random(n);
      if (debug) {
      System.out.print("k: ");
      printHexString(k.toByteArray());
      }

       /* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */
       ECPoint C1 = G.multiply(k);
       C1Buffer = C1.getEncoded(false);
       if (debug) {
       	System.out.print("C1: ");
       	printHexString(C1Buffer);
       }
      
       /*
        * 3 计算椭圆曲线点 S = [h]Pb
        */
       BigInteger h = ecc_bc_spec.getH();
       if (h != null) {
       	ECPoint S = publicKey.multiply(h);
       	if (S.isInfinity())
       		throw new IllegalStateException();
       }
      
       /* 4 计算 [k]PB = (x2, y2) */
       kpb = publicKey.multiply(k).normalize();
      
       /* 5 计算 t = KDF(x2||y2, klen) */
       byte[] kpbBytes = kpb.getEncoded(false);
       t = KDF(kpbBytes, inputBuffer.length);
       // DerivationFunction kdf = new KDF1BytesGenerator(new
       // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
       //
       // t = new byte[inputBuffer.length];
       // kdf.init(new ISO18033KDFParameters(kpbBytes));
       // kdf.generateBytes(t, 0, t.length);
      

      } while (allZero(t));

      /* 6 计算C2=M^t */
      byte[] C2 = new byte[inputBuffer.length];
      for (int i = 0; i < inputBuffer.length; i++) {
      C2[i] = (byte) (inputBuffer[i] ^ t[i]);
      }

      /* 7 计算C3 = Hash(x2 || M || y2) */
      byte[] C3 = sm3hash(kpb.getXCoord().toBigInteger().toByteArray(), inputBuffer,
      kpb.getYCoord().toBigInteger().toByteArray());

      /* 8 输出密文 C=C1 || C2 || C3 */

      byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];

      System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);
      System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);
      System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length, C3.length);

      if (debug) {
      System.out.print("密文: ");
      printHexString(encryptResult);
      }

      return encryptResult;
      }

    /**

    • 私钥解密
      */
      public String decrypt(byte[] encryptData, BigInteger privateKey) {

      if (debug)
      System.out.println("encryptData length: " + encryptData.length);

      byte[] C1Byte = new byte[65];
      System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);

      ECPoint C1 = curve.decodePoint(C1Byte).normalize();

      /*

      • 计算椭圆曲线点 S = [h]C1 是否为无穷点
        /
        BigInteger h = ecc_bc_spec.getH();
        if (h != null) {
        ECPoint S = C1.multiply(h);
        if (S.isInfinity())
        throw new IllegalStateException();
        }
        /
        计算[dB]C1 = (x2, y2) */
        ECPoint dBC1 = C1.multiply(privateKey).normalize();

      /* 计算t = KDF(x2 || y2, klen) */
      byte[] dBC1Bytes = dBC1.getEncoded(false);
      int klen = encryptData.length - 65 - DIGEST_LENGTH;
      byte[] t = KDF(dBC1Bytes, klen);
      // DerivationFunction kdf = new KDF1BytesGenerator(new
      // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
      // if (debug)
      // System.out.println("klen = " + klen);
      // kdf.init(new ISO18033KDFParameters(dBC1Bytes));
      // kdf.generateBytes(t, 0, t.length);

      if (allZero(t)) {
      System.err.println(“all zero”);
      throw new IllegalStateException();
      }

      /* 5 计算M’=C2^t */
      byte[] M = new byte[klen];
      for (int i = 0; i < M.length; i++) {
      M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);
      }
      if (debug)
      printHexString(M);

      /* 6 计算 u = Hash(x2 || M’ || y2) 判断 u == C3是否成立 */
      byte[] C3 = new byte[DIGEST_LENGTH];

      if (debug)
      try {
      System.out.println("M = " + new String(M, “GBK”));
      } catch (UnsupportedEncodingException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
      }

      System.arraycopy(encryptData, encryptData.length - DIGEST_LENGTH, C3, 0, DIGEST_LENGTH);
      byte[] u = sm3hash(dBC1.getXCoord().toBigInteger().toByteArray(), M,
      dBC1.getYCoord().toBigInteger().toByteArray());
      if (Arrays.equals(u, C3)) {
      if (debug)
      System.out.println(“解密成功”);
      try {
      return new String(M, “GBK”);
      } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      }
      return null;
      } else {
      if (debug) {
      System.out.print("u = ");
      printHexString(u);
      System.out.print("C3 = ");
      printHexString(C3);
      System.err.println(“解密验证失败”);
      }
      return null;
      }

    }

    /**

    • 判断是否在范围内
      */
      private boolean between(BigInteger param, BigInteger min, BigInteger max) {
      if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) {
      return true;
      } else {
      return false;
      }
      }

    /**

    • 判断生成的公钥是否合法
      */
      private boolean checkPublicKey(ECPoint publicKey) {

      if (!publicKey.isInfinity()) {

       BigInteger x = publicKey.getXCoord().toBigInteger();
       BigInteger y = publicKey.getYCoord().toBigInteger();
      
       if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {
      
       	BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);
      
       	if (debug)
       		System.out.println("xResult: " + xResult.toString());
      
       	BigInteger yResult = y.pow(2).mod(p);
      
       	if (debug)
       		System.out.println("yResult: " + yResult.toString());
      
       	if (yResult.equals(xResult) && publicKey.multiply(n).isInfinity()) {
       		return true;
       	}
       }
      

      }
      return false;
      }

    /**

    • 生成密钥对
      */
      public SM2KeyPair generateKeyPair() {

      //BigInteger d = random(n.subtract(new BigInteger(“1”)));
      BigInteger d=new BigInteger(“88923537656531405017940506920398063947744475871161460789882517934782180170453”);
      SM2KeyPair keyPair = new SM2KeyPair(G.multiply(d).normalize(), d);

      if (checkPublicKey(keyPair.getPublicKey())) {
      if (debug)
      System.out.println(“generate key successfully”);
      return keyPair;
      } else {
      if (debug)
      System.err.println(“generate key failed”);
      return null;
      }
      }

    public SM2() {
    curve = new ECCurve.Fp(p, // q
    a, // a
    b); // b
    G = curve.createPoint(gx, gy);
    ecc_bc_spec = new ECDomainParameters(curve, G, n);
    }

    public SM2(boolean debug) {
    this();
    this.debug = debug;
    }

    /**

    • 字节数组拼接
      */
      private static byte[] join(byte[]… params) {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] res = null;
      try {
      for (int i = 0; i < params.length; i++) {
      baos.write(params[i]);
      }
      res = baos.toByteArray();
      } catch (IOException e) {
      e.printStackTrace();
      }
      return res;
      }

    /**

    • sm3摘要
      */
      private static byte[] sm3hash(byte[]… params) {
      byte[] res = null;
      try {
      res = SM3.hash(join(params));
      } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
      return res;
      }

    /**

    • 密钥派生函数
      */
      private static byte[] KDF(byte[] Z, int klen) {
      int ct = 1;
      int end = (int) Math.ceil(klen * 1.0 / 32);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      try {
      for (int i = 1; i < end; i++) {
      baos.write(sm3hash(Z, SM3.toByteArray(ct)));
      ct++;
      }
      byte[] last = sm3hash(Z, SM3.toByteArray(ct));
      if (klen % 32 == 0) {
      baos.write(last);
      } else
      baos.write(last, 0, klen % 32);
      return baos.toByteArray();
      } catch (Exception e) {
      e.printStackTrace();
      }
      return null;
      }

}
B)SM2密钥对类实现
import java.math.BigInteger;
import org.bouncycastle.math.ec.ECPoint;

/**

  • SM2密钥对Bean
    */
    public class SM2KeyPair {

    private final ECPoint publicKey;
    private final BigInteger privateKey;

    SM2KeyPair(ECPoint publicKey, BigInteger privateKey) {
    this.publicKey = publicKey;
    this.privateKey = privateKey;
    }

    public ECPoint getPublicKey() {
    return publicKey;
    }

    public BigInteger getPrivateKey() {
    return privateKey;
    }

}
C)SM3类实现
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;

/**

  • SM3杂凑算法实现
    */
    public class SM3 {

    private static char[] hexDigits = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’,
    ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’};
    private static final String ivHexStr = “7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e”;
    private static final BigInteger IV = new BigInteger(ivHexStr.replaceAll(" ",
    “”), 16);
    private static final Integer Tj15 = Integer.valueOf(“79cc4519”, 16);
    private static final Integer Tj63 = Integer.valueOf(“7a879d8a”, 16);
    private static final byte[] FirstPadding = {(byte) 0x80};
    private static final byte[] ZeroPadding = {(byte) 0x00};

    private static int T(int j) {
    if (j >= 0 && j <= 15) {
    return Tj15.intValue();
    } else if (j >= 16 && j <= 63) {
    return Tj63.intValue();
    } else {
    throw new RuntimeException(“data invalid”);
    }
    }

    private static Integer FF(Integer x, Integer y, Integer z, int j) {
    if (j >= 0 && j <= 15) {
    return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
    } else if (j >= 16 && j <= 63) {
    return Integer.valueOf((x.intValue() & y.intValue())
    | (x.intValue() & z.intValue())
    | (y.intValue() & z.intValue()));
    } else {
    throw new RuntimeException(“data invalid”);
    }
    }

    private static Integer GG(Integer x, Integer y, Integer z, int j) {
    if (j >= 0 && j <= 15) {
    return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
    } else if (j >= 16 && j <= 63) {
    return Integer.valueOf((x.intValue() & y.intValue())
    | (~x.intValue() & z.intValue()));
    } else {
    throw new RuntimeException(“data invalid”);
    }
    }

    private static Integer P0(Integer x) {
    return Integer.valueOf(x.intValue()
    ^ Integer.rotateLeft(x.intValue(), 9)
    ^ Integer.rotateLeft(x.intValue(), 17));
    }

    private static Integer P1(Integer x) {
    return Integer.valueOf(x.intValue()
    ^ Integer.rotateLeft(x.intValue(), 15)
    ^ Integer.rotateLeft(x.intValue(), 23));
    }

    private static byte[] padding(byte[] source) throws IOException {
    if (source.length >= 0x2000000000000000l) {
    throw new RuntimeException(“src data invalid.”);
    }
    long l = source.length * 8;
    long k = 448 - (l + 1) % 512;
    if (k < 0) {
    k = k + 512;
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(source);
    baos.write(FirstPadding);
    long i = k - 7;
    while (i > 0) {
    baos.write(ZeroPadding);
    i -= 8;
    }
    baos.write(long2bytes(l));
    return baos.toByteArray();
    }

    private static byte[] long2bytes(long l) {
    byte[] bytes = new byte[8];
    for (int i = 0; i < 8; i++) {
    bytes[i] = (byte) (l >>> ((7 - i) * 8));
    }
    return bytes;
    }

    public static byte[] hash(byte[] source) throws IOException {
    byte[] m1 = padding(source);
    int n = m1.length / (512 / 8);
    byte[] b;
    byte[] vi = IV.toByteArray();
    byte[] vi1 = null;
    for (int i = 0; i < n; i++) {
    b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
    vi1 = CF(vi, b);
    vi = vi1;
    }
    return vi1;
    }

    private static byte[] CF(byte[] vi, byte[] bi) throws IOException {
    int a, b, c, d, e, f, g, h;
    a = toInteger(vi, 0);
    b = toInteger(vi, 1);
    c = toInteger(vi, 2);
    d = toInteger(vi, 3);
    e = toInteger(vi, 4);
    f = toInteger(vi, 5);
    g = toInteger(vi, 6);
    h = toInteger(vi, 7);

     int[] w = new int[68];
     int[] w1 = new int[64];
     for (int i = 0; i < 16; i++) {
         w[i] = toInteger(bi, i);
     }
     for (int j = 16; j < 68; j++) {
         w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15))
                 ^ Integer.rotateLeft(w[j - 13], 7) ^ w[j - 6];
     }
     for (int j = 0; j < 64; j++) {
         w1[j] = w[j] ^ w[j + 4];
     }
     int ss1, ss2, tt1, tt2;
     for (int j = 0; j < 64; j++) {
         ss1 = Integer
                 .rotateLeft(
                         Integer.rotateLeft(a, 12) + e
                                 + Integer.rotateLeft(T(j), j), 7);
         ss2 = ss1 ^ Integer.rotateLeft(a, 12);
         tt1 = FF(a, b, c, j) + d + ss2 + w1[j];
         tt2 = GG(e, f, g, j) + h + ss1 + w[j];
         d = c;
         c = Integer.rotateLeft(b, 9);
         b = a;
         a = tt1;
         h = g;
         g = Integer.rotateLeft(f, 19);
         f = e;
         e = P0(tt2);
     }
     byte[] v = toByteArray(a, b, c, d, e, f, g, h);
     for (int i = 0; i < v.length; i++) {
         v[i] = (byte) (v[i] ^ vi[i]);
     }
     return v;
    

    }

    private static int toInteger(byte[] source, int index) {
    StringBuilder valueStr = new StringBuilder("");
    for (int i = 0; i < 4; i++) {
    valueStr.append(hexDigits[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);
    valueStr.append(hexDigits[(byte) (source[index * 4 + i] & 0x0F)]);
    }
    return Long.valueOf(valueStr.toString(), 16).intValue();

    }

    private static byte[] toByteArray(int a, int b, int c, int d, int e, int f,
    int g, int h) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
    baos.write(toByteArray(a));
    baos.write(toByteArray(b));
    baos.write(toByteArray©);
    baos.write(toByteArray(d));
    baos.write(toByteArray(e));
    baos.write(toByteArray(f));
    baos.write(toByteArray(g));
    baos.write(toByteArray(h));
    return baos.toByteArray();
    }

    public static byte[] toByteArray(int i) {
    byte[] byteArray = new byte[4];
    byteArray[0] = (byte) (i >>> 24);
    byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);
    byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);
    byteArray[3] = (byte) (i & 0xFF);
    return byteArray;
    }
    private static String byteToHexString(byte b) {
    int n = b;
    if (n < 0)
    n = 256 + n;
    int d1 = n / 16;
    int d2 = n % 16;
    return “”+hexDigits[d1] + hexDigits[d2];
    }

    public static String byteArrayToHexString(byte[] b) {
    StringBuffer resultSb = new StringBuffer();
    for (int i = 0; i < b.length; i++) {
    resultSb.append(byteToHexString(b[i]));
    }
    return resultSb.toString();
    }

    public static void main(String[] args) throws IOException {
    System.out.println(SM3.byteArrayToHexString(SM3.hash(“test sm3 hash”.getBytes())));
    }
    }

(3)UI及软件框架部分
A)layout实现
①activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".MainActivity">

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/Theme.MyApplication.AppBarOverlay"/>

<Button
    android:id="@+id/button_first"
    android:layout_marginTop="180dp"
    android:layout_marginLeft="80dp"
    android:background="@color/purple_500"
    android:textColor="@color/white"
    android:layout_width="250dip"
    android:layout_height="150dip"
    android:textSize="30sp"
    android:text="@string/confirm_en" />

<Button
    android:id="@+id/button_second"
    android:layout_marginTop="400dp"
    android:layout_marginLeft="80dp"
    android:background="@color/purple_500"
    android:textColor="@color/white"
    android:layout_width="250dp"
    android:layout_height="150dp"
    android:textSize="30sp"
    android:text="@string/comfirm_de" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

②activity_keyen.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<LinearLayout
    android:id="@+id/line1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="80dp"
    android:layout_marginRight="80dp"
    android:layout_marginTop="80dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:text="@string/mykey_input" />


    <EditText
        android:id="@+id/mykey"
        android:hint="@string/mykey_input"
        android:gravity="start"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@drawable/bg_border"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/button_mykey_confirm"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/confirm_btn"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:text="@string/under_k" />


    <TextView
        android:id="@+id/ktext"
        android:layout_marginTop="2dp"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@drawable/bg_border"
        android:hint="@string/c_key" />
    <Button
        android:id="@+id/clip_k"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/clip_string_k"/>
    <Button
        android:id="@+id/beginen"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/begin_to_enc"/>
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

③activity_encryption.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".Encryption">

<LinearLayout
    android:id="@+id/line1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="50dp"
    android:layout_marginRight="50dp"
    android:layout_marginTop="80dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:text="@string/enter_p" />


    <EditText
        android:id="@+id/p_text"
        android:layout_marginTop="2dp"
        android:hint="@string/enter_p"
        android:gravity="start"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/bg_border"
        android:inputType="text" />
    <Button
        android:id="@+id/confirm_encryto"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/confirm_en"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_marginTop="6dp"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:text="@string/under_c" />


    <TextView
        android:id="@+id/Decyptotext"
        android:layout_marginTop="2dp"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/bg_border"
        android:text="@string/c_text" />
    <Button
        android:id="@+id/clip_c"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/clip_string_c"/>
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

④activity_load.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".Load">

<LinearLayout
    android:id="@+id/line1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="80dp"
    android:layout_marginRight="80dp"
    android:layout_marginTop="150dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="26dp"
        android:text="@string/btn_load" />


    <EditText
        android:id="@+id/username"
        android:hint="@string/username_input"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/bg_border"
        android:inputType="text" />

    <EditText
        android:id="@+id/userkey"
        android:hint="@string/userkey_input"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/bg_border"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/loading"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/btn_load"/>

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

⑤activity_keyde.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<LinearLayout
    android:id="@+id/line1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="100dp"
    android:layout_marginRight="100dp"
    android:layout_marginTop="150dp"
    android:layout_marginBottom="150dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:text="@string/ckey_input" />


    <EditText
        android:id="@+id/ckey"
        android:hint="@string/ckey_input"
        android:gravity="start"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/bg_border"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/button_dec_confirm"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/confirm_btn"/>
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

⑥activity_decryption.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".DecryptionActivity">

<LinearLayout
    android:id="@+id/line1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="50dp"
    android:layout_marginRight="50dp"
    android:layout_marginTop="80dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:text="@string/entern_c" />


    <EditText
        android:id="@+id/c_text"
        android:layout_marginTop="2dp"
        android:hint="@string/entern_c"
        android:gravity="start"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/bg_border"
        android:inputType="text" />
    <Button
        android:id="@+id/confirm_decryto"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textColor="@color/white"
        android:background="@color/purple_500"
        android:text="@string/comfirm_de"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:text="@string/under_p" />


    <TextView
        android:id="@+id/Decyptotext"
        android:layout_marginTop="2dp"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/bg_border"
        android:text="@string/p_text" />
    <Button
        android:id="@+id/clip_p"
        android:layout_marginTop="5dp"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/purple_500"
        android:textColor="@color/white"
        android:text="@string/clip_string_p"/>

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

⑦strings.xml

Only for Alice
Only for Alice

First Fragment
Second Fragment
Next
Previous

<string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
<string name="input_hint">请输入密钥</string>
<string name="confirm_btn">确认</string>
<string name="title_activity_decryption">Decryption</string>
<string name="clip_p">复制明文</string>
<string name="clip_string_p">复制明文</string>
<string name="c_key">使用sm2加密得到的密钥在此处显示</string>
<string name="p_text">明文在此处显示</string>
<string name="c_text">密文在此处显示</string>
<string name="clip_string_c">复制密文</string>
<string name="clip_string_k">复制密钥</string>
<string name="confirm_en">加密</string>
<string name="enter_p">请输入明文</string>
<string name="entern_c">请输入密文</string>
<string name="comfirm_de">解密</string>
<string name="mykey_input">请输入您的密钥</string>
<string name="ckey_input">请输入您收到的密钥</string>
<string name="under_k">使用SM2加密得到的密钥如下</string>
<string name="under_c">使用SM4加密得到的密文如下</string>
<string name="under_p">使用SM4解密得到的明文如下</string>
<string name="begin_to_enc">开始加密</string>
<string name="username_input">请输入您的用户名</string>
<string name="userkey_input">请输入您的口令</string>
<string name="btn_load">登录</string>

⑧dimens.xml

16dp

⑨colors.xml

<?xml version="1.0" encoding="utf-8"?> #D98719 #D98719 #B87333 #FF03DAC5 #FF018786 #FF000000 #FFFFFFFF

⑩bg_borden.xml

<?xml version="1.0" encoding="utf-8"?>

B)MainActivity.java
package com.example.myapplication;

import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;

import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

public static final String TAG = "MAIN_ACTIVITY";
private Button btn1;
private Button btn2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initView();
    initListener();

}

private void initView(){//初始化按钮
    btn1 = findViewById(R.id.button_first);
    btn2 = findViewById(R.id.button_second);
}

private void initListener(){//实现跳转
    btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent=new Intent(MainActivity.this,KeyEn.class);
            startActivity(intent);

        }
    });

    btn2.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Intent intent=new Intent(MainActivity.this, Load.class);
            startActivity(intent);
        }
    });
}

}

C)KeyEnActivity.java
package com.example.myapplication;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;

public class KeyEn extends Activity {

//public static final String TAG = "KenEn_activity";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.keyen);
    cfm_enk_key();
    clip_ck();
    beginenc();
}

private void cfm_enk_key(){
    Button btn_cfm_en=findViewById(R.id.button_mykey_confirm);
    btn_cfm_en.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EditText mykey1=findViewById(R.id.mykey);
            String Mykey=mykey1.getText().toString();//Mykey即为需要使用SM2加密的用户密钥
            Mainfunction function_keyen=new Mainfunction();
            String string_ckey=function_keyen.KeyEncrypt(Mykey);
            TextView tv_k=findViewById(R.id.ktext);
            tv_k.setText(string_ckey);
        }
    });

}
private void clip_ck() {
    Button btn_clip_p=findViewById(R.id.clip_k);
    btn_clip_p.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            clip_k();

        }
    });
}

private void showToast(String 复制成功) {
}
private void clip_k(){
    TextView tv_k1=findViewById(R.id.ktext);
    String c_key=tv_k1.getText().toString();
    //String c_key=(String) this.getResources().getString(R.string.c_key);
    //c_key="发送密钥为:"+c_key;

    ClipboardManager cm;
    // 创建普通字符型ClipData
    ClipData mClipData = ClipData.newPlainText("Label", c_key);
    //获取剪贴板管理器:
    cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// 将ClipData内容放到系统剪贴板里。
cm.setPrimaryClip(mClipData);
showToast(“复制成功”);
}
private void beginenc(){
Button btn = findViewById(R.id.beginen);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(KeyEn.this, Encryption.class);
EditText mykey=findViewById(R.id.mykey);
String Mykey=mykey.getText().toString();//把用户输入的密钥Mykey传过去
intent.putExtra(“mykey”,Mykey);
startActivity(intent);

        }
    });
}

}
D)EncryptionActivity.java
package com.example.myapplication;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;

import java.util.ArrayList;

public class Encryption extends Activity {

//public static final String TAG = "KenEn_activity";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.encryption);
    cfm_enc_p();
    clip_myc();
}
private void cfm_enc_p(){
    Button btn_cfm_en=findViewById(R.id.confirm_encryto);
    btn_cfm_en.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent=getIntent();
            String Mykey=intent.getStringExtra("mykey");//从上一个页面获取输入的密钥


            EditText p_text=findViewById(R.id.p_text);


            String P_text=p_text.getText().toString();//P_text为输入的明文
            //点击按钮开始加密
            System.out.println(P_text);
           // System.out.println(rk);
            Encrypt Enc = new Encrypt(P_text,Mykey);
            String c = Enc.encryptEntrance();

            //Mykey="111";

            TextView tv_c=findViewById(R.id.Decyptotext);

            tv_c.setText(c);

        }
    });
}
private void clip_myc() {
    Button btn_clip_p=findViewById(R.id.clip_c);
    btn_clip_p.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            clip_pp();

        }
    });
}


private void clip_pp(){
    TextView tv_c=findViewById(R.id.Decyptotext);
    String c_text=tv_c.getText().toString();
    //String c_text=(String) this.getResources().getString(R.string.c_text);
   // c_text="密文为:"+c_text;
    ClipboardManager cm;
    // 创建普通字符型ClipData
    ClipData mClipData = ClipData.newPlainText("Label", c_text);
    //获取剪贴板管理器:
    cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// 将ClipData内容放到系统剪贴板里。
cm.setPrimaryClip(mClipData);
//showToast(“复制成功”);
}

}

E)LoadActivity.java
package com.example.myapplication;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Load extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.load);
isJump();
}

private void isJump(){

    Button btn3 = findViewById(R.id.loading);
    btn3.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {//点击按钮
            EditText username=findViewById(R.id.username);
            String name=username.getText().toString();
            EditText userkey=findViewById(R.id.userkey);
            String key=userkey.getText().toString();//获取输入
            if(name.equals("Alice")&&key.equals("123456")) {//验证
                Intent intent = new Intent(Load.this, KeyDe.class);//跳转
                startActivity(intent);
            }
        }
    });
}

}

F) KeyDeActivity.java
package com.example.myapplication;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;

public class KeyDe extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.keyde);
Button btn3 = findViewById(R.id.button_dec_confirm);
btn3.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EditText ckey=findViewById(R.id.ckey);
String c_key=ckey.getText().toString();//获取收到的密钥
//接下来开始对该密钥进行解密,得到原始的k
Mainfunction function_keyde=new Mainfunction();
String string_my_key=function_keyde.KeyDecrypt(c_key);
Intent intent = new Intent(KeyDe.this, DecryptionActivity.class);
intent.putExtra(“string_my_key”,string_my_key);//把解密得到的密钥传过去
System.out.println(“hhh”+string_my_key);
startActivity(intent);
}
});
}
}

G) DecryptionActivity.java
package com.example.myapplication;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.RequiresApi;

import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;

public class DecryptionActivity extends Activity {

//public static final String TAG = "KenEn_activity";


@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.decryption);
    cfm_de();
    clip_myp();



}
private void cfm_de(){
    Button btn_cfm_en=findViewById(R.id.confirm_decryto);
    btn_cfm_en.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent=getIntent();
            String Mykey=intent.getStringExtra("string_my_key");//获取密钥
            System.out.println(Mykey);

            EditText ctext = findViewById(R.id.c_text);
            String c_test = ctext.getText().toString();//c_text即为输入的密文
            Decrypt Dec = new Decrypt(c_test,Mykey);

            //点击按钮开始解密
            //Mykey="111";
            String a=Dec.decryptEntrance();//重新设置显示的密文
            TextView tv_c=findViewById(R.id.Decyptotext);
            System.out.println("hhhhh"+a);
            tv_c.setText(a);


        }

    });
}

private void clip_myp() {
    Button btn_clip_p=findViewById(R.id.clip_p);
    btn_clip_p.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            clip_pp();

        }
    });
}

private void showToast(String 复制成功) {
}
private void clip_pp(){
    TextView tv_p1=findViewById(R.id.Decyptotext);
    String p_text=tv_p1.getText().toString();
    //String p_text=(String) this.getResources().getString(R.string.p_text);
    //p_text="明文为:"+p_text;
    ClipboardManager cm;
    // 创建普通字符型ClipData
    ClipData mClipData = ClipData.newPlainText("Label", p_text);
    //获取剪贴板管理器:
    cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// 将ClipData内容放到系统剪贴板里。
cm.setPrimaryClip(mClipData);
showToast(“复制成功”);
}
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐