浅谈加密算法
前言
本文只涉及加密算法认识与使用,不涉及加密算法的源码分析与加密原理。(因为本人自己也看不懂源码,但是会用真就足够了,就算让我写一个这样的算法,给我源码也不会写,何况还是开源的)
本人并非密码学专家,但接触过 JS 逆向和安卓 Java 层,对一些加密算法也有所了解,借此来分享一下自己所接触过的常见加密算法与使用。
涉及到的常用的加密算法有
- 消息摘要算法
- MD5
- SHA1,SHA3,SHA256...
- HmacMD5,HmacSHA1,HmacSHA256...
- 对称加密算法
- DES
- 3DES(也称 TripleDES,DESede)
- AES
- 非对称加密算法
- RSA
编码
涉及到加密算法,必须要涉及到编码格式,主要涉及到的编码方式编码有以下几种
UTF-8
针对 Unicode 的一种可变长度字符编码。它可以用来表示 Unicode 标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理 ASCII 字符的软件无须或只进行少部份修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。
GBK (gb2312)
GBK 即“国标” ,汉字编码的标准编码字库。
上述两者的区别
-
表示中文的所占字节不同
同样表示一个中文字符,gbk 所占 2 字节,而 utf8 占 3 字节,通俗点就是如果你的项目代码涉及的都是中文这些,不会有希腊文,韩文等等,那么优先 gbk 编码,因为字节少,占用空间少。但如果涉及到更广的语言,那么 uf8 无疑是首选的。一般来说 Unicode 标准中 utf8 已经够用了,在编写代码中多数环境也是再 utf8 的标准上。总之基本 utf8 就完事了。
如需更深入了解可自行百度相关编码知识,本文只做与加密算法相关。
Base64
-
所有的数据都能被编码为只用 65 个字符就能表示的文本。标准的 Base64 每行为 76 个字符,每行末尾添加一个回车换行符(\r\n)。base 是可以互相转化的
-
65 字符:A
Z az 0~9 + / =在 URL Base64 算法中,为了安全,会把 + 替换成 - ,把 / 替换成 _
= 有时候用 ~ 或 . 代替(了解即可)
-
Base64 的应用
密钥、密文、图片、数据简单加密或者预处理
例如下面这些数据 通过链接 base64 图片在线转化即可 base64 编码数据与图片互相转化
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAMbSURBVDhPARAD7/wAbcLpc8Poc7nbcbbVecPggrzQyN3g9/z1+P7yx9rUlr7Ipc/fwNHh8vn/+///3eLeAGy84W+73aPl/6Th/YK80IWvu+b18v3989/h04uXi3aTkb7a3tnj7L3Axe3z8cPJxQB/xON5u9ub2PWczOKDoKSNmJCkopWxqpiyq5izsZqtsJWPkn2al5CSkY3N0sz1//cAu+r8q9jri7TGlrO7q7Oov7qnv7ekyMCrzMSvz8iuycOjqqOHX1lNNTItMzgyYGlkAPT//9/r57jBvMLEuczHs8rCq87Gsc3Gs7q1oqKdioJ/bHVzZF5fWS4wLSIkIystLADe39HW1MXUzbvDu6jKwq29tqOmoJJ8eGx+fG+AfnKTk4dpbGOfpJ6HhYYmFR1ONkMAubutvLqropuLqKGRko6DcXBrPDw6PT07kZKMkpOL6+7l0NPKo6SftqWrfEhesm2KAJaajDg6LWdjV4SAdYWEgJCSkYuPkldbXKWnpuPl4tXa1K+xrJiXk4ZzeaZyiNmUswAyPDNLUkqio52ko56uramZmpVvdHCssa2oqKiRkZOHiIqChIONjIq1qq7Fsbz/9P8AKiQklZGQ///9///9/v37+fj2foB70NLNk5OTrq6wnp6gqqqs4+Lgz87MmpibvbvAAD8ZJodsdf/6/P7////9///9//v5+t/e3PT08vz7+f/+//78/f7/+19hXBkZGTMzNQCbdYqHbHvCvMD3+Pr59/zx7PPs5+v//P3///37+/nw7+3s6+lxc24RExAlJigyMjQA19jt0tHhqqmvycnH6Ofj9fHw+PL28+7029/gyM7M5+flsbCuKCYpISAlIyInMTI2AMDX6eT2//f//+js7evs5+no5Obi4/79//z//97k5P7//////6imqQIBBhARFSMkKADP7fjW8v3d9Pzi8fb7///+//3q7+vq7u3V2drEyMvm5ujQ0NKio6VlaWp1d3aGiIcA0fP8xebvu9jg1Ojv9Pz/+//+8vj02N7a19vc6+zw2djd1NXX+Pz9+///9/n27e/sqToTd5KpZ2kAAAAASUVORK5CYII=
-
浏览器内置 Base64 编码(btoa) 解码(atob)

