保密已经日渐成为各单位重视的方面之一,而简易的密工作数字化系统是不少小单位的重要需求。现在网络上关于这个的资源也不多,我就抛砖引玉,稍作思路介绍吧。

项目背景

​ 随着电子政务的发展与推广,越来越多的政务涉密文件以电子文档的形式存在,我们迫切需要先进的涉密工作数字化系统。现有的电子政务工作系统虽然一定程度上提高了工作效率,但在保密定密工作特殊领域中,因为制度不完善等问题,保密定密方式太落后,容易造成涉密信息泄露的问题。定密是保密工作的源头任务,因此科学严谨的定密方式也决定了保密定密工作质量,体现了对于国家安全的重要性,在数字化快速发展和电子政务不断普及的今天,定密工作数字化系统是广大定密工作者所共同期盼的。

​ 本文针对定密工作数字化系统的几个核心功能进行讲解和实现,并且最后给出代码实现和效果展示。仅此抛砖引玉,希望这个简单的定密工作数字化系统能给后人一点点小的框架设计启发。

框架介绍

数据框架

​ 在这次的简单定密定密工作数字化系统的开发设计中,在数据方面我们着重要处理的是涉密工作人员的信息和涉密文件的信息。

​ 在数据方面,对于每个涉密工作人员,我们会记录六个信息分别是:是否是管理员、现有定密权、原始定密定密权、授权者是谁以及账号基本的账号密码信息,这都是一个涉密数字化系统应该具有的基本组成部分,所以这一部分的定义代码如下:

struct Person {
    int admin; 
    //是否是超级管理员 

    int secret_state; 
    //现有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int origin_secret_state;
    //原有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int from_person;
    //若被授权,则授权者是谁 

    char account[110]; //账号 
    char password[110];//密码 
}person[1100];

​ 对于每个涉密系统文件,我们也会记录这个文件的密级、名称、定密时间、定密的保密年限、为该文件定密的定密者信息以及权限码这六个维度的信息,所以这部分定义的代码如下:

struct File {
    int state; 
    //文件的密级 
    //-1:unknown      未定密的 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int state_time;//定密的时间 
    int state_year;//保密年限

    int handle;//定密者是谁

    char filename[110];//文件名 
    char key[11];
    //10位的权限码,用于控制知悉范围 
}file[1100];

​ 介绍完了数据方面的框架,我们再来看看文件夹结构方面。我们的文件主要分成三个部分,首先是绿色框框内的五个文件夹,这是存放涉密文件的地方,也就是我们的文件数据库,只有超级管理员才有访问的权限;橙色框框里的 $Use$ 文件夹则是涉密人员可以访问的文件夹,涉密人员可以登录账号,凭权限将涉密文件从数据库转移到这个文件夹中进行阅读和使用;而最后紫色框框中的 $File$ 和 $Person$ 两个文件则是存储涉密人员和涉密文件相关信息的备份文件,用于启动程序时恢复之前的数据。

1.png

代码框架

​ 我们的代码大致分为三个部分导入数据,即从我们备份的信息文档中回复之前工作的数据;系统界面,即我们程序的核心也是系统本体;导出数据,也就是将我们当前存在内存中的数据导出到硬盘的文本文件中,以便下次启动系统时恢复系统的进度。所以我们的大体框架就如下所示:

#include <set>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <cstring>
#include <windows.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct Person {
    int admin; 
    //是否是超级管理员 

    int secret_state; 
    //现有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int origin_secret_state;
    //原有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int from_person;
    //若被授权,则授权者是谁 

    char account[110]; //账号 
    char password[110];//密码 
}person[1100];

struct File {
    int state; 
    //文件的密级 
    //-1:unknown      未定密的 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int state_time;//定密的时间 
    int state_year;//保密年限

    int handle;//定密者是谁

    char filename[110];//文件名 
    char key[11];
    //10位的权限码,用于控制知悉范围 
}file[1100];
int person_num = 0, file_num = 0;

void Import() {
    //Do somthing...... 
}

void Export() {
    //Do somthing......
}

void Work() {
    //Do somthing......
}
int main() {
    srand(time(NULL)); //初始化随机种子 
    Import();          //导入数据 
    Work();            //系统界面 
    Export();          //导出数据 
    return 0;
}

核心功能

​ 了解完了我们的大体设计框架,接下来就让我们看看我们这个系统的核心功能吧,在这次的简单定密工作数字化系统的设计和开发中,我们将涉密人员划分为了超级管理员和定密工作者,他们在系统中有着不同的权限,使用着不同的功能,我们一一看来。

​ 超级管理员有两个权限:

  1. 增加涉密人员。即为新进定密人员生成账号、密码和可以定密的密级等信息。
  2. 增加待定密文件。即添加新的文件到待定密库中,后续有权限的涉密人员可以阅读和定密。

​ 而涉密人员有四个权限:

  1. 使用文件。上面提到过,文件分为不涉密的、待定密的、秘密的、机密的和绝密的。涉密人员只能使用不涉密的文件或者凭借权限码阅读涉密文件。权限码是在定密时自动生成的,用于控制知悉范围的十位数字码。
  2. 文件定密。有定密权的涉密人员可以对待定密的文件进行定密。但是定密的密级不能超过定密人员自身能定密的等级,文件的保密年限也不能超过秘密十年、机密二十年、绝密三十年的限制。
  3. 秘密变更。定密人员可以有权修改自己之前定密的密件的相关信息,包括密级和年限等。但是修改密级后,年限仍然要受到从第一次定密算起秘密十年、机密二十年、绝密三十年的限制。
  4. 定密授权。授权定密是在日常工作非常常用的一个功能,涉密工作者 $A$ 可以通过这个功能,将自己拥有的定密权授予给 $B$ 。当然在B的账号中会记录这个定密权是从谁来的,方便在日常工作中责任担当的问题。

