【项目】磁盘文件管理工具

项目介绍

该项目创建的目的为删除磁盘中重复文件,通过计算指定路径下的文件指纹(数字签名)来判断两个文件是否相同,从而按照文件名、文件指纹或模糊匹配删除相同文件

项目原理

计算机签名方法

数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。 是一种类似写在纸上的普通的物理签名

常用的数字签名方法主要有:
HASH算法 ,此算法主要包括MD(信息摘要)和SHA(安全散列算法)两类 。DSA、ECDSA、椭圆曲线数字签名算法,微软产品的序列号验证算法使用的就是ECDSA。与传统的数字签名算法相比,速度快,强度高,签名短

计算机签名 MD5

MD5简介

MD5是由Ron Rivest在1991设计的一种信息摘要(message-digest )算法,当给定任意长度的信息,MD5 会产生一个固定的 128 位“指纹”或者叫信息摘要。从理论的角度,所有的信息产生的 MD5 值都不同,也无法通过给定的 MD5 值产生任何信息,即不可逆

  1. 功能
    输入任意长度的信息,经过处理,输出为 128 位的信息(数字指纹)
    不同的输入得到的不同的结果(唯一性),要使两个不同的信息产生相同的摘要,操作数量级在 2^64 次方
    根据128位的输出结果不可能反推出输入的信息,根据给定的摘要反推原始信息,它的操作数量级在 2^128 次

  2. 用途

防止信息被篡改

1)当发送电子文档的同时发送文档的 MD5 值,接收后计算 MD5 值,若结果相同则没有被篡改
2)作为文件下载安全验证,在下载网络文件或程序时,为了防止不法分子在安装程序中添加木马,在网站上公布由安装文件得到的MD5输出结果。用户下载完成,在本地计算MD5值,比较结果,验证文件是否完整和安全

防止直接看到密码明文

现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。就算不法分子得到数据库种用户密码的MD5值,也无法知道用户的密码。比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度

防止抵赖(数字签名)

这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”

MD5 算法步骤

MD5的算法输入为以bit为单位的信息(1 byte = 8 * bit),经过处理,得到一个128bit的摘要信息。这128位的摘要信息在计算过程中分成4个32bit的子信息,存储在4个buffer(A,B,C,D)中,它们初始化为固定常量。MD5算法然后使用每一个512bit的数据块去改变A,B,C,D中值,所有的数据处理完之后,把最终的A,B,C,D值拼接在一起,组成128bit的输出。处理每一块数据有四个类似的过程,每一个过程由16个相似的操作流组成,操作流中包括非线性函数,相加以及循环左移。MD5算法大致可分为5个步骤:

  1. 添加填充位
    信息的最尾部(不是每一块的尾部)要进行填充,使其最终的长度length(以bit为单位)满足length % 512 = 448,这一步始终要执行,即使信息的原始长度恰好符合上述要求
    填充规则:第一个bit填充位填 ‘1’ ,后续bit填充位都填 ‘0’ ,最终使消息的总体长度满足上述要求。总之,至少要填充 1 bit,至多填充 512 bit

  2. 添加bit长度
    添加一个64bit大小的length,length表示原始消息(未填充之前)的bit长度,极端情况,如果消息长度超过264,那么只使用前264bit消息,这一步完成之后,消息的最终长度变为(length + 64) % 512 = 0,即length为512的整数倍。从这里再去看第一步,至少需要填充 8 bit,有以下几种情况:
    1)消息原始长度 % 512 = 448,这时候原始长度符合要求,但是根据填充规则,仍然要至少填1bit的 ‘1’,后面还剩63bit,不够添加长度,所以需要再加一块数据(512bit),这样后面63bit填0,新加的数据前448bit填0,最后64bit填数据原始长度,长度值是放在最后一块数据的最后64bit
    2)消息原始长度 % 512 < 448,此时最后一块数据长度不大于440bit,最后64bit填数据长度,需要填充的bit数不小于8
    3)消息原始长度 % 512 > 448,此时最后一块数据长度不小于456,最多504,剩余bit不够添加64位长度,和假设1相同,需要增加一块数据,最后64位添加长度,其余填充0

  3. 初始化MD buffer(A,B,C,D)
    用4-word buffer(A, B, C, D)计算摘要,这里A,B,C,D各为一个32bit的变量,这些变量初始化为下面的十六进制值,低字节在前

