C语言实现S-DES密码体制

问题描述:根据输入的10bit主密钥,将输入的8bit明文(密文)加密(解密)成8bit的密文(明文)。

例:输入:明文0100 0011
                  主密钥:10100 00010

       输出:密文0 1 0 0 0 1 0 0

将S盒定义修改为你所使用的课本上定义即可!!!(即修改以下代码块中数组的值)

加密示意图: 

f函数求解示意图:

子秘钥求解示意图:

 代码:

#define _CRT_SECURE_NO_WARNINGS 1
//S-DES密码体制

#include<stdio.h>

//菜单
void menu() {
	printf("-------   S-DES    --------\n");
	printf("-------  1. 加密   --------\n");
	printf("-------  2. 解密   --------\n");
	printf("-------  0. 退出   --------\n");
}

//f函数
int f(int R[4], int key[8]) {//传R0和key1或R1和key2
	int s[4] = { 0 }, s1[4] = { 0 }, s2[4] = { 0 }, f[4] = { 0 };
	int temp = 0;
	//定义两个s盒
	/*int sh1[4][4] = { {1,0,3,2},
					  {3,2,1,0},
					  {0,2,1,3},
					  {3,1,0,2}
	};
	int sh2[4][4] = { {0,1,2,3},
					  {2,0,1,3},
					  {3,2,1,0},
					  {2,1,0,3}
	};*/
	int sh1[4][4] = { {1,0,2,3},
					  {2,3,0,1},
					  {0,1,3,2},
					  {3,2,1,0}
	};
	int sh2[4][4] = { {0,1,2,3},
					  {2,0,3,1},
					  {1,3,0,2},
					  {3,2,1,0}
	};
	//E/P扩位及置换 4 1 2 3 2 3 4 1
	int R0[8] = { 0 };
	int ret = 0;
	R0[0] = R[3];
	R0[1] = R[0];
	R0[2] = R[1];
	R0[3] = R[2];
	R0[4] = R[1];
	R0[5] = R[2];
	R0[6] = R[3];
	R0[7] = R[0];
	//异或
	for (int i = 0; i < 8; i++)
	{
		ret = R0[i] ^ key[i];
		R0[i] = ret;
	}
	//分为左右两个部分s1、s2
	for (int i = 0; i < 4; i++)
	{
		s1[i] = R0[i];
		s2[i] = R0[i + 4];
	}
	//查找对应s盒的数据
	s[0] = s1[0] * 2 + s1[3];
	s[1] = s1[1] * 2 + s1[2];
	temp = sh1[s[0]][s[1]];
	s[0] = temp / 2;
	s[1] = temp % 2;
	s[2] = s2[0] * 2 + s2[3];
	s[3] = s2[1] * 2 + s2[2];
	temp = sh2[s[2]][s[3]];
	s[2] = temp / 2;
	s[3] = temp % 2;
	//p4置换 2 4 3 1
	f[0] = s[1];
	f[1] = s[3];
	f[2] = s[2];
	f[3] = s[0];
	return f;
}

