有时候我们需要给电脑上的有些文件加密,之前都是用压缩工具进行加密压缩,但是太麻烦了而且还慢,于是我就自己构思写了一个小工具,用来快速的对文件进行加锁操作
具体原理是对文件的原数据和文件名进行部分异或运算,破坏文件的可读性
由于算法简单,追求速度,并且未对所有数据进行处理,所以这个小工具具有很大局限性,只能防防没有目的性且不太懂电脑的小白,遇见个稍微懂点了就没用了
看代码:
入口以及安全验证
namespace Locker { class Program { static void Main(string[] args) { while (true) { try { Console.Write("code:"); var cmd = Console.ReadLine(); if (MD5(cmd) == GetCode_MD5()) { //匹配输入的验证码和配置文件中的验证码进行比较,实现简单的安全验证 FileLocker locker = new FileLocker(); locker.Process(); } else { throw new Exception("error code!"); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } /// <summary> /// 读取配置文件保存的md5加密字符串,防君子不防小人不用复杂的hash算法以及加盐 /// </summary> static string GetCode_MD5() { var code_MD5 = ConfigurationSettings.AppSettings["code_MD5"]; if (string.IsNullOrEmpty(code_MD5)) { throw new Exception("config file lost!"); } return code_MD5; } /// <summary> /// 对字符串进行md5加密,得到32位大写字符串 /// </summary> public static string MD5(string str) { byte[] array = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str)); return BitConverter.ToString(array).Replace("-", ""); } } }
配置文件:
其中的code_MD5的默认值是XOR127的hash字符串,即默认口令为XOR127
可以通过自己覆盖MD5值来改变口令
<?xml version="1.0" encoding="utf-8"?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/> </startup> <appSettings> <add key="code_MD5" value="5CA9E1DE9C4535946AB5888FD55C86CC"/> </appSettings> </configuration>
核心逻辑:
using System; using System.IO; using System.Text; namespace Locker { /// <summary> /// 一个简单的对文件加锁的工具 /// </summary> public class FileLocker { /// <summary> /// 破坏数据时用到的异或码,固定写死127,避免太过复杂导致的悲剧 /// </summary> public const byte XorCode = 127; /// <summary> /// 文件夹,固定写死,避免太过复杂导致的悲剧 /// </summary> readonly string dirPath = Environment.CurrentDirectory + "\\XOR" + XorCode; /// <summary> /// 破坏数据的长度,设置为1M /// </summary> const int xorLenMax = 1024 * 1024; /// <summary> /// 加锁文件的后缀 /// </summary> readonly string prefix = ".XOR" + XorCode; /// <summary> /// 对指定文件夹下的文件进行加锁,其原理是通过异或字节破坏文件的内容和后缀,让其不可读 /// </summary> public FileLocker() { //为了防止破坏操作系统文件等悲剧,特限制死了必须在根目录下的指定文件夹中 if (!Directory.Exists(dirPath)) { throw new Exception("未检测到目录下的XOR" + XorCode + "文件夹!"); } } /// <summary> /// 对指定文件夹下的所有文件进行处理,未锁则锁,已锁就解锁 /// </summary> public void Process() { foreach (var fi in new DirectoryInfo(dirPath).GetFiles()) { if (fi.Extension != prefix) { Lock(fi.Name, (int)fi.Length); } else { UnLock(fi.Name); } } } /// <summary> /// 对文件进行加锁 /// </summary> void Lock(string name, long fileLength) { int xorLen = xorLenMax; if (xorLen > fileLength) { xorLen = (int)fileLength; } UpdateData(name, xorLen); SaveInfo(name, xorLen); Rename(dirPath + "\\" + name, dirPath + "\\" + Guid.NewGuid().ToString("N").ToUpper() + prefix); } /// <summary> /// 对文件进行解锁 /// </summary> void UnLock(string name) { (string realName, int xorLen) = GetInfo(name); UpdateData(name, xorLen); Rename(dirPath + "\\" + name, dirPath + "\\" + realName); } /// <summary> /// 重命名 /// </summary> void Rename(string path, string pathNew) { Console.WriteLine("================================="); Console.WriteLine("原文件:" + path); Console.WriteLine("新文件:" + pathNew); Console.WriteLine("================================="); File.Move(path, pathNew); } /// <summary> /// 异或字节数组中的数据,可以破坏文件的可读性 /// </summary> byte[] XorData(byte[] arr) { for (int i = 0; i < arr.Length; i++) { arr[i] = (byte)(arr[i] ^ XorCode); } return arr; } /// <summary> /// 调整文件中的部分数据 /// </summary> void UpdateData(string name, int xorLen) { byte[] arr = null; Read(name, (br, fs) => { arr = br.ReadBytes(xorLen); }); //读取文件中指定长度的头数据 XorData(arr); //对其进行异或 Write(name, (bw, fs) => { bw.Write(arr); }); //在覆写这些数据,破坏可读性 } /// <summary> /// 保存加锁文件相关信息到文件的最后 /// </summary> void SaveInfo(string realName, int xorLen) { Write(realName, (bw, fs) => { fs.Seek(fs.Length, SeekOrigin.Begin); //在文件的最后保存文件的原有信息 bw.Write(xorLen); //记录异或数据的长度 byte[] bs = Encoding.UTF8.GetBytes(realName); XorData(bs); //文件名也要异或下,破坏可读性 bw.Write(bs); bw.Write(bs.Length); //记录文件名的长度 }); } /// <summary> /// 读取加锁文件相关信息 /// </summary> (string realName, int xorLen) GetInfo(string name) { string realName = string.Empty; int xorLen = 0; Read(name, (br, fs) => { var len = fs.Length; fs.Seek(len - 4, SeekOrigin.Begin); //最后4个字节记录文件名字节的长度 int realNameLen = br.ReadInt32(); //读取文件名字节长度 fs.Seek(len - 4 - realNameLen, SeekOrigin.Begin); realName = Encoding.UTF8.GetString(XorData(br.ReadBytes(realNameLen))); //读取文件名 fs.Seek(len - 4 - realNameLen - 4, SeekOrigin.Begin); xorLen = br.ReadInt32(); //读取异或长度 fs.SetLength(len - 4 - realNameLen - 4); }); return (realName, xorLen); } /// <summary> /// 读文件 /// </summary> void Read(string name, Action<BinaryReader, FileStream> action) { using (FileStream fs = new FileStream(dirPath + "\\" + name, FileMode.Open)) { using (BinaryReader br = new BinaryReader(fs)) { action(br, fs); } } } /// <summary> /// 写文件 /// </summary> void Write(string name, Action<BinaryWriter, FileStream> action) { using (FileStream fs = new FileStream(dirPath + "\\" + name, FileMode.Open)) { using (BinaryWriter bw = new BinaryWriter(fs)) { action(bw, fs); } } } } }标签:文件,xorLen,加锁,string,int,电脑,fs,name From: https://www.cnblogs.com/luludongxu/p/17095007.html