国内优秀个人网站线上建模培训班哪个好

当前位置: 首页 > news >正文

国内优秀个人网站,线上建模培训班哪个好,好的企业管理网站,怎么制作网站准考证在网上打印Python 实现高效的 SM4 大文件加密解密实战指南 引言 在数据安全领域#xff0c;使用对称加密算法如SM4进行数据保护非常常见。特别是当处理大文件时#xff0c;合理的内存和块大小管理以及加密解密效率变得尤为重要。本文将分享如何使用Python进行大文件的SM4加密解密操作使用对称加密算法如SM4进行数据保护非常常见。特别是当处理大文件时合理的内存和块大小管理以及加密解密效率变得尤为重要。本文将分享如何使用Python进行大文件的SM4加密解密操作并对代码进行优化加入异常处理和内存管理措施确保程序在处理大文件时的稳定性。 目录 背景介绍SM4算法概述挑战与解决方案填充处理的重要性大文件的分块处理完整代码实现 环境准备AlgorithmTool 类的实现SM4FileHelper 类的实现含详细注释 代码解析与说明 填充与去填充按块加密解密逻辑处理最后一个数据块 最佳实践与注意事项 内存优化异常处理安全性考虑 总结 背景介绍 SM4 是我国国家密码管理局制定的对称加密算法被广泛应用于数据保护领域。然而在对大文件进行加密解密时如果不合理管理内存和块的大小程序可能会崩溃或变得非常缓慢。我们将通过优化代码和加入合适的异常处理机制提升程序的鲁棒性和性能。 SM4 算法概述 SM4 是一种分组对称加密算法其块大小和密钥长度均为128位16字节。它的安全性和高效性使其成为移动通信、电子政务等领域的首选算法。 挑战与解决方案 初始问题 在使用SM4进行大文件加密解密时您可能遇到以下问题 加密后的文件大小与原始文件大小相同加密后的文件应该比原文件略大这是由于填充机制导致的。解密后的文件内容不正确无法还原到原始文件。 问题分析 通过代码分析我们发现了以下问题 填充处理不当加密过程中最后一个数据块没有正确处理填充导致加密数据的长度与原始数据不匹配。数据块未对齐SM4 的块大小是16字节但在加密和解密时使用了不同的块大小导致数据块未正确对齐。 解决方案 通过以下改进我们修复了这些问题 调整数据块的大小使用16的倍数作为块大小例如16 * 1024字节确保数据块与SM4的块大小对齐。正确处理填充仅对最后一个数据块进行填充解密时正确去除填充。添加异常处理引入合理的异常处理机制确保在文件读取、加解密过程中处理意外情况。 完整代码实现含详细注释 环境准备 确保安装了gmssl库 pip install gmsslAlgorithmTool 类的实现 from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT# 工具类提供SM4加解密以及填充处理 class AlgorithmTool:def init(self):pass# 将16进制字符串转换为字节数据staticmethoddef hex_string_to_bytes(data):return bytes.fromhex(data.replace( , ))# PKCS7填充算法确保数据长度是16字节的整数倍def pkcs7_padding(self, data):pad_len 16 - (len(data) % 16) # 计算需要填充的字节数padding bytes([pad_len] * pad_len) # 生成填充字节return data padding # 将填充字节附加到数据末尾# 去除PKCS7填充恢复原始数据def pkcs7_unpadding(self, data):pad_len data[-1] # 读取最后一个字节获取填充长度return data[:-pad_len] # 移除填充字节# 使用SM4进行ECB模式加密def encrypt_sm4(self, key, value):crypt_sm4 CryptSM4()crypt_sm4.set_key(self.hex_string_to_bytes(key), SM4_ENCRYPT) # 设置加密密钥return crypt_sm4.crypt_ecb(value) # 返回加密后的字节数据# 使用SM4进行ECB模式解密def decrypt_sm4(self, key, encrypted_value):crypt_sm4 CryptSM4()crypt_sm4.set_key(self.hex_string_to_bytes(key), SM4_DECRYPT) # 设置解密密钥decrypted_data crypt_sm4.crypt_ecb(encrypted_value) # 进行解密return self.pkcs7_unpadding(decrypted_data) # 去除填充返回解密后的数据SM4FileHelper 类的实现含详细注释 import os import io# 文件加密辅助类提供按块加密和解密大文件的功能 class SM4FileHelper:def init(self, key):self.ag_tool AlgorithmTool() # 使用AlgorithmTool处理加解密self.key key # 16进制密钥self.block_size 16 * 1024 # 块大小为16的倍数# 加密文件并在文件开头保存原始文件大小信息def encrypt_file(self, input_file_path, output_file_path):按块加密文件内容并在文件开头存储原始文件大小try:# 获取输入文件的总大小file_size os.path.getsize(input_file_path)# 打开输入和输出文件with open(input_file_path, rb) as f_in, open(output_file_path, wb) as f_out:# 写入文件大小便于解密时恢复f_out.write(file_size.to_bytes(8, byteorderbig))# 循环按块读取文件while True:chunk f_in.read(self.block_size) # 读取数据块if not chunk:break # 如果没有数据则结束循环if len(chunk) self.block_size:# 如果是最后一个块进行填充后加密padded_chunk self.ag_tool.pkcs7_padding(chunk)encrypted_chunk self.ag_tool.encrypt_sm4(self.key, padded_chunk)else:# 如果是完整的块直接加密encrypted_chunk self.ag_tool.encrypt_sm4(self.key, chunk)f_out.write(encrypted_chunk) # 写入加密后的数据except IOError as e:print(f文件操作错误: {e}) # 处理文件读写错误except Exception as e:print(f加密过程中的错误: {e}) # 处理加密过程中的其他异常# 解密文件并恢复原始文件内容def decrypt_file(self, input_file_path, output_file_path):按块解密文件内容try:# 打开输入和输出文件with open(input_file_path, rb) as f_in_raw, open(output_file_path, wb) as f_out:f_in io.BufferedReader(f_in_raw)# 读取文件开头的原始文件大小original_file_size int.from_bytes(f_in.read(8), byteorderbig)decrypted_size 0 # 已解密的数据大小# 循环按块解密文件while True:encrypted_chunk f_in.read(self.block_size 16) # 读取加密数据块if not encrypted_chunk:break # 如果没有数据则结束循环if f_in.peek(1) b: # 判断是否为最后一个块# 最后一个块进行解密后去填充并调整大小decrypted_chunk self.ag_tool.decrypt_sm4(self.key, encrypted_chunk)remaining_size original_file_size - decrypted_size # 计算剩余未写入的大小decrypted_chunk decrypted_chunk[:remaining_size] # 截断填充后的多余数据else:# 非最后一个块直接解密decrypted_chunk self.ag_tool.decrypt_sm4(self.key, encrypted_chunk)f_out.write(decrypted_chunk) # 写入解密后的数据decrypted_size len(decrypted_chunk) # 更新已解密数据的大小except IOError as e:print(f文件操作错误: {e}) # 处理文件读写错误except Exception as e:print(f解密过程中的错误: {e}) # 处理解密过程中的其他异常# 比较两个文件的大小用于验证解密文件与原文件是否一致def compare_file_size(self, original_file_path, decrypted_file_path):比较两个文件的大小try:# 获取原文件和解密后文件的大小original_size os.path.getsize(original_file_path)decrypted_size os.path.getsize(decrypted_file_path)# 输出文件大小对比结果print(f原文件大小: {original_size} 字节)print(f解密文件大小: {decrypted_size} 字节)# 检查文件大小是否一致if original_size decrypted_size:print(文件大小一致。)else:print(文件大小不一致)except IOError as e:print(f比较文件大小时的错误: {e}) # 处理文件操作异常测试代码 if name main:key 5A3F323272CEA0640C711129E0B6043B # 您的16进制密钥sm4_helper SM4FileHelper(key)input_file testbig.jpg # 要加密的文件encrypted_file encrypted_testbig.sm4 # 保存加密文件decrypted_file decrypted_testbig.png # 解密后的文件# 加密文件sm4_helper.encrypt_file(input_file, encrypted_file)print(f文件 {input_file} 已加密保存到 {encrypted_file})# 解密文件sm4_helper.decrypt_file(encrypted_file, decrypted_file)print(f文件 {encrypted_file} 已解密保存到 {decrypted_file})# 比较文件大小sm4_helper.compare_file_size(input_file, decrypted_file)代码解析与说明 填充与去填充 PKCS7填充在AlgorithmTool类中实现用于确保数据长度是块大小的整数倍。填充过程 计算填充字节数pad_len 16 - (len(data) % 16)。生成填充字节padding bytes([pad_len] * pad_len)。将填充字节附加到原数据末尾。 去填充过程 读取最后一个字节获取填充长度pad_len data[-1]。移除填充字节data[:-pad_len]。
按块加密解密逻辑 块大小选择16 * 1024字节满足SM4的块大小为16的倍数同时平衡处理效率和内存占用。加密逻辑 按块读取文件检查是否是最后一个块 最后一个块进行填充后加密。非最后一个块直接加密。 写入加密后的数据到输出文件。 解密逻辑 按块读取加密文件检查是否是最后一个块 最后一个块解密后去除填充并根据原始文件大小截断多余字节。非最后一个块直接解密。
处理最后一个数据块 加密时的填充 只有最后一个数据块需要填充确保数据长度为16字节的倍数。 解密时的去填充 仅对最后一个数据块进行去填充处理并截断多余字节确保解密文件与原文件一致。 最佳实践与注意事项 内存优化 按块处理通过分块读取避免内存占用过高。块大小调整根据具体情况灵活调整block_size。 异常处理 文件操作异常添加try-except块处理文件读写错误。加解密异常捕获加解密过程中可能的错误如密钥错误或数据格式问题。 安全性考虑 密钥管理妥善存储和传输加密密钥避免密钥泄露。敏感信息保护不要在日志中记录密钥或未加密数据。 总结 通过这次实践成功解决了SM4加密和解密过程中遇到的问题深入理解了对称加密算法的细节。正确处理数据块的填充和按块读取处理确保了内存占用的优化和加解密结果的准确性。