编码、加密和登录授权
古典密码学
起源于古代战争:在战争中,为了防止书信被截获后重要信息泄露,人们开始对书信进行加密。移位式加密如密码棒,使用布条缠绕在木棒上的方式来对书信进行加密。
加密算法:缠绕后书写密钥:木棒的尺寸
替换式加密
按规则使用不同的文字来替换掉原先的文字来进行加密。 码表:
原始字符:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密码字符:BCDEFGHIJKLMNOPQRSTUVWXYZA
(把A移位到最后形成密码字符)
原始书信:I love you 加密书信:J mpwf zpv 解读后:I love you
加密算法:替换文字
密钥:替换的码表
现代密码学
可以加密任何二进制数据
非对称加密的出现使得密码学有了更广泛的用途:数字签名
对称加密
通信双方使用同一个密钥,使用加密算法配合上密钥来加密,解密时使用加密过程的完全逆过程配合 密钥来进行解密。
简化模型即上面的古典密码学中替换式加密的模型:对文字进行规则化替换来加密,对密文进行逆向 的规则化替换来解密。
经典算法
DES(56 位密钥,密钥太短而逐渐被弃用)、AES(128 位、192 位、256 位密钥,现在最流行)
对称加密作用
加密通信,防止信息在不安全网络上被截获后,信息被人读取或篡改。
对称加密(如 AES)的破解
破解思路
拿到一组或多组原文-密文对
设法找到一个密钥,这个密钥可以将这些原文-密文对中的原文加密为密文,以及将密文解密为 原文的组合,即为成功破解
反破解
一种优秀的对称加密算法的标准是,让破解者找不到比穷举法(暴力破解法)更有效的破解手段,并 且穷举法的破解时间足够长(例如数千年)。
对称加密的缺点
密钥泄露:不能在不安全网络上传输密钥,一旦密钥泄露则加密通信失败。
非对称加密
原理:使用公钥对数据进行加密得到密文;使用私钥对数据进行解密得到原数据。 非对称加密使用的是复杂的数学技巧,在古典密码学中没有对应的原型。
使用非对称加密通信,可以在不可信网络上将双方的公钥传给对方,然后在发消息前分别对消息使用 对方的公钥来加密和使用自己的私钥来签名,做到不可信网络上的可靠密钥传播及加密通信。
由于私钥和公钥互相可解,因此非对称加密还可以应用于数字签名技术。
通常会对原数据 hash 以后对 hash 签名,然后附加在原数据的后面作为签名。这是为了让数据更小。
经典算法:RSA(可用于加密和签名)、DSA(仅用于签名,但速度更快) 非对称加密的优缺点
优点:可以在不安全网络上传输密钥
缺点:计算复杂,因此性能相比对称加密差很多
非对称加密(如 RSA、ECDSA)的破解
破解思路
和对称加密不同之处在于,非对称加密的公钥很容易获得,因此制造原文-密文对是没有困难的 事
所以,非对称加密的关键只在于,如何找到一个正确的私钥,可以解密所有经过公钥加密过的密 文。找到这样的私钥即为成功破解
由于非对称加密的自身特性,怎样通过公钥来推断出私钥通常是一种思路(例如 RSA),但往往最佳手段依然是穷举法,只是和对称加密破解的区别在于,对称加密破解是不断尝试自己的新密 钥是否可以将自己拿到的原文-密文对进行加密和解密,而非对称加密时不断尝试自己的新私钥是否和公钥互相可解。
反破解
和对称加密一样,非对称加密算法优秀的标准同样在于,让破解者找不到比穷举法更有效的破解手 段,并且穷举法的破解时间足够长。
密码学密钥和登录密码
密钥(key)
场景:用于加密和解密
目的:保证数据被盗时不会被人读懂内容焦点:数据
登录密码(password)
场景:用户进入网站或游戏前的身份验证
目的:数据提供方或应用服务方对账户拥有者数据的保护,保证「你是你」的时候才提供 权限
焦点:身份
登录和授权的区别
登录:身份认证,即确认「你是你」的过程。
授权:由身份或持有的令牌确认享有某些权限(例如获取用户信息)。登录过程实质上的目的也 是为了确认权限。
因此,在实际的应用中,多数场景下的「登录」和「授权」界限是模糊的。
HTTP 中确认授权(或登录)的两种方式
- 通过 Cookie
- 通过 Authorization Header
Cookie
起源:「购物车」功能的需求,由 Netscape 浏览器开发团队打造。
工作机制:
1.服务器需要客户端保存的内容,放在 headers 里返回,客户端会自动保存。
2.客户端保存的 Cookies,会在之后的所有请求里都携带进器。
3.客户端保存 Cookie 是按照服务器域名来分类的,例如 shop.com 发回的 Cookie 保存下来以后,在之后向 games.com 的请求中并不会携带。
4.客户端保存的 Cookie 在超时后会被删除、没有设置超时时间的 Cookie (称作 Session Cookie)在浏览器关闭后就会自动删除;另外,服务器也可以主动删除还未过期的客户Cookies。
Authorization
两种主流方式: Basic 和 Bearer
Basic:
格式:Authorization: Basic <username:password(Base64ed)>
Bearer:
格 式 :Authorization: Bearer <bearer token> bearer token 的获取方式:通过 OAuth2 的授权流程
OAuth2 的流程(下面的文字可以配合视频课程或者 PPT 中的图来看):
- 第三方网站向授权方网站申请第三方授权合作,拿到 client id 和 client secret
- 用户在使用第三方网站时,点击「通过 XX (如 GitHub) 授权」按钮,第三方网站将页面跳转到授权方网站,并传入 client id 作为自己的身份标识
- 授权方网站根据 client id ,将第三方网站的信息和第三方网站需要的用户权限展示给用户,并询问用户是否同意授权
- 用户点击「同意授权」按钮后,授权方网站将页面跳转回第三方网站,并传入
Authorization code 作为用户认可的凭证。
- 第三方网站将 Authorization code 发送回自己的服务器
- 服务器将 Authorization code 和自己的 client secret 一并发送给授权方的服务器,授权方服务器在验证通过后,返回 access token。OAuth 流程结束。
- 在上面的过程结束之后,第三方网站的服务器(或者有时客户端也会)就可以使用 access token 作为用户授权的令牌,向授权方网站发送请求来获取用户信息或操作用户账户。但这已经在 OAuth 流程之外。
为什么 OAuth 要引入 Authorization code,并需要申请授权的第三方将 Authorization code 发送回自己的服务器,再从服务器来获取 access token,而不是直接返回 access token ?这样复杂的流程意义何在? 为了安全。OAuth 不强制授权流程必须使用 HTTPS,因此需要保证当通信路径中存在窃听者时,依然具有足够高的安全性。
第三方 App 通过微信登录的流程,也是一个 OAuth2 流程:
- 第三方 App 向腾讯申请第三方授权合作,拿到 client id 和 client secret
- 用户在使用第三方 App 时,点击「通过微信登录」,第三方 App 将使用微信 SDK 跳转到微信,并传入自己的 client id 作为自己的身份标识
- 微信通过和服务器交互,拿到第三方 App 的信息,并限制在界面中,然后询问用户是否同意授权该 App 使用微信来登录
- 用户点击「使用微信登录」后,微信和服务器交互将授权信息提交,然后跳转回第三方
App,并传入 Authorization code 作为用户认可的凭证
- 第三方 App 调用自己服务器的「微信登录」Api,并传入 Authorization code,然后等待服务器的响应
- 服务器在收到登录请求后,拿收到的 Authorization code 去向微信的第三方授权接口发送请求,将 Authorization code 和自己的 client secret 一起作为参数发送,微信在验证通过后,返回 access token
- 服务器在收到 access token 后,立即拿着 access token 去向微信的用户信息接口发送请求,微信验证通过后,返回用户信息
- 服务器在收到用户信息后,在自己的数据库中为用户创建一个账户,并使用从微信服务器 拿来的用户信息填入自己的数据库,以及将用户的 ID 和用户的微信 ID 做关联
- 用户创建完成后,服务器向客户端的请求发送响应,传送回刚创建好的用户信息
- 客户端收到服务器响应,用户登录成功在自家 App 中使用 Bearer token
有的 App 会在 Api 的设计中,将登录和授权设计成类似 OAuth2 的过程,但简化掉Authorization code 概念。即:登录接口请求成功时,会返回 access token,然后客户端在之后的请求中,就可以使用这个 access token 来当做 bearer token 进行用户操作了。
Refresh toke
{
"token_type": "Bearer",
"access_token": "xxxxx",
"refresh_token": "xxxxx",
"expires_time": "xxxxx"
}
用法:access token 有失效时间,在它失效后,调用 refresh token 接口,传入 refresh_token
来获取新的 access token。
目的:安全。当 access token 失窃,由于它有失效时间,因此坏人只有较短的时间来「做坏事」;同时,由于(在标准的 OAuth2 流程中)refresh token 永远只存在与第三方服务的服务器中,因此 refresh token 几乎没有失窃的风险。
TCP 连接
什么叫做连接
通信双方建立确认「可以通信」,不会将对方的消息丢弃,即为「建立连接」
TCP 连接的建立与关闭
TCP连接3次握手
• 第一次:客户端发送请求到服务器,服务器知道客户端发送,自己接收正常。SYN=1,seq=x
• 第二次:服务器发给客户端,客户端知道自己发送、接收正常,服务器接收、发送正常。ACK=1,ack=x+1,SYN=1,seq=y
• 第三次:客户端发给服务器:服务器知道客户端发送,接收正常,自己接收,发送也正常.seq=x+1,ACK=1,ack=y+1
上面分析过程可以看出,握手两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论的。
TCP
TCP断开连接4次挥手
• 第一次:客户端请求断开FIN,seq=u
• 第二次:服务器确认客户端的断开请求ACK,ack=u+1,seq=v
• 第三次:服务器请求断开FIN,seq=w,ACK,ack=u+1
• 第四次:客户端确认服务器的断开ACK,ack=w+1,seq=u+1
HTTPS
Hypertext Transfer Protocol Secure:超文本传输安全协议)是一种透过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
HTTPS 默认工作在 TCP 协议443端口,它的工作流程一般如以下方式:
- 1、TCP 三次同步握手
- 2、客户端验证服务器数字证书
- 3、DH 算法协商对称加密算法的密钥、hash 算法的密钥
- 4、SSL 安全加密隧道协商完成
- 5、网页以加密的方式传输,用协商的对称加密算法和密钥加密,保证数据机密性;用协商的hash算法进行数据完整性保护,保证数据不被篡改。
- 6、建立TCP连接采用非对称加密,数据传输利用建立TCP连接时双方达成共识的秘钥进行对称加密(因为数据量很大,也用非对称会影响传输效率)
截至 2018 年 6 月,Alexa 排名前 100 万的网站中有 34.6% 使用 HTTPS 作为默认值,互联网 141387 个最受欢迎网站的 43.1% 具有安全实施的 HTTPS,以及 45% 的页面加载(透过Firefox纪录)使用HTTPS。2017 年3 月,中国注册域名总数的 0.11%使用 HTTPS。
根据 Mozilla 统计,自 2017 年 1 月以来,超过一半的网站流量被加密。
HTTP 与 HTTPS 区别
- HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
- 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
- HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
- http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
- HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。
HTTPS 的工作原理
我们都知道 HTTPS 能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用 HTTPS 协议。
1、客户端发起 HTTPS 请求
这个没什么好说的,就是用户在浏览器里输入一个 https 网址,然后连接到 server 的 443 端口。
生成客户端随机数A
2、服务端的配置
采用 HTTPS 协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl 就是个不错的选择,有 1 年的免费服务)。
这套证书其实就是一对公钥和私钥,如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
生成服务端随机数B
3、传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4、客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。
如果证书没有问题,那么就用客户端随机数A,服务端随机数B生成一个随机值C,然后用证书对该随机值进行加密(pre-master-secret),就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5、传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6、服务端解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密,所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
7、传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。
8、客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容,整个过程第三方即使监听到了数据,也束手无策。
Base64
将二进制数据转换成由 64 个字符组成的字符串的编码算法
什么是二进制数据?
广义:所有计算机数据都是二进制数据狭义:非文本数据即二进制数据
算法
将原数据每 6 位对应成 Base 64 索引表中的一个字符编排成一个字符串(每个字符 8 位)。
Base64 索引表:
编码示例:把「Man」进行 Base64 编码
编码示例:Base64 的末尾补足
Base64 的用途
- 将二进制数据扩充了储存和传输途径(例如可以把数据保存到文本文件、可以通过聊天对话框或 短信形式发送二进制数据、可以在 URL 中加入简单的二进制数据)
- 普通的字符串在经过 Base64 编码后的结果会变得肉眼不可读,因此可以适用于一定条件下的防偷窥(较少用)
Base64 的缺点
因为自身的原理(6 位变 8 位),因此每次 Base64 编码之后,数据都会增大约 1/3,所以会影响存储和传输性能。
「Base64 加密图片传输更安全和高效」???
不。首先,Base64 并不是加密;另外,Base64 会导致数据增大 1/3,降低网络性能,增大用户流量开销,是画蛇添足的手段。(最好不要拿来 diss 你们公司的后端哟,友善)
Base64 对图片进行编码的用于在于,有时需要使用文本形式来传输图片。除此之外,完全没必要使用 Base64 对图片进行额外处理。
变种:Base58
比特币使用的编码方式,去掉了 Base64 中的数字 "0",字母大写 "O",字母大写 "I",和字母小写"l",以及 "+" 和 "/" 符号,用于比特币地址的表示。
Base58 对于 Base64 的改动,主要目的在于用户的便捷性。由于去掉了难以区分的字符,使得Base58 对于「人工抄写」更加方便。另外,去掉了 "+" "/" 号后也让大多数的软件可以方便双击选取。
URL 使用的百分号编码
在 URL 的字符串中,对一些不用于特殊用途的保留字符,使用百分号 "%" 为前缀进行单独编码,以避免出现解析错误。
例如,要在 http://hencoder.com/users 后面添加查询字符串,查询 name 为「隐匿&伟大」的用户,如果直接写成 http://hencoder.com/user/?name=隐匿&伟大 ,"&" 符号就会被解析为分隔符 号,因此需要对它进行转码,转码后的 URL 为 http://hencoder.com/user/?name=隐匿%26伟大 。
这种编码仅用于 URL,目的是避免解析错误的出现。
压缩与解压缩
含义
压缩:将数据使用更具有存储优势的编码算法进行编码。解压缩:将压缩数据解码还原成原来的形式,以方便使用。
目的
减小数据占用的存储空间。
比如一个数据是AAAAAAAAAAAAAAAAAAAABB
使用某种算法压缩后的数据为:
compress:A:20;B:2
注:具体的压缩场景有很多,因此压缩算法也会复杂得多,上面只是一个原型算法。
压缩是编码吗?
是。所谓编码,即把数据从一种形式转换为另一种形式。压缩过程属于编码过程,解压缩过程属于解 码过程。
常见压缩算法
DEFLATE、JPEG、MP3 等。
图片与音频、视频编解码
含义
将图像、音频、视频数据通过编码来转换成存档形式(编码),以及从存档形式转换回来(解码)。
目的
存储和压缩媒体数据(大多数媒体编码算法会压缩数据,但不是全部)。
图片压缩粗暴算法举例
一张纯白(白色的 16 进制数值为 0xffffff)的 64x64 不透明像素图片,原数据格式大致为:
width:64;height:64;ffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff. f
fffff
使用某种算法压缩后的数据为:
width:64;height:64;ffffff:[0,0]-[63,63]
注:具体的压缩场景有很多,因此压缩算法也会复杂得多,上面只是一个原型算法。 音频与视频的编码与上面的图片编码同理。
序列化
目的
让内存中的对象可以被储存和传输。
序列化是编码吗?
不是
和编码的区别
编码是把数据由一种数据格式转换成另一种数据格式;而序列化是把数据由内存中的对象(而不是某 种具体的格式)转换成字节序列。
(1)序列化
由于存在于内存中的对象都是暂时的,无法长期驻存,为了把对象的状态保持下来,这时需要把对象写入到磁盘或者其他介质中,这个过程就叫做序列化。
(2)反序列化
反序列化恰恰是序列化的反向操作,也就是说,把已存在在磁盘或者其他介质中的对象,反序列化(读取)到内存中,以便后续操作,而这个过程就叫做反序列化。
概括性来说序列化是指将对象实例的状态存储到存储媒体(磁盘或者其他介质)的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。
(3)实现序列化的必要条件
一个对象要实现序列化操作,该类就必须实现了Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象类,而Parcelable接口则是android中特有的序列化接口,在某些情况下,Parcelable接口实现的序列化更为高效,关于它们的实现案例我们后续会分析,这里只要清楚知道实现序列化操作时必须实现Serializable接口或者Parcelable接口之一即可。
(4)序列化的应用情景
主要有以下情况(但不限于以下情况)
1)内存中的对象写入到硬盘;
2)用套接字在网络上传送对象;
Serializable
Serializable是java提供的一个序列化接口,它是一个空接口,专门为对象提供标准的序列化和反序列化操作,使用Serializable实现类的序列化比较简单,只要在类声明中实现Serializable接口即可,同时强烈建议声明序列化标识。如下:
public class User implements Serializable {
private static final long serialVersionUID = -2083503801443301445L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Parcelable
鉴于Serializable在内存序列化上开销比较大,而内存资源属于android系统中的稀有资源(android系统分配给每个应用的内存开销都是有限的),为此android中提供了Parcelable接口来实现序列化操作,Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如通过Intent在activity间传输数据,而Parcelable的缺点就使用起来比较麻烦,下面给出一个Parcelable接口的实现案例,大家感受一下:
public class User implements Parcelable {
public int id;
public String name;
public User friend;
/**
* 当前对象的内容描述,一般返回0即可
*/
@Override
public int describeContents() {
return 0;
}
/**
* 将当前对象写入序列化结构中
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
dest.writeParcelable(this.friend, 0);
}
public NewClient() {}
/**
* 从序列化后的对象中创建原始对象
*/
protected NewClient(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
//friend是另一个序列化对象,此方法序列需要传递当前线程的上下文类加载器,否则会报无法找到类的错误
this.friend=in.readParcelable(Thread.currentThread().getContextClassLoader());
}
/**
* public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
* 重写接口中的两个方法:
* createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
* newArray(int size) 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用。
*/
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
/**
* 从序列化后的对象中创建原始对象
*/
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
/**
* 创建指定长度的原始对象数组
*/
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
Hash
定义
Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。(百度百科定义)
作用
相当于从数据中提出摘要信息,因此最主要用途是数字指纹。
Hash 的实际用途:唯一性验证
例如 Java 中的 hashCode() 方法。
怎么重写 hashCode 方法?
把 equals() 方法中的每个用于判断相等的变量都放进 hashCode() 中,一起生成一个尽量不会碰撞的整数即可
为什么每次重写 equals() 方法都需要?因为你要把新的判断条件放进 hashCode() 啊。
Hash 的实际用途:数据完整性验证
从网络上下载文件后,通过比对文件的 Hash 值(例如 MD5、SHA1),可以确认下载的文件是否有损坏。如果下载的文件 Hash 值和文件提供方给出的 Hash 值一致,则证明下载的文件是完好无损的。
Hash 的实际用途:快速查找
HashMap
Hash 的实际用途:隐私保护
当重要数据必须暴露的时候,有事可以选择暴露它的 Hash 值(例如 MD5),以保障原数据的安全。例如网站登录时,可以只保存用户密码的 Hash 值,在每次登录验证时只需要将输入的密码的 Hash 值和数据库中保存的 Hash 值作比对就好,网站无需知道用户的密码。这样,当网站数据失窃时,用户不会因为自己的密码被盗导致其他网站的安全也受到威胁。
注意:这不属于加密。
Hash 是编码吗?
不是。 Hash 是单向过程,往往是不可逆的,无法进行逆向恢复操作,因此 Hash 不属于编码。
Hash 是加密吗?
不是。Hash 是单向过程,无法进行逆向回复操作,因此 Hash 不属于加密。(记住,MD5 不是加密!)
字符集
含义:一个由整数向现实世界中的文字符号的 Map
分支:
ASCII:128 个字符,1 字节
ISO-8859-1:对 ASCII 进行扩充,1 字节
Unicode:13 万个字符,多字节
UTF-8:Unicode 的编码分支
UTF-16 :Unicode 的编码分支
GBK / GB2312 / GB18030:中国自研标准,多字节,字符集 + 编码