效果展示

登陆界面

​ 我们点击 $System.exe$ 进入我们的程序。首先系统会自动导入信息并且检查是否有过期的密件:

2.png

​ 下来我们会看到登录界面,在登录界面中,我们会自动判断是否存在这个账号以及输入的密码是否正确,只有账号存在并且密码正确我们才会进入到系统内。在这里我还做了一点小小的特技,就是把我们的密码替换成 $$ 的样式。不管我们输入什么,在界面上都只会显示 $$ ,这样更加保障了我们保密工作者的账号安全。
3.png

管理员界面

​ 当我们登录的账号是管理员账号的时候,我们进入的就是管理员系统,看到的就是管理员界面。我们可以看到在这个界面中,我们可以通过输入数字的方式进入到想要进入到的功能。

4.png

​ 我们先来看看增加涉密人员账号的界面。在这一步中,我们也是可以通过键盘输入新增的涉密人员账号信息来添加涉密人员账号。在全部都输入完成后我们按回车,就能看到添加成功的字样,并且会在短暂的等待后直接跳转回到我们涉密人员的系统界面。

5.png

​ 接下来我们来看看增加待定密文件的界面。在这一步中,我们可以通过文件名的方式新增一个新的待定密空文件,随后可以在我们的数据库 $Unknown$ 文件夹下看到我们新增的文件。这时我们作为管理员,就可以把里面的文字填补好,留给各位定密人员随后定密了。

6.png

7.png

定密工作者界面

​ 当我们以普通涉密人员的身份登录时,我们的系统会自动跳转到涉密人员的系统界面。在这个界面当中,我们仍然时通过键盘输入操作数字的方式进行交互的。

8.png

​ 我们先来看看使用文件的界面,这里还是要强调一下,我们之前管理员访问的那些文件夹都是有密码保护的,只有 $Use$ 文件夹是我们的涉密人员能够访问的文件夹。所以我们使用文件的这个功能的本质就是验证是否有资格使用这个文件,如果有权限,则把这个文件从数据库中传输到涉密人员能够看到的 $Use$ 文件夹当中。在使用文件的界面中,我们需要输入我们想要使用的文件名,如果该文件是不涉密的,那么就可以直接取出;反之如果是涉密文件,则需要输入授权码之后才能取出阅读。

9.png

10.png

11.png

​ 我们接下来看看文件定密这个功能。当我们进入文件定密这个功能后,我们可以通过输入文件名来获取我们想要定密的文件,待仔细阅读后,我们可以对该文件的密级和保密期限进行限定。当然如果其中输入有不合法的话,系统都会提醒重新输入。在完成定密后,系统也会生成知悉码也就是我们的授权码,用于给予知悉范围内的人员让他们有权利访问我们这个涉密文件。

12.png

​ 我们再来看看秘密变更的操作。这个功能和上面的定密功能非常类似,我们可以为自己之前定密的文件进行密级和保密期限的修改,当然也会生成新的知悉码也就是我们的授权码。这一步中的要求和上一步中一样,如果有不符合规范的信息,都会被系统提醒重新输入。

13.png

​ 我们最后来看看定密授权的操作。在这一步的操作中,我们可以通过输入想要授权人员的账号来将自己的定密权授予给指定的人。当然被授权的人的账号中也会记录是谁授权给了他。

14.png

退出界面

​ 当我们退出系统的时候,会看到我们的操作被自动保存了,并且出现了工作辛苦了的字样。当我们下次再次启动系统的时候,就会自动恢复系统中的人员和文件信息到当前进度。

15.png

代码实现

​ 了解了我们程序运行的概况,下面让我们一起来看看我们的系统是如何实现的吧。

导入数据

​ 在系统启动的时候,我们的系统主要要做两件事,一个是将我们的数据从记录中导入;第二个是通过当前计算机时间检查有没有涉密文件过了保密期,如果有的话我们将会将其自动解密。我们先来看看如何导入数据,这个其实很简单,我们只需要使用文件输入操作,从我们的备份文件中读入相关信息就可以了。

void Import() {
    FILE *fina = fopen("Person.txt","r");
    FILE *finb = fopen("File.txt", "r");

    //读入人员信息 
    fscanf(fina, "%d", &person_num);
    for(int i = 1; i <= person_num; i++) {
        fscanf(fina, "%d", &person[i].admin);
        fscanf(fina, "%s", person[i].account);
        fscanf(fina, "%s", person[i].password);
        fscanf(fina, "%d", &person[i].secret_state);
        fscanf(fina, "%d", &person[i].origin_secret_state);
        fscanf(fina, "%d", &person[i].from_person);
    }

    //读入涉密文件信息 
    fscanf(finb, "%d", &file_num);
    for(int i = 1; i <= file_num; i++) {
        fscanf(finb, "%s", file[i].filename);
        fscanf(finb, "%d", &file[i].state);
        fscanf(finb, "%d", &file[i].state_time);
        fscanf(finb, "%d", &file[i].handle);
        fscanf(finb, "%s", file[i].key);
    }

    //检查是否有密件过期 
    Check(); 
    fclose(fina);
    fclose(finb);
    return ;
}

