电子公文传输系统-个人贡献
个人完成的工作
博客的撰写与信息的汇总
后端程序代码的编写
PutinStorage.java
@csrf_exempt
def approveDocument(request):
current_user = request.session['username']
if request.method == 'POST':
data = json.loads(request.body)
document_name = data.get('documentName')
# 添加日志打印
print("Received document_name:", document_name)
try:
# 根据 document_id 获取对应的文档
document = Document.objects.get(document_name=document_name)
document.is_pass = 1
document.is_sent = 1
LogData = Log.objects.create(
username=current_user,
documentname=document.document_name,
operation=f'用户{current_user}于{timezone.now()}通过了公文:{document.document_name}。'
)
LogData.save()
document.save()
return JsonResponse({'message': 'Document status updated successfully'})
except Document.DoesNotExist:
print(f"Document with ID {document_name} does not exist.")
return JsonResponse({'message': 'Document does not exist'}, status=404)
except Exception as e:
print("Error:", e)
return JsonResponse({'message': 'Internal Server Error'}, status=500)
return JsonResponse({'message': 'Invalid request'}, status=400)
@csrf_exempt
def rejectDocument(request):
current_user = request.session['username']
if request.method == 'POST':
data = json.loads(request.body)
document_name = data.get('documentName')
doc_issuing_office = data.get('issuing_office')
# 添加日志打印
print("Received document_name:", document_name)
print("Received doc_issuing_office:", doc_issuing_office)
try:
# 根据 document_id 获取对应的文档
document = Document.objects.get(document_name=document_name)
document.is_pass = 0
document.is_sent = 0
document.document_owner = document.issuing_office
LogData = Log.objects.create(
username=current_user,
documentname=document.document_name,
operation=f'用户{current_user}于{timezone.now()}拒绝了公文:{document.document_name}。'
)
LogData.save()
document.save()
return JsonResponse({'message': 'Document status updated successfully'})
except Document.DoesNotExist:
print(f"Document with ID {document_name} does not exist.")
return JsonResponse({'message': 'Document does not exist'}, status=404)
except Exception as e:
print("Error:", e)
return JsonResponse({'message': 'Internal Server Error'}, status=500)
return JsonResponse({'message': 'Invalid request'}, status=400)
def decrypt_document(request):
current_user = request.session['username']
if request.method == 'POST':
# 获取传递的文件地址或其他必要信息
data = json.loads(request.body)
file_title = data.get('file_title')
file_name = data.get('file_name')
print(file_title)
print(file_name)
doc = Document.objects.get(document_name=file_title)
file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'docx', file_name)
print(file_path)
doc_owner = doc.issuing_office
cc_office = doc.cc_office
sender_keyowner = UserProfile.objects.get(id=doc_owner)
sender_publickey = sender_keyowner.public_key
sender_privatekey = sender_keyowner.private_key
key_owner = UserProfile.objects.get(username_up=cc_office)
publickey = key_owner.public_key
privatekey = key_owner.private_key
key_sign_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'sign', (file_title + 'signkey.dat'))
key_encrypt_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'key', (file_title + 'encryptkey.dat'))
verify_signature(public_key=sender_publickey,
private_key=sender_privatekey,
input_file=key_encrypt_path,
signature_file=key_sign_path)
key_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'key', (file_title + 'key.dat'))
decrypt_data(public_key=publickey,
private_key=privatekey,
input_file=key_encrypt_path,
output_file=key_path)
key = get_or_generate_key(file_title)
print(f'对称密钥的类型为:{type(key)}')
# 在这里执行文件解密的操作
decrypted_file_address = decrypt_and_hash_file(file_path, key, file_title)
LogData = Log.objects.create(
username=current_user,
documentname=doc.document_name,
operation=f'用户{current_user}于{timezone.now()}下载了公文:{doc.document_name}。'
)
LogData.save()
# 返回解密结果(成功或失败)
return JsonResponse({'message': '文件解密成功', 'decrypted_file_address': decrypted_file_address}) # 或者其他成功信息
else:
return JsonResponse({'message': '无效的请求'}, status=400)
## 密码功能实现
## SM4对称密码算法、SM3哈希摘要算法 ##
def get_or_generate_key(document_name):
# 尝试从外部输入获取密钥
key_file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'key', (document_name + 'key.dat'))
print(key_file_path)
if os.path.exists(key_file_path):
with open(key_file_path, 'rb') as key_file:
key = key_file.read()
print(key)
print(len(key))
if len(key) != 16:
print("密钥长度必须为16字节")
return None
else:
# 生成随机的16字节密钥
key = secrets.token_bytes(16)
with open(key_file_path, 'wb') as key_file:
key_file.write(key)
return key
def encrypt_and_hash_file(input_file_path, key, document_name):
# 读取文件内容
with open(input_file_path, 'rb') as file:
plaintext = file.read()
# 计算文件的哈希值
hash_value = sm3_hash(list(plaintext)) # Convert bytes to list
hash_file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'secure', (document_name + 'hash_original.dat'))
with open(hash_file_path, 'w') as hash_file:
hash_file.write(hash_value)
print(f'原文件的哈希值已保存到:{hash_file_path}')
# 初始化SM4加密器
crypt_sm4 = CryptSM4()
# 设置密钥
crypt_sm4.set_key(key, SM4_ENCRYPT)
# 加密文件内容
ciphertext = crypt_sm4.crypt_ecb(plaintext)
# 创建加密后的文件
encrypted_file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'docx', (document_name + '.enc'))
with open(encrypted_file_path, 'wb') as file:
file.write(ciphertext)
print(f'文件加密成功:{encrypted_file_path}')
def decrypt_and_hash_file(encrypted_file_path, key, document_name):
# 初始化SM4解密器
crypt_sm4 = CryptSM4()
# 设置密钥
crypt_sm4.set_key(key, SM4_DECRYPT)
# 读取加密文件内容
with open(encrypted_file_path, 'rb') as file:
ciphertext = file.read()
# 解密文件内容
plaintext = crypt_sm4.crypt_ecb(ciphertext)
# 创建解密后的文件
decrypted_file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'docxs', (document_name + '.docx'))
with open(decrypted_file_path, 'wb') as file:
file.write(plaintext)
print(f'文件解密成功:{decrypted_file_path}')
# 计算解密文件的哈希值
hash_value = sm3_hash(list(plaintext)) # Convert bytes to list
# 将哈希值保存到hash_decrypted.txt文件
hash_decrypted_file_path = os.path.join(settings.BASE_DIR, 'web', 'static', 'secure', (document_name + 'hash_decrypted.dat'))
with open(hash_decrypted_file_path, 'w') as hash_file:
hash_file.write(hash_value)
print(f'解密文件的哈希值已保存到:{hash_decrypted_file_path}')
# 比较原始哈希和解密后的哈希
hash_original_file = os.path.join(settings.BASE_DIR, 'web', 'static', 'secure',
(document_name + 'hash_original.dat'))
hash_decrypted_file = os.path.join(settings.BASE_DIR, 'web', 'static', 'secure',
(document_name + 'hash_decrypted.dat'))
with open(hash_original_file, 'rb') as original, open(hash_decrypted_file, 'rb') as decrypted:
original_hash = original.read()
decrypted_hash = decrypted.read()
if original_hash == decrypted_hash:
print("加密和解密后的文件内容一致。")
else:
print("加密和解密后的文件内容不一致。")
decrypted_file_path_str = f'/static/docxs/{document_name}'+'.docx'
return decrypted_file_path_str
## SM2算法实现 ##
## SM2密钥生成 ##
class CurveFp:
def __init__(self, A, B, P, N, Gx, Gy, name):
self.A = A
self.B = B
self.P = P
self.N = N
self.Gx = Gx
self.Gy = Gy
self.name = name
sm2p256v1 = CurveFp(
name="sm2p256v1",
A=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC,
B=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93,
P=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF,
N=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123,
Gx=0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7,
Gy=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
)
def multiply(a, n, N, A, P):
return fromJacobian(jacobianMultiply(toJacobian(a), n, N, A, P), P)
def add(a, b, A, P):
return fromJacobian(jacobianAdd(toJacobian(a), toJacobian(b), A, P), P)
def inv(a, n):
if a == 0:
return 0
lm, hm = 1, 0
low, high = a % n, n
while low > 1:
r = high // low
nm, new = hm - lm * r, high - low * r
lm, low, hm, high = nm, new, lm, low
return lm % n
def toJacobian(Xp_Yp):
Xp, Yp = Xp_Yp
return (Xp, Yp, 1)
def fromJacobian(Xp_Yp_Zp, P):
Xp, Yp, Zp = Xp_Yp_Zp
z = inv(Zp, P)
return ((Xp * z ** 2) % P, (Yp * z ** 3) % P)
def jacobianDouble(Xp_Yp_Zp, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
if not Yp:
return (0, 0, 0)
ysq = (Yp ** 2) % P
S = (4 * Xp * ysq) % P
M = (3 * Xp ** 2 + A * Zp ** 4) % P
nx = (M ** 2 - 2 * S) % P
ny = (M * (S - nx) - 8 * ysq ** 2) % P
nz = (2 * Yp * Zp) % P
return (nx, ny, nz)
def jacobianAdd(Xp_Yp_Zp, Xq_Yq_Zq, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
Xq, Yq, Zq = Xq_Yq_Zq
if not Yp:
return (Xq, Yq, Zq)
if not Yq:
return (Xp, Yp, Zp)
U1 = (Xp * Zq ** 2) % P
U2 = (Xq * Zp ** 2) % P
S1 = (Yp * Zq ** 3) % P
S2 = (Yq * Zp ** 3) % P
if U1 == U2:
if S1 != S2:
return (0, 0, 1)
return jacobianDouble((Xp, Yp, Zp), A, P)
H = U2 - U1
R = S2 - S1
H2 = (H * H) % P
H3 = (H * H2) % P
U1H2 = (U1 * H2) % P
nx = (R ** 2 - H3 - 2 * U1H2) % P
ny = (R * (U1H2 - nx) - S1 * H3) % P
nz = (H * Zp * Zq) % P
return (nx, ny, nz)
def jacobianMultiply(Xp_Yp_Zp, n, N, A, P):
Xp, Yp, Zp = Xp_Yp_Zp
if Yp == 0 or n == 0:
return (0, 0, 1)
if n == 1:
return (Xp, Yp, Zp)
if n < 0 or n >= N:
return jacobianMultiply((Xp, Yp, Zp), n % N, N, A, P)
if (n % 2) == 0:
return jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P)
if (n % 2) == 1:
return jacobianAdd(jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P), (Xp, Yp, Zp), A, P)
class PrivateKey:
def __init__(self, curve=sm2p256v1, secret=None):
self.curve = curve
self.secret = secret or SystemRandom().randrange(1, curve.N)
def publicKey(self):
curve = self.curve
xPublicKey, yPublicKey = multiply((curve.Gx, curve.Gy), self.secret, A=curve.A, P=curve.P, N=curve.N)
return PublicKey(xPublicKey, yPublicKey, curve)
def toString(self):
return "{}".format(str(hex(self.secret))[2:].zfill(64))
class PublicKey:
def __init__(self, x, y, curve):
self.x = x
self.y = y
self.curve = curve
def toString(self, compressed=True):
return {
True: str(hex(self.x))[2:],
False: "{}{}".format(str(hex(self.x))[2:].zfill(64), str(hex(self.y))[2:].zfill(64))
}.get(compressed)
## SM2加解密和签名验签 ##
def encrypt_data(public_key, private_key, input_file, output_file):
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
with open(input_file, 'rb') as f:
data = f.read()
print(public_key)
print(private_key)
print(type(public_key))
print(type(private_key))
encrypted_data = sm2_crypt.encrypt(data)
with open(output_file, 'wb') as f:
f.write(encrypted_data)
def decrypt_data(public_key, private_key, input_file, output_file):
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
with open(input_file, 'rb') as f:
encrypted_data = f.read()
decrypted_data = sm2_crypt.decrypt(encrypted_data)
with open(output_file, 'wb') as f:
f.write(decrypted_data)
def sign_data(public_key, private_key, input_file, signature_file):
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
with open(input_file, 'rb') as f:
data = f.read()
random_hex_str = func.random_hex(sm2_crypt.para_len)
signature = sm2_crypt.sign(data, random_hex_str)
with open(signature_file, 'wb') as f:
f.write(binascii.unhexlify(signature))
def verify_signature(public_key, private_key, input_file, signature_file):
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
with open(input_file, 'rb') as f:
data = f.read()
with open(signature_file, 'rb') as f:
signature = f.read()
if sm2_crypt.verify(binascii.hexlify(signature).decode(), data):
print("Signature verification successful")
else:
print("Signature verification failed")
def get_user_logs(request):
current_user = request.session.get('username')
user = UserProfile.objects.get(username_up=current_user)
print(user.username_up)
if user.access_level == 1: # 管理员权限
user_logs = Log.objects.filter(documentname="无") # 获取所有用户日志
user_logs_data = list(user_logs.values()) # 转换为字典列表
print(user_logs_data)
return JsonResponse(user_logs_data, safe=False)
if user.access_level != 1:
user_logs = Log.objects.filter(username=user.username_up, documentname="无")
user_logs_data = list(user_logs.values()) # 转换为字典列表
print(user_logs_data)
return JsonResponse(user_logs_data, safe=False)
def get_document_logs(request):
current_user = request.session.get('username')
user = UserProfile.objects.get(username_up=current_user)
if user.access_level == 1: # 管理员权限
document_logs = Log.objects.exclude(documentname="无") # 获取所有公文操作日志
document_logs_data = list(document_logs.values()) # 转换为字典列表
print(document_logs_data)
return JsonResponse(document_logs_data, safe=False)
if user.access_level != 1:
document_logs = Log.objects.exclude(documentname="无").filter(username=user.username_up)
document_logs_data = list(document_logs.values()) # 转换为字典列表
print(document_logs_data)
return JsonResponse(document_logs_data, safe=False)
def logout(request):
current_user = request.session['username']
# 清除会话信息
if 'user_id' in request.session:
LogData = Log.objects.create(
username=current_user,
documentname="无",
operation=f'用户{current_user}于{timezone.now()}退出了系统。'
)
LogData.save()
del request.session['user_id']
del request.session['username']
# 重定向到主页或登录页
return redirect('index') # 'index' 应该是你的主页 URL 名称或路径
def upload_avatar_page(request):
# 传递表单给模板,以便在页面上显示上传表单
form = AvatarUploadForm()
return render(request, 'upload_avatar.html', {'form': form})
def upload_avatar(request):
current_user = request.session.get('username') # 使用 get 方法以避免键不存在时引发 KeyError
if request.method == 'POST':
form = AvatarUploadForm(request.POST, request.FILES)
if form.is_valid():
try:
user_profile = UserProfile.objects.get(username_up=current_user)
avatar_image = form.cleaned_data['avatarFile']
image = Image.open(avatar_image)
# 将图像转换为PNG格式并覆盖原始图像文件
image = image.convert("RGB")
image.save(user_profile.avatar.path, 'JPEG')
user_profile.save()
return redirect('index') # 重定向到首页或其他页面
except UserProfile.DoesNotExist:
# 处理用户不存在的情况
pass
else:
form = AvatarUploadForm()
return render(request, 'upload_avatar.html', {'form': form})
上传代码至gitee
分配一些工作
小组代码总行数
- 3500行
我贡献的代码行数
- 500行
小组总文档数
- 11
我贡献的文档数
- 7