实验报告
密码引擎部分
1-OpenEuler-OpenSSL编译
一、下载最新的OpenSSL源码(1.1版本)
二、用自己的8位学号建立一个文件夹,cd 你的学号,用pwd获得绝对路径
三、参考https://www.cnblogs.com/rocedu/p/5087623.html先在Ubuntu中完成OpenSSL编译安装,然后在OpenEuler中重现./config --prefix=..(学号目录的绝对路径)指定OpenSSL编译链接
四、提交 test_openssl.c 编译运行截图
五、加分项:在Windows中编译OpenSSL,记录编译过程,提交相关文档(推荐MarkDown格式)
2-电子钥匙功能测试
证书导出
生成证书
在Ubuntu中运行 “龙脉密码钥匙驱动实例工具等\mToken-GM3000\skf\samples\linux_mac”中例程
安装GM3000
加分项:运行“龙脉密码钥匙驱动实例工具等\mToken-GM3000\skf\samples\windows”中例程
3-加密API研究
查找各种标准的原始文档,研究学习(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)
(1)Crypto API
Windows CryptoAPI是Microsoft 公司提出的安全加密应用服务框架,也是PKI推荐使用的加密 API。它提供了在Win32 环境下使用认证、编码、加密和签名等安全服务时的标准加密接口,用于增强应用程序的安全性与可控性。应用开发者可以在不了解复杂的加密机制和加密算法的情况下,简便、快速地开发出标准、通用和易于扩展的安全加密应用程序。
CryptoAPI 提供的功能主要有:密钥管理、数据加密和解密、数字签名和验证、证书管理、可信根证书管理、数据编码和解码、数字证书编码和解码、PKCS#7 标准格式编码和解码等。
CryptoAPI体系架构共由五大主要部分组成:基本CSP函数(Base Cryptographic Functions)、证书编解码函数(Certificate Encode/Decode Functions)、证书库管理函数(Certificate Store Functions),简单消息函数(Simplified Message Functions)、底层消息函数(Low-level Message Functions)。其结构图如下图所示。
Windows CryptoAPI是Microsoft 公司提出的安全加密应用服务框架,也是PKI推荐使用的加密 API。它提供了在Win32 环境下使用认证、编码、加密和签名等安全服务时的标准加密接口,用于增强应用程序的安全性与可控性。应用开发者可以在不了解复杂的加密机制和加密算法的情况下,简便、快速地开发出标准、通用和易于扩展的安全加密应用程序。CryptoAPI 提供的功能主要有:密钥管理、数据加密和解密、数字签名和验证、证书管理、可信根证书管理、数据编码和解码、数字证书编码和解码、PKCS#7 标准格式编码和解码等。
CryptoAPI体系架构共由五大主要部分组成:基本CSP函数(Base Cryptographic Functions)、证书编解码函数(Certificate Encode/Decode Functions)、证书库管理函数(Certificate Store Functions),简单消息函数(Simplified Message Functions)、底层消息函数(Low-level Message Functions)。其结构图如下图所示。
-
基本加密函数:用于选择CSP、建立CSP连接、产生密钥、交换及传输密钥等操作。这些函数为开发加密应用程序提供了足够灵活的空间。所有CSP 的通讯都是通过这些函数,一个CSP 是实现所有加密操作的独立模块,于是在每一个加密应用程序中至少需要提供一个CSP来完成所需的加密操作。
-
证书编/解码函数:用于数据加密、解密、哈希等操作。这类函数支持数据的加密/解密操作;在应用程序中完成计算哈希、创建和校验数字签名操作;用来对证书、证书撤销列表、证书请求和证书扩展进行编码和解码操作。
-
证书库管理函数:用于数字证书及证书库管理等操作。这组函数用于管理证书、证书撤销列表和证书信任列表的使用、储存、获取等。
-
简单消息函数:用于消息处理,比如消息编码/解码、消息加/解密、数字签名及签名验证等操作。它是把多个低层函数包装在一起以完成某个特定任务,以方便用户的使用。
-
底层消息函数:低级消息函数对传输的PKCS#7 数据进行编码,对接收到的PKCS#7 数据进行解码,并且对接收到的消息进行解密和验证。它可以实现简单消息函数可以实现的所有功能,它提供更大的灵活性,但一般会需要更多的函数调用。对于绝大多数应用,我们不推荐使用低级消息函数,使用简化消息函数更为方便。
-
基本加密函数:用于选择CSP、建立CSP连接、产生密钥、交换及传输密钥等操作。这些函数为开发加密应用程序提供了足够灵活的空间。所有CSP 的通讯都是通过这些函数,一个CSP 是实现所有加密操作的独立模块,于是在每一个加密应用程序中至少需要提供一个CSP来完成所需的加密操作。
-
证书编/解码函数:用于数据加密、解密、哈希等操作。这类函数支持数据的加密/解密操作;在应用程序中完成计算哈希、创建和校验数字签名操作;用来对证书、证书撤销列表、证书请求和证书扩展进行编码和解码操作。
-
证书库管理函数:用于数字证书及证书库管理等操作。这组函数用于管理证书、证书撤销列表和证书信任列表的使用、储存、获取等。
-
简单消息函数:用于消息处理,比如消息编码/解码、消息加/解密、数字签名及签名验证等操作。它是把多个低层函数包装在一起以完成某个特定任务,以方便用户的使用。
-
底层消息函数:低级消息函数对传输的PKCS#7 数据进行编码,对接收到的PKCS#7 数据进行解码,并且对接收到的消息进行解密和验证。它可以实现简单消息函数可以实现的所有功能,它提供更大的灵活性,但一般会需要更多的函数调用。对于绝大多数应用,我们不推荐使用低级消息函数,使用简化消息函数更为方便。
(2)PKCS#11
在密码系统中,PKCS#11是公钥加密标准(PKCS, Public-Key Cryptography Standards)中的一份子 ,由RSA实验室(RSA Laboratories)发布[1],它为加密令牌定义了一组平台无关的API ,如硬件安全模块和智能卡。
PKCS#11的对象可根据其生命期长短的不同分成两大类:一类是持久存储的类对象,这类对象被保存在USB Key的安全存储区域当中,直到应用程序主动删除这些对象;另一类是会话对象,这类对象只存在于运行时建立的特定会话(Session对象)当中,一旦会话结束,这类对象也跟着被删除。决定对象生命期的模板属性是CKA_TOKEN,这是个布尔值,所有的对象都有这一属性。当该值为TRUE时,该对象将被保存到Key内的存储空间,否则,该对象保存在会话空间中,当会话结束后,该对象即销毁。
-
指令列表
-
架构
(3)GMT 0016-2012
本标准规定了基于PKI密码体制的智能密码钥匙密码应用接口,描述了密码应用接口函数、数据类型、参数的定义和设备安全要求。适用于智能密码钥匙产品的研制、使用和检测。
智能密码钥匙密码应用接口位于智能密码钥匙应用程序与设备之间,如下图:
设备的应用结构:一个设备中存在设备认证密钥和多个应用,应用之间相互独立。设备的逻辑结构如下图:
设备管理系列函数
访问控制系列函数:
应用管理函数:
容器管理系列函数:
密码服务系列函数:
(4)GMT 0018-2012
-
规范性引用文件
下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件,凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件。
GM/T0006密用标识规范 GM/T0009SM2密码算法使用规范 -
术语和定义
算法标识algorithm ideutifier
用于对密码算法进行唯一标识的符号。
非对称密码算法/公钥密码算法 asymmetric cryptographic algorithm/public key cryptographic algorithm加解密使用不同密钥的密码算法。
解密 decipherment/decryption加密过程对应的逆过程。
设备密钥device key pair
存储在设备内部的用于设备管理的非对称密钥对包含签名密钥对和加密密钥对。
加密encipherment/encryption
对数据进行密码变换以产生密文的过程。
密钥加密密钥key encrypt key;KEK对密钥进行加密保护的密钥。
公钥基础设施public key infrastructure;PKI
用公钥密码技术建立的普遍适用的基础设施,为用户提供证书管理和密钥管理等安全服务。
私钥访问控制码private key access password
用于验证私钥使用权限的口令字。
对称密码技术/对称密码体制 symmetric cryptographic technique
原发者和接收者均采用同秘密密钥进行变换的密码技术(体制)。其中,加密密钥与解密密钥相同或者一个密钥可以从另一个密钥导出的密码体制。
会话密钥session key
处于层次化密钥结构中的最低层,仅在一次会话中使用的密钥。
用户密钥 user key
存储在设备内部的用于应用密码运算的非对称密钥,包含签名密钥对和加密密钥对。 -
符号和缩略语
ECC 椭圆曲线算法(Elliptic Curve Cryptography)
IPK 内部加密公钥(Internal Public Key)
ISK
内部加密私钥(Interal Private Key) EPK
外部加密公钥(Extenal Public Key) KEK 密钥加密密钥(Key Encrypt Key)
总结这些API在编程中的使用方式
(1)Crypto API
使用CryptoAPI编写一个文件保护程序,具有如下功能:
(1)给定明文文件,生成加密文件,同时产生文件的数字签名文件;
(2)给定密文文件,解密出明文文件,并验证签名的正确性。
在不安全的网络上进行安全的数据传输涉及三个方面的要求:信息隐藏,身份鉴别和完整性检验。CryptoAPI除了提供上述三个功能外还提供标准的ASN.1编码、解码,信息解密,数字证书和证书存储区的管理,证书信任列表、吊销列表和证书有效性检查等功能。
1.信息隐藏
信息隐藏的意义是保障信息内容只能被特定的人获取。信息隐藏通常是使用某种形式的密码学方式。数据加密算法能保障信息的安区隐藏和传输。数据加密算法是将明文数据经过一定的变换使其看上去是一组毫无意义的数据。在没有加密密钥的情况下,对于好的加密算法想从密文获取明文信息是不可能的。被加密的数据可以是任意的ASCII编码文本文件,数据库文件,和任意需要进行安全传输的数据。这里,“信息”是指任意的一段数据,“明文”是指任意一段没有被加密的数据,“密文”是指任意一段加密的数据。被加密的数据可以在不安全的通道上进行传输而不伤害其安全性。之后,密文可以被还原成明文。
数据加密和解密的概念是:对数据加密的时候需要一个加密密钥,相当于门上的一把钥匙。解密的时候,需要使用一个解密密钥来解开数据。加密密钥、解密密钥可以相同也可以不相同。
加密密钥必须小心保存,给其它用户的时候也必须通过安全的通道传递。对解密密钥的访问权限必须小心控制,因为拥有解密密钥意味着可以解开所有相应加密密钥加密的信息。
2.身份鉴别
安全通讯的前提是通讯的双方知道对方的身份。身份鉴别的任务就是鉴别一个用户或者实体的真实身份。标识用户身份的文档通常被称为信任状或者凭证。
身份鉴别有时候也用来判定接受的数据就是被发送的数据。如果A向B发送了一段数据,B需要鉴别这段数据就是A发出去的,而不是其它冒充A发出去的。为了满足这类验证的需求,CryptoAPI提供数字签名和校验函数,用来对信息进行鉴别。
因为在计算机网网络上传输的数据与用户之间并没有物理连接,因此对数据进行鉴别的凭证也必须能够在网络上进行传输。这种凭证必须由受信任的凭证发行机构发行。
数字证书就是平常说的证书就是这种凭证,是计算机在网络上进行身份验证的有效凭证。
数字证书是由一个被称为证书机构的信任组织或实体颁发的凭证。它包含与证书对应的用户公钥以及其它一些记录证书主题和用户信息的数据。证书机构只有在验证了证书主题和证书对应的用户公钥的有效性之后才会签发证书。
证书申请者和证书机构之间交换签发证书信息可以使用物理介质,比如软盘,进行传输。通常,这种信息都是在计算机网络上进行完成的。证书机构使用被信任的服务程序处理用户的请求和证书的签发工作。
3.完整性检验
任何通过不安全介质传输的信息都可以被意外或蓄意的修改。在现实世界中,盖章、签名就是用来提供和证明信息完整性的工具。
信息的接收者不但需要确定信息是由谁发送的,还要确定自己收到的信息是发送者发送的信息,而没有任何的变化。要建立数据的完整性检测机制,不仅要发送信息本身,还要发送用来校验数据的信息,这一信息通常被称作哈希值。数据和验证信息都可以与数字签名一起发送来证明其完整性。
(2)PKCS#11
1.架构
2.会话状态
3.对象
(3)GMT 0016-2012
层次关系
智能密码钥匙密码应用接口位于智能密码钥匙应用程序与设备之间,如下图所示。
应用结构
(4)GMT 0018-2012
在公钥密码基础设施应用技术体系框架中,密码设备服务层由密码机,密码卡,智能密码终端等设备组成,通过本标准规定的密码设备应用接口向通用密码服务层提供基础密码服务。如下图所示。
基础密码服务包括密钥生成、单一的密码运算、文件管理等的服务。
本标准采用C语言描述接口函数。如无特别说明,函数中参数的长度单位均为字节数。
列出这些API包含的函数,进行分类,并总结它们的异同
(1)Crypto API
主要函数:
主函数
void main(void)
加密文件
BOOL EncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
解密文件
BOOL DecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
签名文件
BOOL SignFile (PCHAR szSource, PCHAR szDestination);
验证签名
BOOL VerifyFile (PCHAR szSource, PCHAR szDestination);
错误处理
void HandleError(char *s);
加密文件:
打开源文件
hSource = fopen(szSource,"rb")
取得密钥容器(CSP)句柄
CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)
根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件加密)
//创建一个Hash对象
CryptCreateHash(hCryptProv,CALG_MD5, 0, 0, &hHash)
//用用户输入的密码产生一个散列
CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0)
//通过散列生成一个会话密钥
CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM,hHash, KEYLENGTH, &hKey))
//销毁Hash对象
CryptDestroyHash(hHash);
/*会话密钥即对称密钥,用于对原文件进行加密;非对称密钥由于效率非常低,所以一般不用于对数据直接加密,而是对会话密钥进行加密,然后把它传送给对方。对 方通过非对称密钥解密获得这个会话密钥,然后再对数据文件进行解密。可以看出,一个会话密钥的生存期可以限制在这次通信中,即每次通信都用不同的会话密钥 加密,而非对称密钥则必须是长期使用的。在此例中,加解密过程中没有使用到非对称 RSA密钥对,而只在数字签名及验证使用它。*/
加密数据文件
CryptEncrypt(hKey, //密钥
0, //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输
//入FALSE这里通过判断是否到文件尾来决定是否为最后一块
0, //保留
pbBuffer, //输入被加密数据,输出加密后的数据
&dwCount, //输入被加密数据实际长度,输出加密后数据长度
dwBufferLen) //pbBuffer的大小
/*注:查看完整代码时可以发现这是一个循环加密的过程,pbBuffer循环读入待加密文件的固定长度的内存块;当然你也可以将pbBuffer设得很大,一次读入整个文件,但那样浪费内存空间,而且影响扩展性(存在缓冲区溢出的可能)。*/
清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);
解密文件:
打开加密文件(同上)
取得密钥容器(CSP)句柄(同上)
根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件解密)(同上)
这里要求用户输入的密码与加密时输入的密码相同。在实际应用中,这个所谓用户输入的“密码”其实只是一个产生密钥的种子,一旦产生完会话密钥,则用户完全可以忘记当初输入的“密码”,接收方可以使用传过来的密钥直接对加密文件进行解密,而不用再重复一次“生成密钥”的过程。
解密数据文件
CryptDecrypt(hKey, //密钥
0, //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
//入FALSE这里通过判断是否到文件尾来决定是否为最后一块。
0, //保留
pbBuffer, //输入被加密数据,输出加密后的数据
&dwCount)) //输入被加密数据实际长度,输出加密后数据长度
清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
签名文件:
打开源文件(同上)
取得密钥容器(CSP)句柄(同上)
取得签名用的密钥句柄(非对称RSA密钥)
CryptGetUserKey(hCryptProv, // 我们已经得到的CSP句柄
AT_SIGNATURE, // 这里想得到signature key pair
&hKey)) // 返回密钥句柄
导出签名用密钥对的公钥,保存在pbKeyBlob中
CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)
计算数据文件的Hash值,保存在Hash对象hHash中
//生成一个空的Hash对象
CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)
//计算数据文件的Hash值,保存在Hash对象中
CryptHashData(hHash,pbBuffer,dwCount,0)
对数据文件的Hash值进行签名,数字签名保存在pbSignature中
CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)
清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
签名文件:
打开源文件(同上)
取得密钥容器(CSP)句柄(同上)
取得签名用的密钥句柄(非对称RSA密钥)
CryptGetUserKey(hCryptProv, // 我们已经得到的CSP句柄
AT_SIGNATURE, // 这里想得到signature key pair
&hKey)) // 返回密钥句柄
导出签名用密钥对的公钥,保存在pbKeyBlob中
CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)
计算数据文件的Hash值,保存在Hash对象hHash中
//生成一个空的Hash对象
CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)
//计算数据文件的Hash值,保存在Hash对象中
CryptHashData(hHash,pbBuffer,dwCount,0)
对数据文件的Hash值进行签名,数字签名保存在pbSignature中
CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)
清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
验证签名:
打开文件(同上)
取得密钥容器(CSP)句柄(同上)
导入 pbKeyBlob 公钥
CryptImportKey(hCryptProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)
必须是与签名时所用的私钥配对的公钥,在此例中,这个公钥在生成数字签名时已经导出到pbKeyBlob中。
计算数据文件的Hash值,保存在Hash对象hHash中。(同上)
验证数字签名
CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL, 0)
清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
(2)PKCS#11
根据机制标记,可以分为几类:
CKF_ENCRYPT:加密类
CKF_DECRYPT:解密类
CKF_DIGEST:摘要类
CKF_SIGN:签名类
CKF_SIGN_RECOVER:可恢复签名类
CKF_VERIFY:验证类
CKF_VERIFY_RECOVER:可恢复验证类
CKF_GENERATE:密钥产生
CKF_GENERATE_KEY_PAIR:密钥对产生
CKF_WRAP:密钥封装
CKF_UNWRAP:密钥解封
CKF_DERIVE:密钥派生
(3)GMT 0016-2012
(4)GMT 0018-2012
下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件,凡是不注日期的引用文件,其最新版本(包括所有的修单)适用于本文件,
GM/T0006 密码应用标识规范 和GM/T0009 SM2密码算法使用规范
以龙脉GM3000Key为例,写出调用不同接口的代码(Crypto API,PKCS#11,SKF接口),把运行截图加入博客,并提供代码链接
(1)Crypto API
龙脉密码钥匙驱动实例工具等\mToken-GM3000\csp\samples\CryptAPI\VC\EncryptDecryptFile\EncryptFile.sln
要在当前目录下先创建 20201209.txt
龙脉密码钥匙驱动实例工具等\mToken-GM3000\csp\samples\CryptAPI\VC\EnumCerts\EnumCerts.sln
(2)PKCS#11
1.龙脉密码钥匙驱动实例工具等\mToken-GM3000\pkcs11\windows\samples\PKCStest\PKCStest.sln
(1)DES
(2)DES3
(3)RC2
(4)RC4
(5)RSA
(6)AES
(3)SKF接口
龙脉密码钥匙驱动实例工具等\mToken-GM3000\skf\samples\windows\EncryptData\EncryptData.sln
4-国䀄算法交叉测试
2人一组,创建一个文件,文件名为小组成员学号,内容为小组成员学号和姓名
在Ubuntu中使用OpenSSL用SM4算法加密上述文件,然后用龙脉eKey解密,提交代码和运行结果截图
在Ubuntu中基于OpenSSL产生一对公私钥对(SM2算法)
1.创建EC参数和原始私钥文件:
注:生成完成后可以查看一下EC私钥信息:
然后验证一下参数:
2.将原始的私钥文件,转换为pkcs8格式:
3.利用原始的私钥,生成对应的公钥:
至此SM2的秘钥对已经生成结束,pri_key_pkcs8.pem是SM2私钥,而pub_key.pem是公钥。
在Ubuntu中使用OpenSSL用SM3算法计算上述文件的Hash值,然后用OpenSSL SM2算法计算Hash值的签名,用龙脉eKey进行验签,提交代码和运行结果截图
加分项:在Windows中重现上述过程
电子公文传输系统安全性设计与实现部分
电子公文传输系统的设计部分:
一、设计目标
提高行政工作效率:电子公文传输系统可以实现电子化办公,减少了纸质公文的使用和传输,缩短了传输时间,节约了人力和物力资源,提高了办公效率。
提高行政工作质量:电子公文传输系统可以实现对管理员的密码进行加密管理,保证了公文系统的安全性。保障公文的真实性和保密性,降低了公文信息泄露的风险,提高了办公质量。
提高行政工作透明度:电子公文传输系统可以实现公文流转的透明化和公开化,方便了行政机关内部和社会公众对公文流转进程和结果的监督和评价。在系统中的每个用户能够根据自己的权限看到,相关的信息。密级高的信息则是进行了严格保密的的。
实现行政信息化:电子公文传输系统可以与行政机关管理信息系统相连,我们的公文传输系统有着一键归档的功能,通过建立归档的文件夹,然后将内容进行归档处理,实现公文信息的自动化管理和处理,提高了行政管理的科学化和规范化水平。
降低行政成本:电子公文传输系统可以减少纸张、印章、快递、邮寄等行政成本,同时也加快了公文传输速度,降低了行政工作的成本和时间成本。
二、组成内容
公文系统的组成包括以下内容:
1.文件格式:公文系统应支持各种常见的公文格式,包括红头、版面等。在文件传输和下载时使用PDF格式,防止被篡改和保证文件传输时不出现格式改变。
2.文件接收:公文系统的接收功能可实现电子公文接收、扫描件接收,接收范围按照用户权限设置,收到公文后可进入收文箱,在公文处理完成后进入文件归档。
3.文件归档:公文系统的文件归档功能可将文件按照用户设定的规则进行归档,例如按照发文时间、文件类型等分类归档,同时支持打标签、搜索等高级功能。
4.文件发送:公文系统的发送功能可以将已写好的公文文件发送给指定人员或者部门,在发送时可以进行安全控制,确保公文安全。
5.管理员用户功能:公文系统应提供管理员用户功能,管理员能够管理公文系统的基础数据,例如机构、用户、角色、权限等的管理。
6.公文写作:公文系统应支持公文的写作、编辑、格式控制、附件管理,公文撰写过程中应有自动保存功能,避免因为操作失误导致数据丢失。
综上所述,我们组队公文系统是一个涵盖公文的整个生命周期的系统,包括公文的接收、审核、处理、发送、归档、查询等功能,同时支持各种常见的公文格式,提高公文处理效率,真正实现电子化办公。
三、架构设计
公文系统的组成包括前端、后端和数据库三部分:
前端主要由View层编写,包括网页端的界面设计、呈现和交互逻辑等。
界面设计:设计公文系统界面的样式和布局,进行交互元素的处理,包括页面头部、底部、导航条、按钮等元素,以及页面表格、列表等的样式设计和排版。
交互逻辑:制定前端交互逻辑,设定页面的流程和功能,包括用户登录、公文查看、公文编辑、公文流转等功能的处理。
后端主要由Bath或其他编程语言编写,包括服务器端的逻辑处理,数据库管理、安全保障等。
服务器端逻辑:负责公文系统所有接口的实现,包括用户登录、公文编辑、公文查询、公文权限控制、公文流转等功能的实现。
数据库管理:使用数据库管理工具navicat对公文系统的整体数据库进行管理,包括公文信息、用户信息、日志信息等的存储和管理。
安全保障:负责公文系统的安全保障措施,包括安全验证、加解密处理、访问控制等。
我们的公文系统采用前后端分离的架构,通过API进行前后端数据的传递和交互。同时也需要进行系统测试和维护,确保公文系统的正常运行和稳定性。
四、下一步改进
1.增加业务逻辑:公文系统应该根据实际的业务需求,增加相应的业务逻辑,例如增加会议管理、工作计划等功能,从而实现更加全面的业务覆盖。
2.强化安全保障:公文系统中的安全保障措施应该更加完善,例如增加对公文的数字签名、加密、认证等安全控制,防止信息泄露和篡改。
3.提高效率:公文系统应该在处理效率方面进行优化,例如增加自动化流程控制和批量处理功能,缩短公文处理时间,提高办公效率。
4.优化用户体验:公文系统应该优化用户体验,例如提高系统的响应速度,改善界面设计,加强用户教育和培训等。
5.数据可视化分析:公文系统应该增加数据可视化分析功能,例如统计公文的处理状态和效率,分析公文流程的瓶颈,提供数据支持决策。
五、系统概述
我们的电子公文传输系统一共由13个网页组成:
-
1.login.js
这段代码是一个前端代码中常用的API接口请求代码,使用的库是http,其中包括了多个函数,分别用于不同的请求类型:
apiGetCaptcha:用于获取验证码图片的函数,使用的是get请求,参数为params;
apiLogin:用于用户登录的函数,使用的是post请求,参数为params;
apiAdminLogin:用于管理员登录的函数,使用的是post请求,参数为params;
apiLogout:用于用户注销登录的函数,使用的是post请求,参数为params;
apiSendCodeMsg:用于向用户发送验证码的函数,使用的是get请求,参数为params;
apiForgetPassword:用于用户忘记密码后找回密码的函数,使用的是post请求,参数为params;
apiRegister:用于用户注册的函数,使用的是post请求,参数为params。
这些函数都是用于与后端接口进行交互,完成各种用户操作的。例如,用户登录、注册、找回密码等操作都需要通过这些函数与后端接口进行交互,从而实现用户的操作需要
-
2.CategoryAPI.js
这段代码是一组用于学科管理的API接口,其主要功能是实现对学科的增删改查等操作。
这些API接口是通过调用一个名为"http"的模块来实现网络请求的。该模块提供了get、post、put等方法来实现不同的网络请求方式。通过调用这些API接口,可以实现对学科列表的管理,包括增删改查、申请、审核等操作。 -
3.logAPI.js
本段代码主要实现了对日志的增加、修改、删除、查询等操作,并分别对应不同的接口地址。
总的来说,这段代码提供了完整的日志管理的接口,方便开发者进行业务开发,并且提供了各种接口来满足不同需求的使用。
-
4.orgAPI.js
该代码段是一个学科组织的RESTful API接口集合。使用了JavaScript语言编写,后端应该采用了Node.js技术。其中,使用了模块化的技术,导出各个接口函数。
可以看出,该代码段主要用于管理学科组织,提供了非常丰富的API接口,可以满足各种需求。开发者可以根据自己的实际需求进行接口的选择和使用。
-
5.UserAPI.js
上述代码是一个使用Vue框架的前端项目中的一部分,其中定义了一些关于用户管理的API接口。
其中,apiUserList接口用于获取用户列表,apiUserPage接口用于获取分页后的用户列表,apiUserListAll接口用于获取所有用户信息,apiUserOne接口用于获取单个用户信息,apiUserSelf接口用于获取当前用户的信息,apiUserAdd接口用于新增用户,apiUserUpdate接口用于更新用户信息,apiUserCharge接口用于用户充值,apiUserDel接口用于删除用户,apiUserBan接口用于禁用用户。
这些接口都是通过http请求访问后端API服务进行数据的增删改查操作。在前端项目中,这些API接口将被应用于用户管理模块,使用户能够进行相应的用户管理操作。
-
6.FileTypeAPI.js
以上代码是一个文件类型管理的API接口,包含对文件类型的增删改查等操作。总体而言,这些API接口提供了文件类型管理相关的各种操作,并且针对不同的用户和角色,提供了不同层次的数据访问权限控制。
-
7.FileSendAPI.js
这段代码是一个文件传输模块的接口API,主要包括以下功能:
文件传输列表的获取:通过调用apiFileSendList和apiFileSendSelf函数,以GET方法获取文件传输列表,区别在于apiFileSendList获取整个列表,而apiFileSendSelf获取与用户相关的列表。
文件传输页面的获取:通过调用apiFileSendPage函数,以GET方法获取指定页数和页大小的文件传输列表。
文件传输的添加:通过调用apiFileSendAdd函数,以POST方法添加一条文件传输记录。
文件传输的更新:通过调用apiFileSendUpdate函数,以PUT方法更新一条文件传输记录。
文件传输的删除:通过调用apiFileSendDel函数,以DELETE方法删除一条文件传输记录。
文件传输的审核:通过调用apiFileSendChecked函数,以GET方法获取需要审核的文件传输列表。
文件传输的申请:通过调用apiFileSendApply函数,以GET方法获取需要申请的文件传输列表。
文件传输的关闭:通过调用apiFileSendClose函数,以GET方法关闭指定的文件传输。
用户相关文件传输的获取:通过调用apiFileSendEmpSelf函数,以GET方法获取与用户相关的文件传输列表。
文件传输的接受和拒绝:通过调用apiFileSendAccept和apiFileSendUnAccept函数,以GET方法接受或拒绝指定的文件传输。
-
8.FileCategoryListAPI.js
上述代码是一个前端项目中的API接口,通过调用定义的各个API函数,可以获取或发送对应的HTTP请求。
以上的API接口主要是用于文件分类列表相关的操作。其中,apiFileCategoryListList函数是获取文件分类列表并分页的函数;apiFileCategoryListAdd函数是新增一个文件分类的函数;apiFileCategoryListUpdate函数是更新某个文件分类的函数;apiFileCategoryListDel函数是删除某个文件分类的函数。
还有其他的函数,比如apiFileCategoryListSelf函数,可以获取用户自己创建的文件分类列表;apiFileCategoryListChecked函数,可以获取被选中的文件分类;apiFileCategoryListApply函数,可以获取当前申请的文件分类;apiFileCategoryListClose函数,可以关闭某个文件分类。
总之,以上的API接口覆盖了文件分类列表的基本操作,可以方便地实现对文件分类的管理。
-
9.FileCategoryAPI.js
上述代码涉及到一个文件类别管理的相关 API 接口,在具体实现上,这些功能都是通过向服务器发送不同的 HTTP 请求实现的,请求的路径和参数不同,从而区分不同的功能。其中使用到的 HTTP 请求库为 http,从前端代码中看不出具体实现方式。
-
10.FileAPI.js
上述代码是一个文件管理系统的前端接口请求模块,包含了一系列的API请求函数。
其中http和request是基于axios库进行封装的请求方法,params为请求参数。通过调用这些请求函数,能够实现与后端API进行数据交互的功能,实现文件管理系统的各项操作。
六、系统底层架构
-
1.Base controller
该代码为一个基础的控制器类,用于对某个实体类进行 CRUD 操作。其中根据要求实现了增加、分页、按 id 查找、按 id 删除和更新等常用操作,并在每个操作前使用了一个自定义注解 @LogAnno 来记录日志。其中要求实现的方法有:
save 方法,用于新增实体,接受一个 E 类型的参数,返回一个保存成功的消息。
list 方法,用于分页查询实体,接受两个 int 类型的参数 currentPage 和 size,返回一个 IPage类型的结果。
detail 方法,用于根据 id 查询实体,接受一个 Serializable 类型的参数 id,返回一个 R类型的结果。
delete 方法,用于根据 id 删除实体,接受一个 List类型的参数 ids,返回一个删除成功的消息。
update 方法,用于更新实体,接受一个 E 类型的参数,返回一个更新成功的消息。
page 方法,用于分页查询实体并根据名字模糊查询,接受三个参数:int 类型的 page 和 pageSize,和一个字符串类型的 name,返回一个 R类型的结果。
-
2.Category controller
本段代码是一个Java后端控制器类,用于处理与“类别”相关的请求。首先,它导入了一些需要用到的类和注解,并继承了一个BaseController类,说明它是一个实际处理请求的类。然后,它定义了一个CategoryService对象,并在listAll()方法中使用了LambdaQueryWrapper查询所有类别并返回。接下来,它使用了一个自定义的LogAnno注解,在delete()方法中记录了删除操作的日志,该方法会根据传入的id列表删除对应的数据,并在删除之前检查是否有属于该类别的用户存在,如果存在则返回错误信息,否则返回删除成功信息。这个类是整个类别管理模块的核心,处理了所有和类别有关的请求,包括添加、删除、查询和修改等。
-
3.Code controller
本文介绍了一个验证码控制器CodeController,使用了Spring框架进行开发。在这个控制器中,我们应用了注解和Kaptcha库,通过生成一张带有验证码的图片来防止机器人或恶意攻击者对网站进行攻击。
首先,我们需要引入一些依赖项和库。这个程序使用了com.google.code.kaptcha库来生成带有验证码的图片,并且使用了Lombok库来避免繁琐的日志记录。我们也使用了Spring的注解和依赖注入机制。这些库能够让我们更快、更加轻松地实现这个功能。
方法开始部分,我们首先设置了响应头的一些选项,阻止了浏览器对验证码图片进行缓存。接下来我们使用captchaProducer.createText()方法生成了图像上的验证码文本,并使用HttpSession API将文本存储到了会话中以便后续使用。然后,我们使用captchaProducer.createImage()方法根据验证码文本生成了一张验证码图片,并使用ImageIO.write()方法将其写入到响应的输出流中。
最后,我们在try-catch代码块中完成输出操作,并将输出流使用out.close()方法关闭,释放资源。
-
4.Common controller
本文介绍了一个用于文件上传和下载的通用控制器 CommonController。其中,使用了注解技术以及上传文件的 API 和操作下载文件的方法。
代码的核心功能是文件上传和下载。在代码中,实现了上传文件的功能。使用 File 类的对象将文件保存到给定的目录中。其次,提供了下载文件的方法,方法中,通过 FileInputStream 类和 ServletOutputStream 类,将指定目录下的文件发送到客户端,从而实现下载功能。
总体而言,CommonController 通过简洁的代码实现了文件上传和下载的功能,使用了注解、API 等技术手段使程序更加健壮,功能更加完善,很好地完成了上传和下载文件的任务。
-
5.File category controller
这份代码是一个文件分类控制器,其中定义了一些对文件分类的操作方法。
其中,第一个方法是listAll(),它通过LambdaQueryWrapper查询所有的文件分类,并通过R类进行封装并返回。
第二个方法是listSelf(),它通过LambdaQueryWrapper查询当前用户的所有文件分类,并通过R类进行封装并返回。
第三个方法是save(),它是一个POST请求,用于向数据库中新增一条文件分类信息。它首先会对新增的文件分类名称进行非空判断和是否已存在的校验,然后将当前用户ID设置到新增的文件分类中,并通过QueryWrapper进行查询,如果查询结果不为0,则返回错误信息,否则将新增的文件分类信息保存到数据库中,并通过R类进行封装并返回保存成功的信息。
整个代码实现了对文件分类的查询和新增操作,同时通过注解的方式实现了操作日志的记录。
-
6.File category list controller
该类中包含了两个主要的方法,一个是归档操作的方法,一个是按条件查询并分页显示列表的方法。
归档操作的方法将接收到的参数解析成文件和分类的id,然后构造一个文件分类对象,指定用户id,查询数据库中是否已有该文件分类的记录,如果有则更新记录,否则新增一条记录。最后返回一个成功的消息。
列表查询方法接收到分页和查询条件的参数,首先构造一个查询对象,在lambda表达式中指定查询条件,然后调用服务类的getVO方法获取指定页面的结果,并将结果封装成一个R对象返回给前端。在方法上加上了@LogAnno注解,用来记录用户浏览归档的行为。
-
7.Filesendcontroller
本文介绍了一个文件收发管理系统的Java代码,主要包含了文件收发的发送、接受、拒绝以及管理员和用户浏览文件信息的功能实现。对于发送文件,用户可以向指定接收者发送文件,发送成功后更新状态;对于接受文件,用户可以确认接受,管理员可以浏览所有文件信息;对于拒绝文件,用户可以拒绝该文件;对于浏览文件接收,用户和管理员可以根据条件进行筛选和浏览。
-
8.File type controller
以上代码是一个针对加密类别的控制器,在此控制器中,我们使用了MyBatis-Plus提供的LambdaQueryWrapper来构建查询条件,并使用baseService的list方法来查询所有的加密类别。在listAll方法中,我们将查询结果封装在R.success中,最终返回给前端。
-
9.Log controller
本文介绍了Java语言中的一个控制器类,该类可以对应用程序中的“日志”进行管理和操作。
这个控制器类实现了一个基础控制器类,方法包括浏览日志。控制器类还包括了一个list方法,可以对分页进行处理,并且可以对日志名称进行查询。在list方法中,使用了MyBatis-Plus的LambdaQueryWrapper,这是一个用于构造查询条件的工具类。
-
10.Org controller
本代码是一个组织控制器,主要包括删除组织和获取组织列表的功能。
其中,删除组织功能需要先检查组织中是否有用户存在,如果有则不能删除,否则可以删除,并返回删除结果。这里使用了一个注解 @LogAnno,记录了删除操作的类型。
获取组织列表功能直接返回了所有的组织列表。
代码中还注入了一个 UserService 和一个 OrgService,用于组织相关操作的服务。
此外,控制器还继承了一个 BaseController,该类封装了通用的控制器方法。
-
11.Usercontroller
本代码主要功能是实现用户登录验证。用户提交登录信息后,首先会判断角色是否为空,若为空则返回角色不可为空;然后判断验证码是否失效,若验证码失效,则返回验证码失效;接着判断用户输入的验证码是否正确,若不正确则返回验证码错误。当用户信息正确时,首先对用户密码进行MD5加密,然后通过查询数据库进行用户匹配,若用户不存在则返回用户不存在,若密码错误则返回密码错误。当用户存在且密码正确时,进一步查询用户状态,若用户已被禁用则返回账号已禁用。最终,若用户登录成功,则将用户ID存储在Session中,并返回登录成功信息。
七、安全性措施
加密算法的选择
为保证密码方案的安全性,我们组在UserController类中,我们增加角色时需要将口令进行加密处理。由于密码长度通常不会很长,因此我们采用了MD5算法,对用户输入的口令进行哈希运算并存入数据库中。