//加密与解密(input==1时为加密算法,input==2时是解密算法)
void encryption_and_decryption(int input) {
	//加密解密变量定义
	int m[8] = { 0 };//存贮明文(当是解密算法是用作存贮密文)
	int c1[8] = { 0 };//存贮IP置换前的密文
	int c[8] = { 0 };//存贮密文
	int m1[8] = { 0 };//IP置换后
	int L0[4] = { 0 }, R0[4] = { 0 };//定义L0和R0
	int L1[4] = { 0 }, R1[4] = { 0 };
	int L2[4] = { 0 }, R2[4] = { 0 };

	//子秘钥变量定义
	int key[10] = { 0 };
	int p10[10] = { 0 };//存贮p10置换
	int LS_1[10] = { 0 };
	int LS_2[10] = { 0 };
	int key1[8] = { 0 }, key2[8] = { 0 };

	//f函数变量定义
	int temp = 0;
	int* pf = NULL;

	//加密算法
	if (input == 1) {
		printf("请输入二进制明文(以空格隔开):");
	}
	//解密算法
	else
	{
		printf("请输入二进制密文(以空格隔开):");
	}
	for (int i = 0; i < 8; i++)
	{
		scanf_s("%d", &m[i]);
	}
	//IP置换 2 6 3 1 4 8 5 7
	m1[0] = m[1];
	m1[1] = m[5];
	m1[2] = m[2];
	m1[3] = m[0];
	m1[4] = m[3];
	m1[5] = m[7];
	m1[6] = m[4];
	m1[7] = m[6];
	//分为两部分
	for (int i = 0; i < 4; i++)
	{
		L0[i] = m1[i];
		R0[i] = m1[i + 4];
		L1[i] = m1[i + 4];//L1与R0相同
	}
	//求子秘钥
	printf("请输入主密钥(以空格隔开):");
	for (int i = 0; i < 10; i++)
	{
		scanf_s("%d", &key[i]);
	}
	//p10置换 3 5 2 7 4 10 1 9 8 6
	p10[0] = key[2];
	p10[1] = key[4];
	p10[2] = key[1];
	p10[3] = key[6];
	p10[4] = key[3];
	p10[5] = key[9];
	p10[6] = key[0];
	p10[7] = key[8];
	p10[8] = key[7];
	p10[9] = key[5];
	//左移一位
	for (int i = 0; i < 5; i++)
	{
		LS_1[i] = p10[(i + 1) % 5];
		LS_1[i + 5] = p10[((i + 1) % 5) + 5];
	}
	//p8置换 6 3 7 4 8 5 10 9 求key1
	key1[0] = LS_1[5];
	key1[1] = LS_1[2];
	key1[2] = LS_1[6];
	key1[3] = LS_1[3];
	key1[4] = LS_1[7];
	key1[5] = LS_1[4];
	key1[6] = LS_1[9];
	key1[7] = LS_1[8];
	//左移两位
	for (int i = 0; i < 5; i++)
	{
		LS_2[i] = LS_1[(i + 2) % 5];
		LS_2[i + 5] = LS_1[((i + 2) % 5) + 5];
	}
	//p8置换 6 3 7 4 8 5 10 9 求key2
	key2[0] = LS_2[5];
	key2[1] = LS_2[2];
	key2[2] = LS_2[6];
	key2[3] = LS_2[3];
	key2[4] = LS_2[7];
	key2[5] = LS_2[4];
	key2[6] = LS_2[9];
	key2[7] = LS_2[8];
	//加密先用key1
	if (input == 1) {
		pf = f(R0, key1);
	}
	//解密先用key2
	else
	{
		pf = f(R0, key2);
	}
	//f函数与L0异或
	for (int i = 0; i < 4; i++)
	{
		temp = L0[i] ^ *(pf + i);
		R1[i] = temp;
		R2[i] = temp;//R2和R1一样
	}
	//加密
	if (input == 1) {
		pf = f(R1, key2);
	}
	//解密
	else
	{
		pf = f(R1, key1);
	}
	for (int i = 0; i < 4; i++)
	{
		temp = L1[i] ^ *(pf + i);
		L2[i] = temp;
	}
	//将上述求得的L2和R2进行拼接合并到c1
	for (int i = 0; i < 4; i++)
	{
		c1[i] = L2[i];
		c1[i + 4] = R2[i];
	}
	//IP逆置换 4 1 3 5 7 2 8 6
	c[0] = c1[3];
	c[1] = c1[0];
	c[2] = c1[2];
	c[3] = c1[4];
	c[4] = c1[6];
	c[5] = c1[1];
	c[6] = c1[7];
	c[7] = c1[5];
	//分不同情况打印
	if (input == 1) {
		printf("密文是:");
	}
	else
	{
		printf("明文是:");
	}
	for (int i = 0; i < 8; i++)
	{
		printf("%d ", c[i]);
	}
	printf("\n");
}

void test() {
	int input = 0;
	do {
		menu();
		printf("请选择:->");
		scanf_s("%d", &input);
		switch (input)
		{
		case 1:
			encryption_and_decryption(input);
			break;
		case 2:
			encryption_and_decryption(input);
			break;
		case 0:
			printf("已退出加密解密系统\n");
			break;
		default:
			printf("输入有误,请重新输入!\n");
			break;
		}
	} while (input);
}

int main() {
	test();
	return 0;
}

运行结果截图:

如果内容对你有帮助,关注我,给我点个小小的赞吧!

若内容有误,请指正并多多包容,谢谢。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪脱脱写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值