/*word A: 01 23 45 67
 word B: 89 ab cd ef
 word C: fe dc ba 98
 word D: 76 54 32 10
*/
 // 初始化A,B,C,D 
 _atemp = 0x67452301; 
 _btemp = 0xefcdab89; 
 _ctemp = 0x98badcfe; 
 _dtemp = 0x10325476;
  1. 按512位数据逐块处理输入信息
    512bit数据为一个处理单位,暂且称为一个数据块chunk,每个chunk经过4个函数(F, G, H, I)处理,这四个函数输入为3个32位(4字节)的值,产生一个32位的输出。四个函数如下所示:
/*
F(x,y,z) = (x & y) | ((~x) & z) 
G(x,y,z) = (x & z) | ( y & (~z)) 
H(x,y,z) = x ^ y ^ z 
I(x,y,z) = y ^ (x | (~z))
 */

处理过程中要用一个含有64个元素的表K[1…64],表中的元素值由sin函数构建,K[i]等于2^(32) * abs(sin(i))的整数部分,即:

/*
K[i] = floor(2^(32) * abs(sin(i + 1))) // 因为此处i从0开始,所以需要sin(i + 1) 
*/
for (int i = 0; i < 64; i++) 
{ 
    _k[i] = (size_t)(abs(sin(i + 1)) * pow(2, 32)); 
}

在处理一个chunk(512bit)的数据时,会把这个chunk再细分成16组4字节数据,一个chunk经过4轮进行处理,每轮都会把chunk的所有数据处理一遍,每轮有16个相似的子操作,所以一个chunk的数据要进行64个子操作计算之前先保存MD buffer的当前值:
a = A, b = B, c = C, d = D

第一轮:F函数处理(0 <= i <= 15)
在这里插入图片描述
在这里插入图片描述

F = F(b, c, d) 
d = c
c =b
b = b + shift((a + F + k[i] + chunk[g]), s[i]) 
a = d

第二轮:G函数处理 (16 <= i <= 31)
在这里插入图片描述
在这里插入图片描述

G = G(b, c, d) 
d = c 
c =b 
b = b + shift((a + G + k[i] + chunk[g]), s[i]) 
a = d

第三轮:H函数处理(32 <= i <= 47)
在这里插入图片描述
在这里插入图片描述

H = H(b, c, d) 
d = c 
c =b 
b = b + shift((a + H + k[i] + chunk[g]), s[i]) 
a = d

第四轮:I函数处理(48 <= i <= 63)
在这里插入图片描述
在这里插入图片描述

I = I(b, c, d) 
d = c 
c =b 
b = b + shift((a + I + k[i] + chunk[g]), s[i]) 
a = d

注:<<<s表示循环左移操作

/*
s[ 0..15] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22 } 
s[16..31] = { 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20 }
s[32..47] = { 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23 } 
s[48..63] = { 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }
 */
size_t s[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 
            12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 
            4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 
            15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 };
  if (0 <= i < 16) g = i; 
  if (16 <= i < 32) g = (5 * i + 1) % 16; 
  if (32 <= i < 48) g = (3 * i + 5) % 16;
  if(48 <= i < 63) g = (7 * i) % 16;

一个chunk数据处理完之后,更新MD buffer的值A, B, C, D

A = a + A; 
B = b + B; 
C = c + C; 
D = d + D;
  1. 摘要输出

拼接4个buffer(A,B,C,D)中的摘要信息,以A中的低位字节开始,D的高位字节结束。最终的输出是128bit摘要信息的16进制表示,故最后输出一个32长度的摘要信息

项目流程及模块介绍

  1. 写出计算 MD5 值的程序(MD5.c & MD5.h)
  2. 写出根据 MD5 值、文件名、模糊匹配删除相同文件等关于文件处理的程序(fileManager.cpp & fileManager.h)
  3. 将上述关于文件操作的程序包到一个工具类中(fileManagerTool.cpp & fileManagerTool.h)
  4. 写出进行指定目录下文件检索找到文件的程序(fileutil.cpp & fileutil.h)
  5. 最后完成菜单设计,将功能实现(test.cpp)
  6. 对基本功能进行测试

    代码链接.
发布了60 篇原创文章 · 获赞 122 · 访问量 8730

猜你喜欢

转载自blog.csdn.net/qq_44759710/article/details/104904235