基於字符設備對字符串進行加密解密

字符設備驅動

任務

編寫利用字符設備實現對字符串加密解密的程序。
  加密:將大小寫字母循環加4
  解密:將大小寫字母循環減4
  例如:"China!“加密成"Glmre!”

驅動代碼

//這是驅動代碼,實現一個主設備號,兩個次設備。一個次設備號加密,一個次設備號解密。
//相應的測試程序是 test1.c

#include<linux/module.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#define OFFSET 4	
#define Major 200
#define SIZE 256
MODULE_LICENSE("GPL");

dev_t mydev;//存放申請的主次設備號
struct cdev mycdev[2]; //用於描述設備信息的結構體
char str[SIZE]={0}; //用於存放從用戶態傳送到內存態的數據
ssize_t my_write1(struct file* pfile,const char __user * buff, size_t num, loff_t *f_p)
{	
	int n=0;
	printk(KERN_INFO"Write1 now\n");
	if(num>SIZE)		//若是num大小超出存儲的數組大小
		return -ENOMEM;

	if(copy_from_user(str,buff,num))	//若是還有從用戶態未讀完的數據
		return -EFAULT;
//	copy_from_user(str,buff,num);

#if 1
	while(str[n] != 0)	//字符加密,即字母往後循環移動 OFFSET 位數
	{
		if( ('a'<=str[n]&&str[n]<='z') || ('A'<=str[n]&&str[n]<='Z') )
		{
			if( ('a'<=str[n]&&str[n]<=('z'-OFFSET)) || ('A'<=str[n]&&str[n]<=('Z'-OFFSET)) )
				str[n] += OFFSET;
		else
		{	
			str[n] += OFFSET - 26;
		}
			
		n++;
		}
	}

#endif
	printk(KERN_INFO"Write1 Succeed\n");
	return 0;
}
ssize_t my_write2(struct file* pfile,const char __user * buff, size_t num, loff_t *f_p)
{
	printk(KERN_INFO"Write2 Now\n");
	if(num>SIZE)		//若是num大小超出存儲的數組大小
		return -ENOMEM;

	if(copy_from_user(str,buff,num))	//若是還有從用戶態未讀完的數據
		return -EFAULT;

	printk(KERN_INFO"Write2 Succeed\n");
	return 0;

}
ssize_t my_read1(struct file* pfile,char __user* buff, size_t num, loff_t *f_p)
{
	printk(KERN_INFO"Read1 now\n");
	if(num>SIZE)	//若所讀大小超出內核態儲存的大小
		num=SIZE;
	if(copy_to_user(buff,str,num))	//若是還有從內核態未讀完的數據
		return -EFAULT;
	printk(KERN_INFO"Read1 Succeed\n");
	return 0;

}
ssize_t my_read2(struct file* pfile,char __user* buff, size_t num, loff_t *f_p)
{

	int n=0;
	printk(KERN_INFO"Read2 now\n");
	while(str[n] != 0)	//字符解密,即字母循環向前移動 OFFSET 位數
	{
		if( ('a'<=str[n]&&str[n]<='z') || ('A'<=str[n]&&str[n]<='Z') )
		{
			if( (('a'+OFFSET)<=str[n]&&str[n]<='z') || (('A'+OFFSET)<=str[n]&&str[n]<='Z') )
				str[n] -= OFFSET;
			else
			{	
				str[n] += 26 - OFFSET;
			}
		}
		
		n++;
	}

#endif
	if(num>SIZE)	//若所讀大小超出內核態儲存的大小
		num=SIZE;
	if(copy_to_user(buff,str,num))	//若是還有從內核態未讀完的數據
		return -EFAULT;

	printk(KERN_INFO"Read2 Succeed\n");
	return 0;
}
int my_open(struct inode * id,struct file* pfile)
{
	printk(KERN_INFO"Open file\n");
	printk(KERN_INFO"Open Succeed\n");
	return 0;
}
int my_release(struct inode * id,struct file* pfile)
{
	printk(KERN_INFO"Release file\n");
	printk(KERN_INFO"Release Succeed\n");
	return 0;
}
struct file_operations ops1={	//第一個次設備號用於加密
	.owner = THIS_MODULE,
	.open = my_open,
	.release = my_release,
	.read = my_read1,
	.write = my_write1   //對於設備特性的描述
};
struct file_operations ops2={	//第二個次設備號用於解密
	.owner = THIS_MODULE,
	.open = my_open,
	.release = my_release,
	.read = my_read2,
	.write = my_write2   //對於設備特性的描述
};

int __init init_module(void)
{
	int ret = 1;
	printk(KERN_INFO"Init cdev now\n");
	mydev = MKDEV(Major,0);	//創建設備號
	ret = register_chrdev_region(mydev,2,"cdevTest");	//申請兩個設備號 即次設備號是0,1
	if(ret != 0 )
	{
		printk(KERN_INFO"Error dev number\n");	//設備號申請失敗
		return 0;
	}
	
	cdev_init(&mycdev[0],&ops1);
	ret = cdev_add(&mycdev[0],mydev,1);
	if(ret != 0 )
	{
		printk(KERN_INFO"Error cdev1\n");	//設備特性添加失敗
		return 0;
	}
	cdev_init(&mycdev[1],&ops2);
	ret = cdev_add(&mycdev[1],mydev+1,1);
	if(ret != 0 )
	{
		printk(KERN_INFO"Error cdev2\n");	//設備特性添加失敗
		return 0;
	}
	printk(KERN_INFO" Succeed\n");
	

	return 0;
}

void __exit cleanup_module (void)
{
	printk(KERN_INFO"Exit cdev now\n");
	unregister_chrdev_region(mydev,2);//註銷設備號
	cdev_del(&mycdev[0]); //註銷設備
	cdev_del(&mycdev[1]); //註銷設備
}

測試代碼

測試前,需要現在Linux 的 /dev 下創建相應的驅動文件。
  mknod /dev/code_cdev1 c 200 0
  mknod /dev/code_cdev2 c 200 0
  由於實驗中涉及對驅動文件的讀寫操作,所以需要更改對文件的權限。
  sudo chmod 777 /dev/code_cdev1
  sudo chmod 777 /dev/code_cdev2

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
int main()
{
	int fd_1 =-1;
	int fd_2 =-1;
	char str[256] = {0};
	fd_1 = open("/dev/code_cdev1",O_RDWR);	//打開相應的驅動文件,此文件需要自己手動提前創建
	if(fd_1<0)
	{
		printf("fd_1 error\n");
		return 0;
	}
	fd_2 = open("/dev/code_cdev2",O_RDWR);	
	if(fd_2<0)
	{
		printf("fd_2 error\n");
		return 0;
	}
	printf("Please Enter:");
	gets(str);
	printf("You Enter:%s\n",str);
	write(fd_1,str,strlen(str));
	read(fd_1,str,strlen(str));
	printf("Encode Print:%s\n",str);
	
	write(fd_2,str,strlen(str));
	read(fd_2,str,strlen(str));
	printf("Uncode Print:%s\n",str);



	close(fd_1);
	close(fd_2);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章