​ 下面我们来看看如何检查我们的密件是否过期,首先我们需要一个函数 int GetTime() 来获取我们当前计算机的时间并且转化为形如 $20200706$ 这样的年份加上月份加上日期的八位数。接下来我们就只需要遍历每一个文件,比较我们当前的时间是否超过了某些文件的保密期。如果是的话我们就修改其密级为未涉密的,并且将其移动到数据库中的不涉密文件夹中。

int GetTime() { //获得当前时间并且格式化 
    time_t now = time(0);
    tm *ltm = localtime(&now);

    int ans = 0;
    ans = (1900 + ltm -> tm_year) * 10000 + (1 + ltm -> tm_mon) * 100 + ltm -> tm_mday;

    return ans;
}

void Check() { //检查过期密件 
    printf("正在进行过期检查\n"); 
    int now_time = GetTime();
    for(int i = 1; i <= file_num; i++) {
        if(file[i].state_time + file[i].state_year * 10000 >= now_time && file[i].state >= 1) {
            string from, to;
            string secret, now_secret; 
            if(file[i].state == 1) now_secret = "./Secret/";
            else if(file[i].state == 2) now_secret = "./Confidential/";
            else if(file[i].state == 3) now_secret = "./Top-secret/";

            string name(file[i].filename);
            from = now_secret + name + ".txt";
            to = "./Unclassified/" + name + ".txt";
            CopyFileA(from.c_str(), to.c_str(), false);
            printf("%s已过保密期,自动解密中……\n");
        }
    }
    printf("检查完成!");
    Sleep(1000);
    system("cls");
    return ; 
}

导出数据

​ 导出数据和导入数据十分类似,不过少了检查过期密件的步骤。在这一步中,我们只需要通过文件的相关操作,将我们现有的数据保存或者说备份到我们的文件当中就可以了,这里就不过多赘述了。

void Export() {
    printf("工作辛苦了,数据正在备份……\n");
    FILE *fouta = fopen("Person.txt","w");
    FILE *foutb = fopen("File.txt", "w");

    fprintf(fouta, "%d\n", person_num);
    for(int i = 1; i <= person_num; i++) {
        fprintf(fouta, "%d ", person[i].admin);
        fprintf(fouta, "%s ", person[i].account);
        fprintf(fouta, "%s ", person[i].password);
        fprintf(fouta, "%d ", person[i].secret_state);
        fprintf(fouta, "%d ", person[i].origin_secret_state);
        fprintf(fouta, "%d\n", person[i].from_person);
    }

    fprintf(foutb, "%d\n", file_num);
    for(int i = 1; i <= file_num; i++) {
        fprintf(foutb, "%s ", file[i].filename);
        fprintf(foutb, "%d ", file[i].state);
        fprintf(foutb, "%d ", file[i].state_time);
        fprintf(foutb, "%d ", file[i].handle);
        fprintf(foutb, "%s\n", file[i].key);
    }

    fclose(fouta);
    fclose(foutb);
    printf("数据备份成功,再见!");

    return;
}

系统主体

登录窗口

​ 在我们的数字化系统中,最简单但也是最基础的就是我们的登录系统了。在登录系统中,我们的程序会通过你输入的用户名和已有的账户注意比较,看看是否存在,如果存在的话,再看看输入的密码是否正确。这里有一点需要注意,由于输入密码的时候周围可能有其他人,为了保障账号的安全,我们应该用 $*$ 去替换我们密码中的字符显示在我们的窗口中。在确认正确登陆后,我们最后再区分一下是跳转到管理员窗口还是定密工作者窗口就好啦,所以这部分的代码如下:

void password(char *p) {  //获得密码并替换为* 
    int n = 0;
    while(1) {
        p[n] = getch();
        if(p[n] == '\r' || p[n] == '\n')break;
        if(p[n] == '\b') {
            printf("\b");
            printf(" ");
            printf("\b");
            n--;
            if(n >= 0) n--;
        } 
        else printf("*");
        n++;
    }
    p[n]='\0';
    printf("\n");
    //printf("\n密码是:%s\n",p);
    return ;
}

void Work() {  //登录系统 
    char temp[1100];
    int flag = 0;
    printf("欢迎使用定密工作数字管理系统\n");
    while(1) {
        printf("请输入账号:"); scanf("%s", temp);
        flag = 0;
        while(flag == 0) {
            for(int i = 1; i <= person_num; i++) {
                if(!strcmp(temp, person[i].account)) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) {
                printf("无此账号,请重新输入账号:");
                scanf("%s", temp);
            }
        }

        printf("请输入密码:"); password(temp);
        if(!strcmp(temp, person[flag].password)) {
            printf("登录成功!\n");
            break; 
        } 
        else printf("密码错误,登陆失败请重试!\n");
    }
    Sleep(1000);
    if(person[flag].admin) Admin_windows();
    else Normal_windows(flag);
}

管理员功能

​ 管理员主要有两个功能,增加涉密人员账号和增加待定密文件,我们一个一个来看。

​ 首先是增加涉密人员,这一步很简单,我们只需要读入涉密人员的相关信息,比如账号、密码和定密权限存储到我们的人员信息当中就好啦。当然我们中间也要增加一些异常检测房子存入了奇奇怪怪的东西。下面是这部分的代码:

