前言:
说实话在进行铜锁探密之前,我对密码最初的概念还保留在,我们登录QQ或者微信输入的“密码”。当老师和我说,那是口令而不是密码时,老师接下来讲的东西成功引起了我的注意。因此处于好奇,我去网上搜了下什么叫密码学?然后它大概是这么说的。
[密码学(在西欧语文中,源于希腊语kryptós“隐藏的”,和gráphein“书写”)是研究如何隐密地传递信息的学科。在现代特别指对信息以及其传输的数学性研究,常被认为是数学和计算机科学的分支,和信息论也密切相关。著名的密码学者Ron Rivest解释道:“密码学是关于如何在敌人存在的环境中通讯”,自工程学的角度,这相当于密码学与纯数学的异同。密码学是信息安全等相关议题,如认证、访问控制的核心。密码学的首要目的是隐藏信息的涵义,并不是隐藏信息的存在。密码学也促进了计算机科学,特别是在于电脑与网络安全所使用的技术,如访问控制与信息的机密性。密码学已被应用在日常生活:包括自动柜员机的芯片卡、电脑使用者存取密码、电子商务等等。
密码是通信双方按约定的法则进行信息特殊变换的一种重要保密手段。依照这些法则,变明文为密文,称为加密变换;变密文为明文,称为脱密变换。密码在早期仅对文字或数码进行加、脱密变换,随着通信技术的发展,对语音、图像、数据等都可实施加、脱密变换。]
说实话,这番解释,给密码又增加了一份神秘的色彩。因此就在想,现存的密码算法真的是那么的严谨和完美嘛?当学到SM3杂凑算法时,我顿时非常感兴趣了,因为SM3杂凑算法是一种不可逆的算法,意思是只能加密,不能被反向解密。但当我深入了解SM3杂凑算法时,好像事情变的有趣了起来。
一、初遇铜锁
自我总结:
初见铜锁,想放弃,但心有不甘。初极狭,后豁然开朗。从搭建铜锁环境用了差不多半天时间,到后面捣鼓快忘记的C语言,想说,我失去的青春好像回来了。又回到大学课堂,老师带我捣鼓C语言,捣鼓单片机等。
1、环境搭建,一次难忘的经历
打开手册,开头的实验的环境说明,让我重新回到使用小红帽、centos敲命令的时光。其实个人很喜欢linux系统,也很喜欢Ubuntu。这些系统启动起来特别快,运行程序也比较安全可靠。就是那些命令老是有点记不住,因此还是比较喜欢Windows的图形化界面。
因为看到可以通过在Windows里面安装Docker环境,实现安装虚拟机的过程,因此准备捣鼓捣鼓一番。说实话,因为公司不常用Docker,在开始学习营之前我只是知道Docker是个容器,相当于一个隔离版的虚拟机。不仅可以跨系统安装很多好玩的,而且不像虚拟机那样占用大量的资源。其实个人理解docker就是一个简单的进程,就如下图所示docker就是一个进程级别的。
Docker 是一个黑盒的进程,区别于传统的进程,Docker 可以独立出一个自己的空间,不会使得在 Docker 中的行为以及变量溢出到宿主机上。因此这次Docker环境搭建,让我打开了新世界的大门,让我彻底难忘Docker。
2、键盘敲出的每一个命令,都是最美的音符
在前面说到铜锁学习需要使用到类似Docker的环境,因此我就开始找很多关于Docker的资料,比如Docker到底是干什么的?Docker有什么用?通过类似下面一张张Docker的图解让我知道为啥Docker会深受开发者的喜欢了。
虽然安装Docker 时,参考了旧的教程导致自己走了一些弯路,如Docker 其实不需要开启Hyper-V,其实wls2更适合Docker。但在键盘中每一次次调试和敲击,让我认识到学无止境、不进则退。
在安装好Docker后,正式进入了铜锁的学习,按照手册开始一步步的进行实战,让我学会了实战SM4加解密算法的一些原理。但当我在PowerShell中,不断重复输入“echo -n "hello tongsuo" | /opt/tongsuo/bin/tongsuo dgst -sm3 ”命令时,发现每次返回的结果都是一样的。因此我开始萌发了一个大胆的想法。
二、SM3杂凑算法增强改造
前面我们提到,当我敲同一条SM3杂凑算法加密时发现,每次返回的结果是一样的时候,我从开始的好奇,陷入了沉思。因为在大量的项目实践中,我认识到,人们常用的密码都类似123456,abc123之类的。因为我用计算机记住常用密码 如123456,abc123的杂凑加密值。然后拥有用户档案的数据库查询权限,不就可以暴力破解用户的账号了。
此时我在想如果我是企业老板,我肯定不希望我的员工知道公司客户的密码的。因此我希望在数据库中即便不同用户设置了一样的密码。但保持至数据库的值也是不一样的。因此我开始了我大胆的猜想和增强改造。
三、艺术源于生活
SM3杂凑算法增强改造的灵感来源家里的智能锁,智能锁有个模式就是前面不管你随便输入多少位密码,只需要在按*键后,再输入正确的密码就可以打开门了。这样即便每次看上去输入的密码都是不一样的,但是每次都能成功打开智能门。
因此我在SM3杂凑算法中,加个了几个随机数,如在SM3杂凑加密值的前4位拼接4为随机数,第16-20位拼接5位随机数。然后再保存到数据库,这样即便是同样的密码,在数据库中保存的值也都是不一样的。因此即可拿到了数据库的查询值也是很难去暴力枚举破解用户的密码的。因此就将SM3杂凑算法进行了改造,类似部分改造源码如下。
#include <openssl/evp.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> static int sm3(const unsigned char *in, size_t inlen, unsigned char *out) { EVP_MD_CTX *mctx = NULL; if ((mctx = EVP_MD_CTX_new()) == NULL || !EVP_DigestInit_ex(mctx, EVP_sm3(), NULL) || !EVP_DigestUpdate(mctx, in, inlen) || !EVP_DigestFinal_ex(mctx, out, NULL)) { EVP_MD_CTX_free(mctx); return 0; } EVP_MD_CTX_free(mctx); return 1; } int main() { //增加4位随机数,保存至数据库的SM3值时,将生成的4位随机数拼接在SM3杂凑值前面,其他的类似 int num[4], cnt = 0, n; srand(clock()); // 设置随机数种子 while (cnt < 4) { n = rand() % 4; // 生成4以内随机数,这样更利于测试 for (int i = 0; i < cnt; i++) if (num[i] == n) // 遍历数组,有相同的重新生成随机数 continue; num[cnt++] = n; } for (int i = 0; i < cnt; i++) // 打印随机数数组 printf("%d ", num[i]); return 0; unsigned char in[] = "hello tongsuo"; unsigned char out[EVP_MAX_MD_SIZE]; int ret; ret = sm3(in, strlen(in), out); assert(ret == 1); for (int i = 0; i < EVP_MD_size(EVP_sm3()); i++) printf("%x", out[i]); printf("\n"); return 0; } // gcc sm3.c -I/opt/tongsuo/include -L/opt/tongsuo/lib64 -lcrypto -Wl,-rpa th=/opt/tongsuo/lib64
通过代码库,将自己的想法和代码提交进去了,也让自己学开源贡献了一份微薄的力量。因此在本次训练营学习中,学到了新工具,也表达了自己的新想法,真是Nice!