编码、加密、Hash
今天没有编码,还是属于纯理论的东东,概念也比较多,但是实际真正完全理解它们的人不多,也很重要,这些东东在实际中也经常被用到,但需要真正理解了才能正确的使用它们,这里列一下相关司:MD5、SHA1、RSA、DSA、AES、BASE64、encoded URL、Unicode、UTF-8、GBK、ISO-8859-1..........一看都眼熟,但是它们具体哪个场合去用它们还是比较难理清的,所以这次的目的就是彻底理清这些东东。
加密解密 Entryption & Decryption:
古典密码学:
- 移位式加密:
如密码棒,使⽤布条缠绕在⽊棒上的方式来对书信进行加密,该密码棒长这样:该密码棒的规格是严密定制的,也就是通信双方都有一样规格的密码棒,然后缠绕布条后进行书写,写好之后再将布条给拆掉,这样既使中途被敌人接活了布条,敌人也看不懂具体意思,这样也就达到了加密的效果。所以可以简单规纳一下:
加密算法:缠绕后书写
密钥:木棒的尺寸 - 替换式加密:
按规则使用不同的文字来替换掉原先的文字来进行加密,具体举个例子:
也就是密码字符基于原始字符做了一个移位,然后将原始字符对应成密码字符也就对原内容进行了加密,然后对方就可以根据码表则将加密的字符进行还原,所以简单归纳:
加密算法:替换文字。
密钥:替换的码表。
现代密码学:【有了计算机之后】
不止可以用于文字内容,还可以用于各种二进制数据。
- 对称加密:
原理:使用密钥和加密算法对数据进行转换,得到的无意义数据为密文;使用密钥和解密算法对密文进行逆向转换,得到原数据。通信双方使用同一个密钥,使用加密算法配合上密钥来加密,解密时使用加密过程的完全逆过程配合密钥来进⾏解密。简化模型即上面的古典密码学中替换式加密的模型:对文字进行规则化替换来加密,对密文进行逆向的规则化替换来解密。此时对方拿到密文则进行解密,如下:
这种加密有两个经典算法:
DES(56 位密钥,密钥太短而逐渐被弃⽤)、AES(128 位、192 位、256 位密钥,现在最流行)而它的作用:
加密通信,防⽌信息在不安全⽹络上被截获后,信息被人读取或篡改。
另外对称加密是可以被破解的,其破解思路:
①、拿到一组或多组原文-密文对。②、设法找到一个密钥,这个密钥可以将这些原文-密文对中的原文加密为密文,以及将密⽂解密为 原文的组合,即为成功破解。
有破解就有反破解:一种优秀的对称加密算法的标准是,让破解者找不到⽐穷举法(暴力破解法)更有效的破解手段,并且穷举法的破解时间⾜够长(例如数千年)。
另外它也是有缺点的:
密钥泄露:不能在不安全⽹络上传输密钥,⼀旦密钥泄露则加密通信失败。 - 非对称加密【重点】:
原理:使⽤公钥对数据进行加密得到密文;使⽤私钥对数据进行解密得到原数据。⾮对称加密使用的是复杂的数学技巧,在古典密码学中没有对应的原型。
居然是用同一个算法应用了不同的钥匙就能达到解密的效果,那怎么做到的呢?这里举一个简单的例子用来理解它的原理,但并非是真正非对称加密所采用的,如下:
比如我们只能输入这些数字:0123456789,然后我遇到危险了想写110,但肯定不能名文,所以采用非对称加密,其加密规则如下:
加密算法:对数字位进行加法。
公钥:数字加4。
私钥:数字加6。
所以110加密的密文就为:此时对方则需要将554进行解密,还是使用相同的加密算法对数字位进行加法操作,只是这次是用私钥来进行加法,私钥需要加6,所以加完之后会变成:
所以非对称加密会有溢出的处理。
使⽤⾮对称加密通信,可以在不可信网络上将双方的公钥传给对方,然后在发消息前分别对消息使用 对⽅的公钥来加密和使用⾃己的私钥来签名,做到不可信网络上的可靠密钥传播及加密通信。下面再来举个场景:这样就可以大胆的将公钥在网络上进行传输,所以可以大胆的告诉对方公钥信息,如下:
然后A给B发送数据,则用公钥B对数据进行加密发送给B,此时B就可以用私钥B对密文进行解密了,同样的如果B给A发也是雷同,那假如公钥B和公钥A被C给截获到了,如下:
那他拿了公钥信息也解不了密文的,所以非对称加密的一个核心就是私钥一定得要自己拿着,不能公开。
那用公钥能解出私钥加密内容么?其实是可以的,下面图解一下:然而描述的这个步骤刚好就是它:
所以很显然是可以用公钥解私钥加密的内容,由于私钥和公钥互相可解,因此非对称加密还可以应用于数字签名技术。具体表现如下:所以可以发现加密和数字签名的区别在于:加密是使用公钥加密,用私钥验证,而数字签名则是相反的,用私钥加密,公钥解密,需要注意一下它们之间的区别。
直接对原数据签名会导致原数据不可读,所以通常会对原数据 hash 以后对 hash 签名,然后附加在原数据的后面作为签名,所以完整版的签名与验证就为:
另外对于加密和签名可以混合着使用,变形如下:
这里还需回过头来说一种情况,就是我们知道在非对称加密中对外公开了公钥信息,如下:但是!!!第三方拿到了公钥信息之后是可以对数据进行伪装的呢?如:
这里就可以用公钥加密+私钥解密的方式,具体如下:
经典算法:RSA(可用于加密和签名)、DSA(仅用于签名,但速度更快)
非对称加密的优缺点:
优点:可以在不安全网络上传输密钥。
缺点:计算复杂,因此性能相比对称加密差很多。
非对称加密的破解:和对称加密不同之处在于,非对称加密的公钥很容易获得,因此制造原文-密文对是没有困难的事。所以,⾮对称加密的关键只在于,如何找到一个正确的私钥,可以解密所有经过公钥加密过的密文。找到这样的私钥即为成功破解。由于⾮对称加密的⾃身特性,怎样通过公钥来推断出私钥通常是一种思路(例如 RSA),但往往最佳手段依然是穷举法,只是和对称加密破解的区别在于,对称加密破解是不断尝试自⼰的新密钥是否可以将⾃⼰拿到的原文-密文对进行加密和解密,而⾮对称加密时不断尝试⾃⼰的新私钥是否和公钥互相可解。非对称加密的反破解:
和对称加密⼀样,非对称加密算法优秀的标准同样在于,让破解者找不到⽐穷举法更有效的破解手段,并且穷举法的破解时间⾜够⻓。
密码学密钥和登录密码:
- 密钥(key)
场景:⽤于加密和解密。目的:保证数据被盗时不会被人读懂内容。焦点:数据。 - 登录密码(password)
场景:用户进⼊⽹站或游戏前的身份验证。
目的:数据提供方或应用服务方对账户拥有者数据的保护,保证「你是你」的时候才提供权限。焦点:身份。
Base64:
什么是二进制数据呢?
算法:
那为啥要取6位二进制位,而非8位呢?因为2的6次方刚好是64,如果大于6位那不大于64了,那不大于64的数据无法对应Base64的字符了,所以。。
另外需要注意:Base64转换之后会比原数据的体积要大,从现象就可以看出:
用途:
2. 普通的字符串在经过 Base64 编码后的结果会变得⾁眼不可读,因此可以适用于⼀定条件下的防偷窥(较少用)。
缺点:
Base58 对于 Base64 的改动,主要⽬的在于⽤户的便捷性。由于去掉了难以区分的字符,使得 Base58 对于「人工抄写」更加⽅便。另外,去掉了 "+" "/" 号后也让大多数的软件可以方便双击选取。
URL encoding:
例如,要在 http://hencoder.com/users 后⾯添加查询字符串,查询 name 为「隐匿匿&伟⼤大」的⽤户,如果直接写成 http://hencoder.com/user/?name=隐匿&伟大 ,"&" 符号就会被解析为分隔符号,因此需要对它进行转码,转码后的 URL 为 http://hencoder.com/user/?name=隐匿%26伟大 。
压缩与解压缩 Compression & Decompression:
含义:
压缩:把数据转换一种方式来存储,以减小存储空间。
解压缩:把压缩后的数据还原成原先的形式,以便使用。
目的:
减小数据占用的存储空间。
常见的压缩算法:
压缩是编码吗?
![](https://img2018.cnblogs.com/blog/324374/201902/324374-20190205223244128-1146343874.png)
![](https://img2018.cnblogs.com/blog/324374/201902/324374-20190205223441131-1279394484.png)
序列化 Serialization:
目的:
哈希 Hash:
定义:
作用:
经典算法:
MD5、SHA1、SHA256等。
举例说明Hash的本质:
写一个简单的Hash的算法,当然只是为了说明Hash的一个原理,并非真实的实现,比如定义这么一个hash实现的方法:
然后咱们对这样两个字符串进行hash的结果如下:
但是!!!咱们这个碰撞率比较高,也就是说很容易重,比如:
这就是由于咱们的这个hash算法是比较low,成熟的碰撞率会比较低的。
实际用途:
- 数据完整性验证:
从⽹络上下载⽂件后,通过比对⽂件的 Hash 值(例如 MD5、SHA1),可以确认下载的⽂件是否有损坏。如果下载的⽂件 Hash 值和⽂件提供⽅给出的 Hash 值一致,则证明下载的⽂件是完好⽆损的。 - 快速查找:
hashCode()和HashMap,在我们学j2se时教科书上通常会说重写了类的equals()方法,就一定要重写类的hashCode()方法,为啥呢?下面来用例子来阐述一下,对于这个类重写了equals()方法:
然后按照教科书式的要求又重写了hashCode()方法:当然此时的hashCode是比较脆弱,很容易发生碰撞,不过这里重点是为了理解为啥重写了equals()方法之后一定要重写hashCode()方法呢?这就要说到HashMap了,在存数据时是根据对象的hashCode()来进行内存的存储的,如果对象木有重写hashCode()则会默认用Object的默认hashCode()的实现,那就在使用HashMap存对象时会出BUG,对于两个不同的对象由于hashCode()是一样导致值被替换了,所以重写hashCode()是为了给Hash相关的存储对象来使用的,如果对象不会被存储到Hash相关的存储对象中,那确实是木有必要重写hashCode(),但!!谁又能保证你定义的对象不被存储到Hash相当的集合当中呢?所以,保险起见重写了equals()之后,一定要重写hashCode()。
- 隐私保护:
当重要数据必须暴露的时候,有时可以选择暴露它的 Hash 值(例如 MD5),以保障原数据的安全。 例如网站登录时,可以只保存用户密码的 Hash 值,在每次登录验证时只需要将输入的密码的 Hash 值和数据库中保存的 Hash 值作比对就好,⽹站⽆需知道⽤户的密码。这样,当⽹站数据失窃时,⽤户不会因为⾃⼰的密码被盗导致其他网站的安全也受到威胁。
Hash是编码吗?
Hash是加密吗?据说MD5是“不可逆加密”?
![](https://img2018.cnblogs.com/blog/324374/201902/324374-20190211152556009-570151167.png)
这是错误的!!!所以说“不可逆加密”的说法也不正确。
知道了Hash的概念之后,这里就要回过头来说一下非对称加密的,先回顾一下:
其中标红的“签名数据”的大小跟原数据是一样的大的,如果一个10G的视频文件,它的签名数据有10G那么大,那显得太臃肿了,所以事实上会对原数据的hash值进行签名,完整版的非对称加密如下:
字符集 Charset:
含义:
一个由整数向现实世界中的文字符号的Map。
分支:
- ASCII:128 个字符,1 字节。
- ISO-8859-1:对 ASCII 进行扩充,1 字节
- Unicode:13 万个字符,多字节。
1、UTF-8:Unicode 的编码分⽀。2、UTF-16 :Unicode 的编码分⽀。
啥叫“编码分支”呢?下面举个浅显一点的例子说明一下:
每个字对应一个8位的字节数,但是可能UTF-8的表示法不会表示全,可能会这样写:
也就是省略了一些位,而对于UTF-16可能会表示成这样:
当然上面的举例不是太严谨,对于UTF-16很显然是用16位表示一个字符,没有上面例子中写得这么短,但只是为了说明一下“编码分支”这个词的意思。
- GBK / GB2312 / GB18030:中国自研标准,多字节,字符集 + 编码。