system("cls");
person_num++;
printf("请输入涉密人员账号:"); scanf("%s", str); strcpy(person[person_num].account, str);
printf("请输入涉密人员密码:"); scanf("%s", str); strcpy(person[person_num].password, str);
printf("请输入涉密人员定密权限(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);
while(strlen(str) != 1 || !(str[0] >= '1' && str[0] <= '3')) {
    printf("输入格式错误,请重新输入定密权限:");
    scanf("%s", str);
}
person[person_num].origin_secret_state = person[person_num].secret_state = str[0] - '0';
person[person_num].from_person = 0;
printf("添加成功,即将返回主界面!");
Sleep(1000);

​ 接着是增加待定密文件,这个需要用到一些文件的操作。我们首先需要读入我们的文件名,然后将文件的密级之类的信息先初始化一下。接着就是要使用 $Windows$ 的文件操作函数在我们的 $Unknown$ 文件夹下添加这个文件。下面是这部分的代码:

system("cls");file_num++; printf("请输入文件名:"); cin >> path; strcpy(file[file_num].filename, path.c_str());file[file_num].state = -1;file[file_num].state_year = file[file_num].state_time = file[file_num].handle = 0;strcpy(file[file_num].key, "2333333333");path = "./Unknown/" + path + ".txt";FILE *fout = fopen(path.c_str(), "w");fclose(fout);printf("添加成功,即将返回主界面!");Sleep(1000);

定密工作者功能

​ 定密工作者主要有四个功能,查看文件、文件定密、秘密变更和定密授权,我们一个一个来看。

​ 首先是查看文件。首先我们要读入涉密人员想要查看的文件名,然后我们就遍历整个文件目录,看看有没有这个文件。如果不存在的话我们就要返回文件不存在的相关信息然后返回主界面。如果存在的话我们要看一看这个文件是涉密的还是非涉密的,如果已经被定密是非涉密的或者已经到期自动解除秘密的,我们就可以直接查看。如果是涉密文件或者未定密的文件,则需要我们的授权码才能查看文件。下面是这部分的代码:

system("cls");printf("请输入你想要阅读的文件名:"); cin >> path;int flag = 0;for(int i = 1; i <= file_num; i++) {    if(!strcmp(path.c_str(), file[i].filename)) {       flag = i;       break;  }}if(flag == 0) printf("不存在这个文件,即将返回主界面!"); else {  string from, to;    string secret;  if(file[flag].state == 0) {     secret = "./Unclassified/";     from = secret + path + ".txt";      to = "./Use/" + path + ".txt";      CopyFileA(from.c_str(), to.c_str(), false);     printf("这是不涉密的文件,已经复制到你的文件夹中!\n");  }   else if(file[flag].state == -1) printf("该文件正在定密,请稍后再查询!\n");    else {      printf("这个是涉密文件,请输入访问口令:"); scanf("%s", temp);      if(!strcmp(temp, file[flag].key)) {         if(file[flag].state == 1) secret = "./Secret/";         else if(file[flag].state == 2) secret = "./Confidential/";          else if(file[flag].state == 3) secret = "./Top-secret/";                        from = secret + path + ".txt";          to = "./Use/" + path + ".txt";          CopyFileA(from.c_str(), to.c_str(), false);         printf("口令正确,已经复制到你的文件夹中!\n");      }       else  printf("口令错误,查看失败!\n");   }   printf("即将返回主界面!");}Sleep(1000);

​ 其次是文件定密。和查看文件类似的,我们要读入涉密人员想要定密的文件的文件名,然后我们就遍历整个文件目录,看看有没有这个待定密文件。如果不存在的话我们就要返回文件不存在的相关信息然后返回主界面。如果有的话我们先把文件发送到定密人员的文件夹下,待其仔细阅读后,我们记录其给该文件确定的密级和保密期限。这里需要注意的是,定密人员给文件定的密级不能超过他自身的定密权限,而且保密期限也不能超过秘密十年、机密二十年、绝密三十年的限制。在读入完信息后,我们就要更新这个文件的相关信息,并且在数据库中,将其从未定密的文件夹转移到他密级对应的文件夹。下面是这部分的代码:

system("cls");printf("请输入你想要定密的文件名:"); cin >> path;int flag = 0;for(int i = 1; i <= file_num; i++) {    if(!strcmp(path.c_str(), file[i].filename) && file[i].state == -1) {        flag = i;       break;  }}if(flag == 0) printf("不存在这个待定密文件,即将返回主界面!"); else {   string from, to;    string secret, now_secret;  now_secret = "./Unknown/";          from = now_secret + path + ".txt";  to = "./Use/" + path + ".txt";  CopyFileA(from.c_str(), to.c_str(), false); printf("该涉密文件已放入到你的文件夹中!\n");       printf("仔细阅读后,请输入定密的密级:(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);  while(strlen(str) != 1 || !(str[0] >= '0' && str[0] <= '3')) {      printf("输入格式错误,请重新输入定密的密级:");       scanf("%s", str);   }       if(str[0] - '0' <= person[now].secret_state) {      char Year[110];     file[flag].state =  str[0] - '0';       file[flag].state_time = GetTime();      int year;       printf("定密成功,");        aomi:       printf("定密成功,请输入保密期限:"); scanf("%s", Year);     while(!((strlen(Year) == 1 || (strlen(Year) == 2 && ((Year[0] >= '0' && Year[0] <= '9'))))  && (Year[0] >= '1' && Year[0] <= '9'))) {           printf("输入格式错误,请重新输入定密的密级:");           scanf("%s", Year);      }               if(strlen(Year) == 1) year = Year[0] - '0';     else year = (Year[0] - '0') * 10 + (Year[1] - '0');     if(year <= file[flag].state * 10) {         file[flag].state_year = year;           for(int j = 0; j < 10; j++) file[flag].key[j] = rand() % 10 + '0';          file[flag].handle = now;                        if(file[flag].state == 0) secret = "./Unclassified/";           else if(file[flag].state == 1) secret = "./Secret/";            else if(file[flag].state == 2) secret = "./Confidential/";          else if(file[flag].state == 3) secret = "./Top-secret/";            from = now_secret + path + ".txt";          to = secret + path + ".txt";            MoveFileA(from.c_str(), to.c_str());            printf("定密成功!该文件的知悉码为%s,请控制好知悉范围\n", file[flag].key);       }       else {          printf("您设置的年限太长,请重新输入!\n");            goto aomi;      }           }   else printf("您的权限不够,请向上级申请授权,定密失败!\n");     printf("即将返回主界面!");}Sleep(1000);

​ 再次是秘密变更。这一部分和上一部分的定密也是十分类似的。唯一需要注意的是,定密人员只能对自己本人定密的文件做出相关信息的变更。在读入完信息后,我们也是更新这个文件的相关信息,并且在数据库中,将其从未定密的文件夹转移到他密级对应的文件夹。下面是这部分的代码:

system("cls");printf("请输入你想要更改定密的文件名:"); cin >> path;int flag = 0;for(int i = 1; i <= file_num; i++) {  if(!strcmp(path.c_str(), file[i].filename) && file[i].handle == now && file[i].state >= 0) {        flag = i;       break;  }}if(flag == 0) printf("不存在这个您之前定密的文件,即将返回主界面!"); else {    string from, to;    string secret, now_secret;  if(file[flag].state == 0) secret = "./Unclassified/";   else if(file[flag].state == 1) now_secret = "./Secret/";    else if(file[flag].state == 2) now_secret = "./Confidential/";  else if(file[flag].state == 3) now_secret = "./Top-secret/";        from = now_secret + path + ".txt";  to = "./Use/" + path + ".txt";  CopyFileA(from.c_str(), to.c_str(), false); printf("该涉密文件已放入到你的文件夹中!\n");       printf("仔细阅读后,请输入定密的密级:(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);  while(strlen(str) != 1 || !(str[0] >= '1' && str[0] <= '3')) {      printf("输入格式错误,请重新输入定密的密级:");       scanf("%s", str);   }       if(str[0] - '0' <= person[now].secret_state) {      char Year[110];     file[flag].state =  str[0] - '0';       //file[flag].state_time = GetTime();        int year;       printf("定密成功,");        aomib:      printf("定密成功,请输入保密期限:"); scanf("%s", Year);     while(!((strlen(Year) == 1 || (strlen(Year) == 2 && ((Year[0] >= '0' && Year[0] <= '9'))))  && (Year[0] >= '1' && Year[0] <= '9'))) {           printf("输入格式错误,请重新输入定密的密级:");           scanf("%s", Year);      }               if(strlen(Year) == 1) year = Year[0] - '0';     else year = (Year[0] - '0') * 10 + (Year[1] - '0');     if(year <= file[flag].state * 10) {         file[flag].state_year = year;           for(int j = 0; j < 10; j++) file[flag].key[j] = rand() % 10 + '0';          file[flag].handle = now;                        if(file[flag].state == 0) secret = "./Unclassified/";           else if(file[flag].state == 1) secret = "./Secret/";            else if(file[flag].state == 2) secret = "./Confidential/";          else if(file[flag].state == 3) secret = "./Top-secret/";            from = now_secret + path + ".txt";          to = secret + path + ".txt";            MoveFileA(from.c_str(), to.c_str());            printf("定密成功!该文件的知悉码为%s,请控制好知悉范围\n", file[flag].key);       }       else {          printf("您设置的年限太长,请重新输入!\n");            goto aomib;     }           }   else printf("您的权限不够,请向上级申请授权,定密失败!\n");     printf("即将返回主界面!");}Sleep(1000);

​ 最后是定密授权。这一部分比较简单,我们只需要读入被授权人的账号信息,检测是否有这个人和这个人当前有没有这个定密权限就可以了。最后记得变更被授权人的密级和被授权信息。这里有一点是需要注意的,就是我们的涉密权限是分为现在的涉密权限和原始的涉密权限,我们授权是只能授权自己原始的定密权限给他人的。这里就保证了不会反复授权的问题。下面是代码实现:

system("cls");  printf("请输入你想授权的人的账号:"); scanf("%s", str);  int flag = 0;   for(int i = 1; i <= person_num; i++) {      if(!strcmp(person[i].account, str)) {           flag = i;           break;      }   }   if(flag == 0) printf("无此用户,即将返回主界面!");  else {      if(person[now].origin_secret_state > person[flag].secret_state) {           person[flag].secret_state = person[now].origin_secret_state;            person[flag].from_person = now;         printf("授权成功!即将返回主界面!");        }       else printf("该用户已经有这项定密权了,授权失败!");  }   Sleep(1000);}else break;

完整程序

#include <set>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <conio.h>
#include <string.h>
#include <cstdlib>
#include <cstring>
#include <windows.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct Person {
    int admin; 
    //是否是超级管理员 

    int secret_state; 
    //现有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int origin_secret_state;
    //原有的定密权(包括被授权) 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int from_person;
    //若被授权,则授权者是谁 

    char account[110]; //账号 
    char password[110];//密码 
}person[1100];

struct File {
    int state; 
    //文件的密级 
    //-1:unknown      未定密的 
    //0:Unclassified  不涉密的 
    //1:Secret        秘密级定密权 
    //2:Confidential  机密级定密权 
    //3:Top-secret    绝密级定密权 

    int state_time;//定密的时间 
    int state_year;//保密年限

    int handle;//定密者是谁

    char filename[110];//文件名 
    char key[11];
    //10位的权限码,用于控制知悉范围 
}file[1100];
int person_num = 0, file_num = 0;

int GetTime() { //获得当前时间并且格式化 
    time_t now = time(0);
    tm *ltm = localtime(&now);

    int ans = 0;
    ans = (1900 + ltm -> tm_year) * 10000 + (1 + ltm -> tm_mon) * 100 + ltm -> tm_mday;

    return ans;
}

void Check() { //检查过期密件 
    printf("正在进行过期检查\n"); 
    int now_time = GetTime();
    for(int i = 1; i <= file_num; i++) {
        if(file[i].state_time + file[i].state_year * 10000 >= now_time && file[i].state >= 1) {
            string from, to;
            string secret, now_secret; 
            if(file[i].state == 1) now_secret = "./Secret/";
            else if(file[i].state == 2) now_secret = "./Confidential/";
            else if(file[i].state == 3) now_secret = "./Top-secret/";

            string name(file[i].filename);
            from = now_secret + name + ".txt";
            to = "./Unclassified/" + name + ".txt";
            CopyFileA(from.c_str(), to.c_str(), false);
            printf("%s已过保密期,自动解密中……\n");
        }
    }
    printf("检查完成!");
    Sleep(1000);
    system("cls");
    return ; 
}
void Import() {
    FILE *fina = fopen("Person.txt","r");
    FILE *finb = fopen("File.txt", "r");

    //读入人员信息 
    fscanf(fina, "%d", &person_num);
    for(int i = 1; i <= person_num; i++) {
        fscanf(fina, "%d", &person[i].admin);
        fscanf(fina, "%s", person[i].account);
        fscanf(fina, "%s", person[i].password);
        fscanf(fina, "%d", &person[i].secret_state);
        fscanf(fina, "%d", &person[i].origin_secret_state);
        fscanf(fina, "%d", &person[i].from_person);
    }

    //读入涉密文件信息 
    fscanf(finb, "%d", &file_num);
    for(int i = 1; i <= file_num; i++) {
        fscanf(finb, "%s", file[i].filename);
        fscanf(finb, "%d", &file[i].state);
        fscanf(finb, "%d", &file[i].state_time);
        fscanf(finb, "%d", &file[i].handle);
        fscanf(finb, "%s", file[i].key);
    }

    //检查是否有密件过期 
    Check(); 
    fclose(fina);
    fclose(finb);
    return ;
}

void Export() {
    printf("工作辛苦了,数据正在备份……\n");
    FILE *fouta = fopen("Person.txt","w");
    FILE *foutb = fopen("File.txt", "w");

    fprintf(fouta, "%d\n", person_num);
    for(int i = 1; i <= person_num; i++) {
        fprintf(fouta, "%d ", person[i].admin);
        fprintf(fouta, "%s ", person[i].account);
        fprintf(fouta, "%s ", person[i].password);
        fprintf(fouta, "%d ", person[i].secret_state);
        fprintf(fouta, "%d ", person[i].origin_secret_state);
        fprintf(fouta, "%d\n", person[i].from_person);
    }

    fprintf(foutb, "%d\n", file_num);
    for(int i = 1; i <= file_num; i++) {
        fprintf(foutb, "%s ", file[i].filename);
        fprintf(foutb, "%d ", file[i].state);
        fprintf(foutb, "%d ", file[i].state_time);
        fprintf(foutb, "%d ", file[i].handle);
        fprintf(foutb, "%s\n", file[i].key);
    }

    fclose(fouta);
    fclose(foutb);
    printf("数据备份成功,再见!");

    return;
}

void Admin_windows() {
    char temp[110], str[110];
    string path;
    int type;
    while(1) {
        system("cls");
        printf("管理员欢迎您!请输入数字进行操作:\n");
        printf("1.增加涉密人员\n");
        printf("2.增加待定密文件\n");
        printf("3.退出系统\n"); 

        printf("请输入您的操作:"); scanf("%s", temp);
        while(strlen(temp) != 1 || !(temp[0] >= '1' && temp[0] <= '3')) {
            printf("输入格式错误,请重新输入操作:");
            scanf("%s", temp);
        }

        if(temp[0] == '1') {
            system("cls");
            person_num++;
            printf("请输入涉密人员账号:"); scanf("%s", str); strcpy(person[person_num].account, str);
            printf("请输入涉密人员密码:"); scanf("%s", str); strcpy(person[person_num].password, str);
            printf("请输入涉密人员定密权限(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);
            while(strlen(str) != 1 || !(str[0] >= '1' && str[0] <= '3')) {
                printf("输入格式错误,请重新输入定密权限:");
                scanf("%s", str);
            }
            person[person_num].origin_secret_state = person[person_num].secret_state = str[0] - '0';
            person[person_num].from_person = 0;
            printf("添加成功,即将返回主界面!");
            Sleep(1000);
        }
        else if(temp[0] == '2') {
            system("cls");
            file_num++; 
            printf("请输入文件名:"); cin >> path; strcpy(file[file_num].filename, path.c_str());
            file[file_num].state = -1;
            file[file_num].state_year = file[file_num].state_time = file[file_num].handle = 0;
            strcpy(file[file_num].key, "2333333333");

            path = "./Unknown/" + path + ".txt";
            FILE *fout = fopen(path.c_str(), "w");
            fclose(fout);
            printf("添加成功,即将返回主界面!");
            Sleep(1000);
        }
        else break;
    }
    return ;
}

void Normal_windows(int now) {
    char temp[110], str[110];
    string path;
    int type;
    while(1) {
        system("cls");
        printf("涉密人员欢迎您!请输入数字进行操作:\n");
        printf("1.使用文件\n");
        printf("2.文件定密\n");
        printf("3.秘密变更\n");
        printf("4.定密授权\n");
        printf("5.退出系统\n"); 

        printf("请输入您的操作:"); scanf("%s", temp);
        while(strlen(temp) != 1 || !(temp[0] >= '1' && temp[0] <= '5')) {
            printf("输入格式错误,请重新输入操作:");
            scanf("%s", temp);
        }

        if(temp[0] == '1') {
            system("cls");
            printf("请输入你想要阅读的文件名:"); cin >> path;
            int flag = 0;
            for(int i = 1; i <= file_num; i++) {
                if(!strcmp(path.c_str(), file[i].filename)) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) printf("不存在这个文件,即将返回主界面!"); 
            else {
                string from, to;
                string secret; 
                if(file[flag].state == 0) {
                    secret = "./Unclassified/";
                    from = secret + path + ".txt";
                    to = "./Use/" + path + ".txt";
                    CopyFileA(from.c_str(), to.c_str(), false);
                    printf("这是不涉密的文件,已经复制到你的文件夹中!\n"); 
                }
                else if(file[flag].state == -1) printf("该文件正在定密,请稍后再查询!\n");
                else {
                    printf("这个是涉密文件,请输入访问口令:"); scanf("%s", temp);
                    if(!strcmp(temp, file[flag].key)) {
                        if(file[flag].state == 1) secret = "./Secret/";
                        else if(file[flag].state == 2) secret = "./Confidential/";
                        else if(file[flag].state == 3) secret = "./Top-secret/";

                        from = secret + path + ".txt";
                        to = "./Use/" + path + ".txt";
                        CopyFileA(from.c_str(), to.c_str(), false);
                        printf("口令正确,已经复制到你的文件夹中!\n"); 
                    }
                    else  printf("口令错误,查看失败!\n"); 
                }
                printf("即将返回主界面!");
            }
            Sleep(1000);
        }
        else if(temp[0] == '2') {
            system("cls");
            printf("请输入你想要定密的文件名:"); cin >> path;
            int flag = 0;
            for(int i = 1; i <= file_num; i++) {
                if(!strcmp(path.c_str(), file[i].filename) && file[i].state == -1) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) printf("不存在这个待定密文件,即将返回主界面!"); 
            else {
                string from, to;
                string secret, now_secret; 
                now_secret = "./Unknown/";

                from = now_secret + path + ".txt";
                to = "./Use/" + path + ".txt";
                CopyFileA(from.c_str(), to.c_str(), false);
                printf("该涉密文件已放入到你的文件夹中!\n"); 

                printf("仔细阅读后,请输入定密的密级:(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);
                while(strlen(str) != 1 || !(str[0] >= '0' && str[0] <= '3')) {
                    printf("输入格式错误,请重新输入定密的密级:");
                    scanf("%s", str);
                }

                if(str[0] - '0' <= person[now].secret_state) {
                    char Year[110];
                    file[flag].state =  str[0] - '0';
                    file[flag].state_time = GetTime();
                    int year;
                    printf("定密成功,");
                    aomi:
                    printf("定密成功,请输入保密期限:"); scanf("%s", Year);
                    while(!((strlen(Year) == 1 || (strlen(Year) == 2 && ((Year[0] >= '0' && Year[0] <= '9'))))  && (Year[0] >= '1' && Year[0] <= '9'))) {
                        printf("输入格式错误,请重新输入定密的密级:");
                        scanf("%s", Year);
                    }

                    if(strlen(Year) == 1) year = Year[0] - '0';
                    else year = (Year[0] - '0') * 10 + (Year[1] - '0');
                    if(year <= file[flag].state * 10) {
                        file[flag].state_year = year;
                        for(int j = 0; j < 10; j++) file[flag].key[j] = rand() % 10 + '0';
                        file[flag].handle = now; 

                        if(file[flag].state == 0) secret = "./Unclassified/";
                        else if(file[flag].state == 1) secret = "./Secret/";
                        else if(file[flag].state == 2) secret = "./Confidential/";
                        else if(file[flag].state == 3) secret = "./Top-secret/";
                        from = now_secret + path + ".txt";
                        to = secret + path + ".txt";
                        MoveFileA(from.c_str(), to.c_str()); 
                        printf("定密成功!该文件的知悉码为%s,请控制好知悉范围\n", file[flag].key);
                    } 
                    else {
                        printf("您设置的年限太长,请重新输入!\n");
                        goto aomi;
                    }

                }
                else printf("您的权限不够,请向上级申请授权,定密失败!\n");

                printf("即将返回主界面!");
            }
            Sleep(1000);
        }
        else if(temp[0] == '3') {
            system("cls");
            printf("请输入你想要更改定密的文件名:"); cin >> path;
            int flag = 0;
            for(int i = 1; i <= file_num; i++) {
                if(!strcmp(path.c_str(), file[i].filename) && file[i].handle == now && file[i].state >= 0) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) printf("不存在这个您之前定密的文件,即将返回主界面!"); 
            else {
                string from, to;
                string secret, now_secret; 
                if(file[flag].state == 0) secret = "./Unclassified/";
                else if(file[flag].state == 1) now_secret = "./Secret/";
                else if(file[flag].state == 2) now_secret = "./Confidential/";
                else if(file[flag].state == 3) now_secret = "./Top-secret/";

                from = now_secret + path + ".txt";
                to = "./Use/" + path + ".txt";
                CopyFileA(from.c_str(), to.c_str(), false);
                printf("该涉密文件已放入到你的文件夹中!\n"); 

                printf("仔细阅读后,请输入定密的密级:(0:非密,1:秘密,2:机密,3:绝密):"); scanf("%s", str);
                while(strlen(str) != 1 || !(str[0] >= '1' && str[0] <= '3')) {
                    printf("输入格式错误,请重新输入定密的密级:");
                    scanf("%s", str);
                }

                if(str[0] - '0' <= person[now].secret_state) {
                    char Year[110];
                    file[flag].state =  str[0] - '0';
                    //file[flag].state_time = GetTime();
                    int year;
                    printf("定密成功,");
                    aomib:
                    printf("定密成功,请输入保密期限:"); scanf("%s", Year);
                    while(!((strlen(Year) == 1 || (strlen(Year) == 2 && ((Year[0] >= '0' && Year[0] <= '9'))))  && (Year[0] >= '1' && Year[0] <= '9'))) {
                        printf("输入格式错误,请重新输入定密的密级:");
                        scanf("%s", Year);
                    }

                    if(strlen(Year) == 1) year = Year[0] - '0';
                    else year = (Year[0] - '0') * 10 + (Year[1] - '0');
                    if(year <= file[flag].state * 10) {
                        file[flag].state_year = year;
                        for(int j = 0; j < 10; j++) file[flag].key[j] = rand() % 10 + '0';
                        file[flag].handle = now; 

                        if(file[flag].state == 0) secret = "./Unclassified/";
                        else if(file[flag].state == 1) secret = "./Secret/";
                        else if(file[flag].state == 2) secret = "./Confidential/";
                        else if(file[flag].state == 3) secret = "./Top-secret/";
                        from = now_secret + path + ".txt";
                        to = secret + path + ".txt";
                        MoveFileA(from.c_str(), to.c_str()); 
                        printf("定密成功!该文件的知悉码为%s,请控制好知悉范围\n", file[flag].key);
                    } 
                    else {
                        printf("您设置的年限太长,请重新输入!\n");
                        goto aomib;
                    }

                }
                else printf("您的权限不够,请向上级申请授权,定密失败!\n");

                printf("即将返回主界面!");
            }
            Sleep(1000);
        }
        else if(temp[0] == '4') {
            system("cls");
            printf("请输入你想授权的人的账号:"); scanf("%s", str);
            int flag = 0;
            for(int i = 1; i <= person_num; i++) {
                if(!strcmp(person[i].account, str)) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) printf("无此用户,即将返回主界面!");
            else {
                if(person[now].origin_secret_state > person[flag].secret_state) {
                    person[flag].secret_state = person[now].origin_secret_state;
                    person[flag].from_person = now;
                    printf("授权成功!即将返回主界面!");
                }
                else printf("该用户已经有这项定密权了,授权失败!");
            } 
            Sleep(1000);
        }
        else break;
    }
    return ;
}

void password(char *p) {  //获得密码并替换为* 
    int n = 0;
    while(1) {
        p[n] = getch();
        if(p[n] == '\r' || p[n] == '\n')break;
        if(p[n] == '\b') {
            printf("\b");
            printf(" ");
            printf("\b");
            n--;
            if(n >= 0) n--;
        } 
        else printf("*");
        n++;
    }
    p[n]='\0';
    printf("\n");
    //printf("\n密码是:%s\n",p);
    return ;
}

void Work() {  //登录系统 
    char temp[1100];
    int flag = 0;
    printf("欢迎使用定密工作数字管理系统\n");
    while(1) {
        printf("请输入账号:"); scanf("%s", temp);
        flag = 0;
        while(flag == 0) {
            for(int i = 1; i <= person_num; i++) {
                if(!strcmp(temp, person[i].account)) {
                    flag = i;
                    break;
                }
            }
            if(flag == 0) {
                printf("无此账号,请重新输入账号:");
                scanf("%s", temp);
            }
        }

        printf("请输入密码:"); password(temp);
        if(!strcmp(temp, person[flag].password)) {
            printf("登录成功!\n");
            break; 
        } 
        else printf("密码错误,登陆失败请重试!\n");
    }
    Sleep(1000);
    if(person[flag].admin) Admin_windows();
    else Normal_windows(flag);
}
int main() {
    srand(time(NULL)); //初始化随机种子 
    Import();          //导入数据 
    Work();            //系统界面 
    Export();          //导出数据 
    return 0;
}

由于功能较为复杂,完整的程序非常长,如果感兴趣的话可以点击下面的链接下载我整个程序包。

Secret.rar

总结和不足

​ 在这次的实验中,我独自开发了这个简单的定密工作化数字系统。不过恰逢考试周时间比较紧张,许多其他功能比如辅助定密、年审等功能都未能按时实现,还是有一些小缺憾的。不过这个框架已经较为完整了,希望我拙劣的代码能给定密工作系统的开发者一点点小小的启发吧。

Last modification:September 7th, 2021 at 10:44 pm
If you think my article is useful to you, please feel free to appreciate