用C#编写最简单的文件加解密工具
接下来我们用C#编写命令行加解密工具, 顺便看看C#有没有加入好用的语法特性。
C#的发展速度非常快, 几乎加上了我所见过的所有语法特性, 要跟上巨硬的节奏非常不容易, 不过它是开创者。
比如可空类型就是C#首次捣鼓出来的, 当时学习的时候没在意, 后来经过kotlin的发扬光大后发现这语言特性这么香, 避免nullPointerException最好的办法就是尽量不用它。
所以有空可以关注一下C#的最新进展。
书归正传……
加解密原理
加解密文件实现原理就是替换大法, 比如有这样的字符串:
2023通过我们的加密后变成这样4245, 这样简单的原理适用于任何计算机文件, 因为文件就是一大串0-255的数字的集合……
我们对文件的每一个数字做一定的运算后得到加密后的文件, 对加密文件的每一个数字做逆运算后得到解密后的文件。
具体而言每一个数字加上3, 解密就是给每一个数字减去3, 那么这里有个问题如果得到的数据大于255不就溢出了么?
我们把0-255这256个值当作一个首尾相连的整体就很好解决溢出问题, 如果得到的值大于255就减去256, 得到的值小于0就加上256。
关于实现思路到此为止, 接下来编码实现!
小工具的上下文环境
我们通过命令行参数获取目标数据, 包括 动作要解密或加密, 文件路径, 其他必要信息。
处理完成后返回一个结果数据, 动作是否成功, 处理后的结果, 其他必要信息。
为此我们需要一个枚举类型叫Action表示程序的动作, 此外一个泛型类Context里面有三个泛型字段。
看如下代码:
Action枚举类型
enum Action |
加密、 解密; 帮助和错误, 很好理解。
Context类
class Context<T1, T2, T3> |
接下来在Context类的基础上需要两个类型, Target表示目标, Result表示结果。
我们这次用C#的顶层语句, 就像编写脚本语言一样, 不过需要注意的是我们把Action和Context放在源文件的最后。
using语句不变在源程序的开头, 下来是调用main函数, 中间是其他函数定义。
Target和Result
using Target = Context<Action, string, string>; |
这样我们得到了两个上下文类型Target的三个字段分别表示Action动作, string文件路径, string必要信息。
Result的三个字段表示bool处理是否成功, byte数组表示处理结果, string相关信息。
这样一来我们可以使用普通的类一样用Result和Target类型就可以了。
小工具可以这样搞first, second和third不会容易搞混, 如果面对较大项目的时候这样的技巧慎用!
还是老老实实用success, secretContent和msg这样的字段名。
这就是C#的表现力, 本来需要定义类似的两个类型, 现在直接用一个泛型类搞定, 顺便感叹C#using语句的功能特别多, 列举一下我所知的功能列表:
引用命名空间
重命名命名空间类型等
安全释放资源
定义新的类型, 存疑
这样一来我们的准备工作已经顺利完成, 接下来顺着程序的运行轨迹编码实现就可以了。
using语句后就是我们的main函数调用
main(args); |
需要注意的是在顶层语句我们直接使用args变量即可, 无需额外动作……
接下来看看main函数是如何运行的。
Main函数
void Main(string[] querys) |
这里需要注意的是switch语句, 这样的语法可以去掉case; break, 当然你的case语句有多行的话还是用回传统的编写方式。
生成Target对象
// 接受一个字符串数组, 返回Target对象 |
这次是更复杂的switch语句。
命令行参数解析的不算特别精细不过也大差不差。
接下来程序开始调用加解密函数, 特别简单如下所示:
加解密函数
Result Encryption(Target target) |
接下来是读取文件的函数:
Result ReadBytes(Target target) |
最后是核心功能, 也特别简单:
void calculate(byte[] buf, int num) |
编写一个玩具文件加解密工具就是这么简单轻松。
编译运行看看效果。
> dotnet run -e hello.txt |
最后
这样的工具还有哪些可以优化的空间?
至少两个方面需要继续做。
1.友好明确的错误提示尤其是这样的用法
> secret.exe -d hello.txt |
这样的提示只有我们自己知道啥情况, 过了几个月恐怕自己也搞不清这意味着什么!
2.加入口令, 为了实现简单可以限制密码的长短和类型, 比如必须提供六位数字等。
不怕挑战可以用任意长度和类型的任何密码, 只是算法实现有难度……