Hex
二进制数据最常用的一种表示方式。用 0-9 a-f 16 个字符表示。每个十六进制字符代表 4bit。也就是2个十六进制字符代表一个字节。如a12345678用 md5 加密的结果为 32 位 0-9a-f 字符e9bc0e13a8a16cbb07b175d92a113126 每 2 个十六进制字符为一个字节,32 位字符也就是 16 个字节。
在实际应用中,尤其在密钥初始化的时候,一定要分清楚自己传进去的密钥是哪种方式编码的,采用对应方式解析,才能得到正确的结果。
单向散列函数(消息摘要算法,哈希算法)
- MD5
- SHA1,SHA3,SHA256...
- HmacMD5,HmacSHA1,HmacSHA256...
先说最简单的也是用的最多的算法,性质如下
- 不管明文多长,散列后的密文定长
- 明文不一样,散列后结果一定不一样
- 散列后的密文不可逆
- 一般用于校验数据完整性、签名、sign
你只需要需要性质就行,下文会举实例。
由于密文不可逆,所以后台无法还原,也就是说他要验证,会在后台以跟前台一样的方式去重新签名一遍。也就是说他会把源数据和签名后的值一起提交到后台。常用于校验数据完整性、签名、sign
比如我有一篇毕业论文,我写的差不多了,然后去厕所回来,看到我的一个室友坐在我电脑前,我该如何知道他是否有更改过我的毕业论文。这是消息摘要算法就能解决这个问题,在你走之前将论文取 MD5(后面例子也都以 MD5 为例),然后去厕所完,再取一次 MD5 的值,将两者一比对,只要修改了一个字符或者添加了一个空格,两者的 MD5 值都完全不一样,基本差别巨大。也就可以知道你的论文有没有被改了,但是被改了你也没有办法还原回去,然后你就毕业不了了。
由于固定原文加密后的密文是固定的,理论上只要我一个一个字符试过去,将结果与密文对比,相同的话就可以知道原文。那么可以将这些原文和密文存入对应的数据库里,在查加密后的密文后去数据库找原文,如彩虹表就是专门暴力破解这种算法的(相关链接 什么是彩虹表)。防止通过彩虹表破解的话就需要对原文在做一次操作----加盐。加盐可以理解为就是添加了一些字符串,例如上面说到kuizuo这个字符串 通过 MD5 算法后得到的结果是ff1fa96799ded9ee89d0f764b3e9ff54 这就是不加盐 MD5 返回的结果,万一我在kuizuo后面加一个!后呢,结果为7e74121af78b9555241fdf6538e2f22b,可以看到两者完全天壤之别,这就是这个算法妙的地方,我不加!的彩虹表所对应的kuizuo密文可能在彩虹表里都有了,但是我这样处理,在kuizuo这个字符串前或后,都加一个随机的字符串(这些随机的字符串可要记得,不然你自己到时候数据效验的时候也不知道原文对不对了),然后进行拼接在取 MD5 的值,这样他的彩虹表就废了,就需要猜测出我的加的盐,然后在重新生成密文与原文对应的数据库。
在涉及 HTTP 请求的时候,用到最多的还是 sign,如一段 post 的 data 数据为
{"phone":"15212345678”,"timestamp":"1598567732417" , sign:"41785be6d13c5e3a0112c79255607f3a"}