密码学课设实验——序列密码c++实现

一、实验目的

通过实现简单的线性反馈移位寄存器(LFSR),理解LFSR的工作原理、本原多项式的重要意义

 

二、实验内容

1)利用C\C++语言实现给定的LFSR;

2)通过不同初始状态生成相应的序列,并观察它们的周期有什么特点;

3)利用生成的序列对文本进行加/解密(按对应位作模2加运算)。

给定的LFSR为:

 

  • 实验步骤

1.总体理解,LFSR每个状态对应一个输出,所以需要定义三个变量分别为

int array[5];     //暂存状态

int state[32][5]; //存储状态,总共有2^5共32种不同的状态

int seq[32];      //输出序列

2.由所给的图得知反馈函数f(x)=a1^a4,即a5=a1^a4,得到下面的主要函数int temp=arr[0]^arr[3];

3.关于不同的状态;定义了三个相关函数

//打印当前状态

void print(int *arr)

//求出下一状态

void next(int *arr)

//获得状态并存储

void get_state(int *arr, int *s)

4.求解周期:将上文中的state二维数组作为参数依此比较每一状态,求出周期

定义了一个比较函数int cmp_s(int s[32][5]),比较state数组中存储的32个不同的状态、

5.由于是模2运算,所以加密和解密函数都可以使用同一个加密解密函数

void enc(int *cipher, int *m, int *seq, int num),seq传入加密序列,然进行异或

其中,关于加密序列的使用,循环使用然后与二进制的明文进行异或

 

代码如下:

// 序列密码.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//f(x)=a1^a4,即a5=a1^a4

#include "pch.h"
#include<iostream>
#include<math.h>
using namespace std;
#include<fstream>
#include<string>

#define n 5

//求输入
int LFSR(int *arr)
{
	int temp=arr[0]^arr[3];
	return temp;
}

//打印
void print(int *arr)
{
	cout << "当前状态:";
	for (int i = 0; i < n; i++)
	{
		cout<< arr[i];
	}
	cout << "\t";
	cout << "输出:" << arr[0] << endl;
}

//求出下一状态
void next(int *arr)
{
	int a5 = LFSR(arr);
	for (int i = 0; i < n - 1; i++)
	{
		arr[i] = arr[i + 1];
	}
	arr[n - 1] = a5;
}

//获得状态并存储
void get_state(int *arr, int *s)
{
	for (int i = 0; i < n; i++)
	{
		s[i] = arr[i];
	}
}

//为了获取周期对状态进行比较
int cmp_s(int s[32][5])
{
	for (int i = 1; i < 32; i++)
	{
		int j;
		for (j = 0; j < 5; j++)
		{
			if (s[0][j] != s[i][j])
				break;
			else continue;
		}
		if (j == 5)
		{
			return i;
		}
	}
}

string change(char c)
{
	string data;
	for (int i = 0; i < 8; i++)
	{
		//  data+=c&(0x01<<i);
		if ((c >> (i - 1)) & 0x01 == 1)
		{
			data += "1";
		}
		else
		{
			data += "0";
		}
	}
	for (int a = 1; a < 5; a++)
	{
		char x = data[a];
		data[a] = data[8 - a];
		data[8 - a] = x;
	}

	return data;
}

void enc(int *cipher, int *m, int *seq, int num)
{
	int counter = 0;
	int counter_num = 0;
	int num_8 = 8 * num;//num传入filenum,因为是8位,filenum为符号数,所以位数为8*filenum
	while (counter_num<num_8)
	{
		cipher[counter_num]=seq[counter]^m[counter_num];
		counter++;
		counter_num++;
		if (counter == 31)
			counter = 0;
	}
}

int main()
{
	int array[5];
	int state[32][5]; //存储状态,总共有2^5共32种不同的状态
	int seq[32];      //输出序列
	int s_num = 0;

	cout << "请输入初始状态:";
	for (int i = 0; i < n; i++)
	{
		cin >> array[i];
	}
	get_state(array,state[s_num]);
	cout << s_num<<":";
	print(state[s_num]);
	seq[s_num] = array[0];

	//下一状态
	for (int i = 1; i < 32; i++)
	{
		next(array);
		++s_num;
		get_state(array, state[s_num]);
		cout << s_num<<":";
		print(state[s_num]);
		seq[s_num] = array[0];
	}
	
	cout << "输出序列为:";
	for (int i = 0; i < 32; i++)
	{
		cout << seq[i];
	}
	cout << endl;

	cout<<"周期为:"<<cmp_s(state)<<endl;

	char ch[200];//存明文
	char c;
	int i = 0, filenum;
	char filename[81];
	ifstream f_in;
	rewind(stdin); //清空缓冲区
	cout << endl;
	cout << "输入要加密的文件名:";
	cin.getline(filename, 81);
	f_in.open(filename, ios::in | ios::out);
	if (!f_in)
	{
		cout << "Open input file error!" << endl;
		exit(0);
	}
	while (!f_in.eof())
	{
		f_in.get(c);
		ch[i] = c;
		i++;
	}
	f_in.close();

	filenum = i - 1;
    
	//输出明文
	cout << endl;
	cout << "原文为:";
	for (int num = 0; num < filenum; num++)
		cout << ch[num];
	cout << endl;

	//把明文转为二进制存入二维数组binary中
	int binary[200][8] = {0};
	for (int j = 0; j < filenum; j++)
	{
		int temp[8];
		string da = change(ch[j]);
		for (int i = 0; i < 8; i++)
		{
			temp[i] = da[i];
			if (temp[i] == 48)
				temp[i] = 0;
			else temp[i] = 1;
		}
		for (int i = 0; i < 8; i++)
		{
			//cout << temp[i];
			binary[j][i] = temp[i];
		}
		//cout << endl;
	}

	/*for (int i = 0; i < filenum; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			cout << binary[i][j];
		}
		cout << endl;
	}*/

	int M[1600] = { 0 };
	int count = 0;
	for (int i = 0; i < filenum; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			M[count]=binary[i][j];
			//cout << M[count];
			count++;
		}
	}
	cout << endl << "明文表示为:";
	for (int i = 0; i < count; i++)
	{
		cout << M[i];
	}
	cout << endl;

    cout << endl << "密文表示为:";;
	int cipher[1600];
	enc(cipher,M,seq,filenum);
	for (int i = 0; i < count; i++)
	{
		cout << cipher[i];
	}
	cout << endl;

	cout << endl << "解码出的明文为:";;
	int c_M[1600];
	enc(c_M, cipher, seq, filenum);
	for (int i = 0; i < count; i++)
	{
		cout << c_M[i];
	}
	cout << endl;
	
	cout <<endl<< "解码出的原文为:";
	for (int i = 0; i < filenum; i++)
	{
		int temp_num = 0;
		int temp_i = 8 * i;
		temp_num = c_M[0+temp_i] * 128 + c_M[1 + temp_i] * 64 + c_M[2 + temp_i] * 32 + c_M[3 + temp_i] * 16 + c_M[4 + temp_i] * 8 + c_M[5 + temp_i] * 4 + c_M[6 + temp_i] * 2 + c_M[7 + temp_i] * 1;
		char c_n = temp_num;
		cout << c_n;
	}
	return 0;
}

结果如下:

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值