1750 字
9 分钟
- 次浏览
课程小作业也可以写成一次工程复盘
读前导览

这个 C# WinForms 课程作业,把鼠标绘图、文件读写、AES/RSA 混合加密和状态管理问题揉在了一起。

正文
1750 字
阅读
9 分钟
结构
8 节
来源线索
GitLaughs/Essay-based-encryption-and-decryption-system
GitLaughs/c-sharp-homework https://github.com/GitLaughs/c-sharp-homework

这个项目的名字很直接:Essay-based-encryption-and-decryption-system,基于随笔画的加解密系统。公开仓库在这里:

https://github.com/GitLaughs/Essay-based-encryption-and-decryption-system

它看起来像一个普通课程作业:C#、Windows Forms、鼠标绘图、文件读写、AES、RSA。功能也不复杂:在窗体里随手画几笔,把绘图数据加密保存,再从文件里解密恢复。

但这类小作业其实很适合写回看。因为它把很多“课本概念”放进了一个真的要跑起来的界面里:事件处理、状态管理、序列化、加密流程、文件结构、错误提示,全都要一起工作。

作业题目背后是四个小系统#

这个项目表面上是“画图加解密”,实际可以拆成四层:

要解决的问题
WinForms 界面菜单、鼠标事件、颜色/线条选项、保存/打开对话框
绘图数据怎么记录一条随笔线,怎么从点重新画出来
文件读写加密后的数据如何组织,如何可靠读回
加密流程AES 加密绘图数据,RSA 保护 AES 密钥和 IV

课程作业很容易只盯着“功能完成”。不过实际写的时候会发现,只要其中一层没有想清楚,整个程序就会表现得很奇怪。

比如绘图功能本身不难,鼠标按下、移动、抬起都能触发事件;麻烦的是,画面停在屏幕上还不够,还得把点、颜色和线型这些信息存下来,后面才能加密、写文件、解密恢复。

画出来的图必须先变成数据#

WinForms 里用鼠标画线很直观,但屏幕上的像素不是一个适合加密的对象。

更合理的做法是把绘图过程转成结构化数据:

stroke -> points -> line style -> color

只要这些数据能被序列化,就可以进入后面的文件和加密流程。否则程序只能“看起来画出来了”,但保存、解密、恢复都会变得很麻烦。

这个点对初学者很有用。很多 GUI 程序卡住,问题常常出在界面状态和业务数据混在了一起。屏幕显示是一回事,可持久化数据是另一回事。

AES 和 RSA 各做各的事#

README 里提到的加密流程是一个典型混合加密思路:

  • 用 AES 生成对称密钥和 IV。
  • 用 AES 加密绘图数据。
  • 生成 RSA 密钥对。
  • 用 RSA 加密 AES 密钥和 IV。
  • 把加密后的密钥、IV、绘图数据写入文件。
  • 解密时用 RSA 私钥恢复 AES 密钥和 IV,再用 AES 恢复绘图数据。

这比“直接用 RSA 加密所有绘图数据”更接近真实工程里的做法。RSA 更适合保护小块密钥材料,AES 更适合加密正文数据。

我觉得这个作业比较有意思的地方,是它把对称加密、非对称加密、文件格式和界面操作放到了一条流程里。

文件格式要比想象中更重要#

加密后的文件不是随便写一堆字节就完事了。

解密时程序需要知道:

  • 哪一段是 RSA 加密后的 AES key。
  • 哪一段是 RSA 加密后的 IV。
  • 哪一段是 AES 加密后的绘图数据。
  • 每一段长度是多少。
  • 读到的数据是否完整。

如果文件结构没有设计好,解密代码就会充满猜测。小作业里也许能靠“固定顺序 + 固定长度”跑通,但一旦数据结构变化,就很容易坏。

回头看这个项目时,文件读写这一块其实不能糊弄。格式写得清不清楚,直接影响后面能不能把图恢复出来。

那个重复解密的 bug#

README 里最有生活气息的一段,是那个重复解密的 bug:解密文件后再次解密,会提示需要先加密。最简单的修法是注释掉提示和 return,但这样又没有报错提示。

这其实是很典型的状态管理问题。

程序可能把“是否已经加密过”“当前是否有可解密文件”“当前画布是否有内容”“上一次操作是什么”混在了一起。第一次操作时没问题,第二次重复操作就会暴露状态判断不准确。

这种 bug 通常不能靠删提示解决,还是要重新定义状态:

  • 当前画布是否有绘图数据。
  • 当前是否已经加载加密文件。
  • 当前是否存在待保存结果。
  • 加密按钮和解密按钮分别依赖哪些条件。
  • 错误提示应该对应哪个状态。

课程作业里遇到这种问题很正常。它提醒我,GUI 程序会被用户反复点击、回退、重试,状态判断要按这种使用方式来设计。

菜单不是装饰#

题目要求菜单至少包括绘图、加密、解密,还要能调整线条类型、线条颜色。

这些看似是界面小功能,但它们会影响数据结构。线条颜色和类型如果只是即时绘制时生效,却没有写入绘图数据,那么解密恢复时就只能还原轨迹,不能还原样式。

所以菜单选项背后也要进入模型层:

current pen style -> stroke metadata -> encrypted payload -> restored drawing

这就是很多课程 GUI 作业容易漏掉的地方:控件有了,事件也能触发,但状态没有被纳入保存和恢复流程。

小作业也能练工程习惯#

这个项目不需要被包装成什么大型系统。它值得记的地方就在于小:

  • 一个窗体。
  • 一套菜单。
  • 一份绘图数据。
  • 一个加密文件。
  • 一条加密/解密流程。

但小项目同样可以练几个很实用的工程习惯:

  • 把界面状态和可保存数据分开。
  • 把文件格式写清楚。
  • 不滥用 RSA 做大数据加密。
  • 对重复点击和错误路径做状态判断。
  • 把 README 写清楚,包括已知 bug 和修复思路。

这些习惯以后写更大的工具也用得上。

为什么这类作业值得写进博客#

很多课程作业交完就被丢进硬盘角落。其实它们很适合变成博客素材。

因为课程作业的规模刚好:功能不大,背景清楚,问题具体,回看成本低。写下来主要是留一份当时的思路:课堂概念怎么落到代码里,哪些地方又暴露出状态和文件设计上的欠账。

对我来说,这篇更像是一个提醒:哪怕只是一个 WinForms 小作业,只要里面有真实的状态、数据、文件和错误路径,就值得认真回看一次。

课程小作业也可以写成一次工程复盘
https://blog.sunmmyapi.xyz/posts/winforms-doodle-encryption-course-project/
作者
Sun
发布于
2026-05-29
许可协议
CC BY-NC-SA 4.0

继续读

相关内容