Web3.0 · 基础层技术 · SCQA模型趣谈密码学

【小木箱成长营】密码学系列教程:

Web3.0 · 基础层技术 ·密码学在移动端应用与实践

一、序言

Hello,我是小木箱,欢迎来到小木箱成长营密码学系列教程,今天将分享Web3.0 · 基础层技术 · SCQA模型趣谈密码学。

SCQA模型趣谈密码学主要分为四部分,第一部分是加解密算法,第二部分是Hash算法,第三部分是数据编解码,最后一部分是总结与展望。

其中,加解密算法主要是分为四部分,第一部分是对称加密,第二部分是DH交换算法,第三部分是非对称加密,第四部分是混合加密。

如果学完小木箱密码学系列教程,那么任何人完成高性能日志组件、网络接口组件和网络优化工作,甚至迎接Web3.0都会有巨大帮助。

二、加解密算法

SCQA模型是麦肯锡芭芭拉·明托在《金字塔原理》中提出的“结构化表达”模板工具,常用于方案、文案、广告、演讲、讲故事、写作等。SCQA是Situation、Complication、Question和Answer4个英文单词简称,分别是

  • S—业务背景
  • C—困境冲突
  • Q—分析问题
  • A—解决问题

如果你想把难以理解的密码学知识表达清楚,那么建议采用万能表达模板—SCQA。

加密技术⽆处不在但是容易忽略。更多的了解加密技术能做什么,不能做什么,对我们建⽴更加完善的信息安全意识是⾮常重要的。

加密技术的演进其实是⼀场没有硝烟的战争,在加密⽅和破解⽅惊⼼动魄的攻守战中不断完善。

接下来,我们将⾸先利用⼀个⼩故事,然后通过业务背景、困境冲突、分析问题和解决问题的SCQA模型⽅式了解加密技术演进,最终达到活学活用的目的。

S: 业务背景

故事的主⼈公是小木箱和粉丝。他们通过微信公众平台进行传话,小木箱给粉丝发了⼀个消息:微信公众号小木箱成长营。

image.png

但是,消息被对⾯的黑粉窃听了!

image.png

于是黑粉⽴刻拦截了他们的信息,并把小木箱和粉丝交流关系链中断了。

C: 困境冲突

当下面临的问题有三个。第一个窃听问题,小木箱和粉丝交流过程中,内容是明文传输的,内容被黑粉窃听,导致信息泄露风险。

第二个是密钥配送问题,通过对称加密算法,小木箱和粉丝好像解决了⼀个信息传递的问题,但是,实际操作过程中,发现了⼀个⼤问题:如何共享秘钥?这就是密钥配送问题。

第三个问题是中间⼈攻击问题,小木箱和粉丝即使解决了密钥配送问题,不一定能确保密钥通信安全。

黑粉通过⾃⼰的聪明才智,想到了⼀个劫持+篡改的⽅案,再次攻破了DH密钥交换和⾮对称加密,即中间⼈攻击。

Q:分析问题

如何解决窃听问题呢?

针对窃听问题,为了避免被黑粉窃听,小木箱和粉丝想到了⼀个好办法:首先小木箱和粉丝共享了⼀个密钥,然后小木箱先把消息加密成密⽂,最后再发送给粉丝,粉丝拿到密⽂之后⽤密钥解密成明⽂。这就是对称加密。

image.png

如何解决密钥配送问题呢?

针对密钥配送问题,密钥配送问题的解决⽅案有很多,有两种解决密钥配送问题⽅案:DH 交换算法和⾮对称加密算法。

如何解决中间人攻击问题呢?

中间人攻击本质即篡改和伪装,解决方案有单向散列、消息验证码、数字签名和数字证书四种方式。

A: 解决问题

针对窃听问题,首先我们来说说对称加密,加密方式主要讲解四种加解密方式: 第一种是DES加密,第二种是3DES加密,第三种是AES加密,第四种是ChaCha加密。

下面小木箱将从简介、历史、现状、明文块长和密钥长和加解密流程等多方面维度讲解四种加解密算法。

2.1 对称加密

2.1.1 对称加密简介

加密处理方式有对称加密和非对称加密两种。

其中,对称加密指的是通信双⽅同时掌握⼀个密钥,加密解密都是由⼀个密钥完成的(即加密密钥等于解密密钥,加解密密钥可以相互推倒出来)。

image.png

对称加密双⽅通信前共同拟定⼀个密钥,不对第三⽅公开,解密时使用加密过程的完全逆过程配合密钥来进行解密。

2.1.2 对称加密手段

2.1.2.1 DES

其中,对称加密指的是加密和解密的密钥不同的加密算法。首先我们讲解一下第一种对称加密算法DES 加密。

2.1.2.1.1 DES 简介

关于DES加密,DES,全称Data Encryption Standard,数据加密标准。

2.1.2.1.2 DES 历史

DES是1975年IBM推出,并随后在国际上⼴泛使⽤开来。

2.1.2.1.3 DES 现状

随着计算机技术的发展,在20世纪末的时候,DES算法已经可以被暴⼒破解。在1999年的DES III ⽐赛中,只⽤了22 ⼩时多就完成了破解。所以现在不要再使⽤DES算法。

2.1.2.1.4 DES 明文块长和密钥长

DES 算法的明⽂块⻓度是64位。密钥总⻓度是64位,其中每隔7位会有⼀个⽐特的错误校验,所以有效密钥⻓度为56位。

2.1.2.1.5 DES 加解密流程

DES的加解密流程如下:

  1. 第一步:DES算法的基本结构被称为Feistel⽹络。Feistel⽹络中,⼀个基本单位叫做轮,整个加密过程就是由16个轮循环组成。
  2. 第二步:明⽂被平分成左右两部分L0和R0。L0经过加密得到加密后的L0,作为下⼀轮的右半部分R1。R0不做处理,直接作为下⼀轮的左半部分L1。

2.1.2.1.6 DES 加密结构

DES解密和加密的结构是⼀样的(利⽤传统的换位、异或、置换等加密⽅法),具体可以参考下面的图解。

2.1.2.1.7 DES 代码实现

github.com/strich1991/…

2.1.2.2 3DES

然后,我们讲解一下第二种对称加密算法3DES加密。

2.1.2.2.1 3DES 简介

3DES算法是将DES算法重复3次的⼀种算法。

2.1.2.2.2 3DES 历史

3DES是DES算法被攻破之后,被开发出来临时替代DES算法的。1999年,NIST(National Institute of Standards and Technology,美国国家标准技术研究所)将3DES指定为过渡加密标准。

2.1.2.2.3 3DES 现状

3DES算法由于其处理效率不⾼,并且作为过渡标准,所以除了⼀些要向下兼容原有的DES算法的场景,现在很少被使⽤。

2.1.2.2.4 3DES 明文块长和密钥长

3DES算法的明⽂块⻓度为64位,有效密钥⻓度为56*3位。

2.1.2.2.5 3DES 加解密过程
  1. 3DES的加密为依次进⾏密钥1的DES加密、密钥2的DES解密、密钥3的DES加密。
  2. 3DES的解密为依次进⾏密钥3的DES解密、密钥2的DES加密、密钥1的DES

解密。

  1. 3DES的加密的结构是加解密交替进⾏⽽不是进⾏3次加密(思考⼀下这是为什么?)

由于DES密码长度容易被暴力破解,增加DES的密钥长度可反破解,因此针对每个数据块进行三次DES加密,即3DES。

组合分组方法设计的分组3DES加密算法,3DES密钥相比DES长度更长,安全性更高。

2.1.2.2.6 3DES 代码实现

github.com/songxiaolia…

2.1.2.3 AES

接着,我们讲解一下第三种对称加密算法AES加密。

2.1.2.3.1 AES 简介

AES算法,Advanced Encryption Standard,⾼级加密标准,是取代DES算法的⼀种新的对称加密标准。

2.1.2.3.2 AES 历史

AES是NIST公开竞选得到的⼀种加密标准。可以说是先有了AES的名字,然后竞选之后才确定的算法。最终被选中的算法叫做Rijndael算法。不过严格来讲,AES是Rijndael的⼀种特殊情况。

2.1.2.3.3 AES 现状

AES现在已经是最流⾏的对称密钥加密算法,⼴泛应⽤在各个领域。也是我们现在推荐使⽤的对称加密算法。

2.1.2.3.4 AES 明文块长和密钥长

AES的块⻓128位,密钥⻓度⽀持128位、192位、256位三种⻓度。(这⾥注意,Rijndael算法的块⻓和密钥⻓度,是在128-256之间的32倍数即可。

2.1.2.3.5 AES 加解密过程

AES加密过程分为两个过程,⼀是密钥扩展过程、⼀是明⽂加密过程。

A: 密钥扩展过程:

密钥扩展过程是基于⽤户密钥,通过Rijndael密钥编排算法⽣成多组128⽐特⻓的轮密钥,根据密钥⻓度,分别⽣成10组、12组和14组轮密钥。

B: 明文加密过程:

  1. AES加密与DES加密⼀样,是由多轮组成。根据密钥⻓度,分别是10轮、12轮、14轮。

  2. 每⼀轮由以下四种运算组合⽽成:

    1. SubBytes,字节替换。是通过⼀个S-Box对每个字节进⾏替换操作。
    2. ShiftRows,⾏位移。每⼀⾏根据所在⾏数位移不同的字节数。
    3. MixColums,列混合。每⼀列需要跟⼀个常量矩阵相乘。
    4. AddRoundKey,轮密钥加。将列混合之后的结果和轮密钥做异或运算。
  3. 第⼀轮只有AddRoundKey运算。

  4. 最后⼀轮是SubBytes->ShiftRows->AddRoundKey运算。

  5. 中间轮都是SubBytes->ShiftRows->MixColums->AddRoundKey运算。

AES解密过程就是AES加密逆过程,小木箱不做过多讲解。

2.1.2.3.5 AES 代码实现

github.com/ForTheDevel…

2.1.2.4 ChaCha20

最后,我们讲解一下第四种对称加密算法ChaCha20加密

2.1.2.4.1 ChaCha20 简介

ChaCha20算法是Google设计的一种新型流密码算法,ChaCha命名来源于印度某漫画"Chacha Chaudhary",20表示ChaCha20算法有20轮加密计算。

ChaCha20带Poly1305消息认证码的ChaCha20(即ChaCha20-Poly1305),作为OpenSSL中RC4的替代品,用以完成互联网的安全通信。

Google最初实现了HTTPS(TLS/SSL)流量在Chrome浏览器(Android手机版)与Google网站之间的通信。

2.1.2.4.2 ChaCha20 历史

2008年,丹尼尔·J·伯恩斯坦发布“ChaCha”密码家族,目的是增加每一轮扩散以提升性能。

2013年,Google提出ChaCha20-Poly1305算法,11月份在Chrome31版本启用了ChaCha20-Poly1305算法。

2014年,所有的IOS设备和Android设备上Chrome启用了ChaCha20-Poly1305算法。

firfox密码库用的是NSS,NSS3.23版本支持ChaCha20/Poly1305。

2.1.2.4.3 ChaCha20 现状

ChaCha20算法因为其轻量级、链路加密、密钥安全、IOT安全特征,所以更适用于ARM设备。

ChaCha20-poly1305比AES-128-GCM性能高,但因为ChaCha20 IOT安全特征,因此手机设备更适合ChaCha20-poly1305算法,电脑上更适合AES-128-GCM算法。

2.1.2.4.4 ChaCha20 明文长和密钥长

ChaCha20矩阵输入一个256位的密钥长度、64位随机数、64位计数器值以及4×32位的常数,常数填充在32位整型数组中作为初始矩阵。

2.1.2.4.5 ChaCha20 加解密过程

2.1.2.4.5.1 ChaCha20加密

了解ChaCha20加密之前我们首先要熟悉三个新概念,第一个是ChaCha20的初始矩阵,第二个是初始矩阵置换,第三个是轮函数。

首先,聊聊ChaCha20的初始矩阵,ChaCha20的初始矩阵是指输入一个256位的密钥、64位随机数、64位计数器值以及4×32位的常数,它们均填充在32位整型数组中作为初始矩阵。

其次,聊聊初始矩阵置换,初始矩阵置换是指 ChaCha20算法有20轮运算,其中奇数轮次与偶数轮次在执行轮函数前需要分别经过行置换和列置换,故20轮运算可以看作10次迭代,每次迭代先做行置换再做列置换。

接着,聊聊轮函数,轮函数是指在矩阵每次完成置换后,都需要执行一次轮函数QUARTERROUND,该函数输入为4个32位串,即4个数组中的元素,输出同样也为4个32位串,这样执行完轮函数后除了数据以外,矩阵结构未发生任何变化。

最后,聊聊ChaCha20加密过程,ChaCha20加密其实是将需要加密的信息(明文)与密钥流按位异或即得到密文,明文大于512位时,对轮函数进行20轮周期(10轮行周期+10轮列周期),初始矩阵已经变成了一个新的4×4矩阵,此时将新矩阵与初始矩阵矢量相加,得到的矩阵再拆分倒序序列化处理后即得到一个512位的密钥比特流。

由于计数器是32位,理论上可以生成2^512bit(256GB)的密钥流,所以一般长度的信息加密完全足够,这就是ChaCha20加密过程。

2.1.2.4.5.2 ChaCha20解密

聊完ChaCha20加密过程,我们再聊聊ChaCha20解密过程,接收方使用发送方传输过来的初始密钥、随机数以及协商好的常数和依次递增的计数器值按照ChaCha20的密钥流生成规则产生与加密相同的密钥流,按位与密文异或即可得到明文,这就是ChaCha20解密过程。

2.1.2.5 ChaCha20 代码实现

github.com/kitsook/Cha…

2.1.3 对称加密破解思路

说完四种加解密算法,小木箱说说对称加密算法的破解思路。

对称加密算法破解比较简单,首先拿到⼀组或多组原文-密文对,然后设法找到⼀个密钥,这个密钥可以将这些原文-密文对中的原文加密为密文,以及将密文解密为原⽂的组合,即成功破解。

2.1.4 对称加密反破解

对称加密如何反破解呢?

⼀种优秀的对称加密算法的标准是让破解者找不到⽐穷举法(暴力破解法)更有效地破解⼿段,并且穷举法的破解时间⾜够长(例如数千年)。

2.1.5 对称加密优缺点

对称加密算法的优点很明显,效率高,性能高。缺点是有密钥泄露风险,只能在安全网络上传输密钥,一旦密钥泄露则加密通信失败。

2.1.6 对称加密作用

对称加密算法的作用在于加密通信,防⽌信息在不安全网络上被截获后,信息被人读取或篡改。

2.1.7 对称加密分组和填充⽅式

2.1.7.1 分组模式

从上⾯的算法,我们可以看到,输⼊的明⽂都是固定⼤⼩的块。那么对于⼀个任意⻓度的明⽂,要如何加密呢?

答案就是分组。下面简单介绍CBC、CTR和CFB三种分组模式。

2.1.7.1.1 CBC模式

CBC模式的全称是Cipher Block Chaining模式,密文分组链接模式。名字中也展示CBC的实质,像链条一样相互链接在一起。

CBC加密“链条”起始于一个初始化向量IV,这个初始化向量IV是一个随机的比特序列。

CBC加密必须是从“链条”头开始加密,所以中间任何一个分组都无法单独生成密文。

CBC解密的时候,如果解密“链条”中间有一环“断”了,会出现什么问题呢?

CBC解密过程中如果有一环出现了问题,硬盘等问题出现了,但是整个链条长度没变,如上图的情况,那么一个坏的环会影响2个分组的解密。

如果链条长度也发生变化了,或者某个分组中的1个比特位在网络传输过程中缺失了。那么影响的解密分组可能就不止2个分组了。

因为会引起整个链条上重新分组,这样一来导致原文无法解密(因为位数少于分组要求,解密的时候不会填充末尾分组不足的比特位)。

这一点算是CBC链式的一个“小缺点” 。一个比特位的缺失会导致整个密文无法解析。

对CBC的攻击

由于CBC是链式的,所以攻击者可以考虑从“头”开始攻击,即攻击初始化向量IV,例如把初始化向量中的某些比特位进行0,1反转。

这样的话,消息接收者在解密消息的时候,明文1分组会受到初始化向量的影响,出现错误。

还有一种攻击办法是直接攻击密文,例如密文分组中的某个分组n被改变了,那么就会影响到明文分组n+1的解密。

2.1.7.1.2 CTR模式

CTR模式的全称是CounTeR模式(计数器模式)。CTR模式是一种通过将逐次累加的计数器进行加密来生成密钥流的流密码。

注意上图中解密过程,中间是加密而不是解密!因为需要保证明文和密文之间异或的对象不变。不变才能异或两次还原明文。

计数器每次都会生成不同的nonce来作为计数器的初始值。这样保证每次的值都不同。

这种方法就是用分组密码来模拟生成随机的比特序列。

对 CTR 的攻击

在被攻击方面CTR和OFB是差不多的。CTR模式的密文分组中有一个比特被反转了,则解密后明文分组中仅有与之对应的比特会被反转,这个错误不会被放大。

不过CTR模式比OFB模式相比有一个更好的优点在于,如果OFB模式某次密钥流的一个分组进行加密后生成的结果和前一次一样,那么这个分组之后的每次密钥流都不变了。

CTR模式就不会存在这一问题。

2.1.7.1.3 CFB模式

CFB模式的全称是Cipher FeedBack模式(密文反馈模式)。在CFB模式中,前一个密文分组会被送到密码算法的输入端。反馈即返回输入端。

注意上图中解密过程,中间是加密而不是解密!因为需要保证明文和密文之间异或的对象不变。不变才能异或两次还原明文。

CFB整个过程很像一次性密码本,如果把明文分组前的加密部分全部都看成一个随机比特序列,那么就和一次性密码本的流程一样了。由算法生成的比特序列称为密钥流

在CFB模式中,密码算法就相当于用来生成密钥流的伪随机数生成器,初始化向量相当于是伪随机数生成器的种子。

也因为它是伪随机数,所以CFB不具备一次性密码本绝对无法被破译的性质的。

所以说,CFB是一种使用分组密码来实现流密码的方式之一

对CFB的攻击

可以对CFB实施重放攻击(replay attack)

例如攻击者可以把上一次会话中的部分分组截取出来放进下次会话随机位置。

这样消息接收者在拿到密文后进行解密,会导致其中一个分组出现错误(上图中是明文分组2解密失败),这个时候无法判断是通信出错还是被人攻击所致。(想要判断需要用到消息认证码才行,而此处只是单纯的CFB)

2.1.7.2 填充⽅式

在分组的前提下,如果明⽂的⻓度不能被块⻓整除的情况,就需要填充。主要有三种填充⽅式:

  • NoPadding,不填充,很少⽤。需要使⽤者保证明⽂⻓度是块⻓的整数倍。

  • ZeroPadding,缺字节填0,不缺字节填⼀个块的0。

  • PKCS7Padding,缺⼏个字节就每字节都填⼏。不缺填⼀个块的块⻓

最后,简单总结一下六种分组模式和三种填充方式

填充方式 特点
NoPadding 不填充,很少⽤。需要使⽤者保证明⽂⻓度是块⻓的整数倍
ZeroPadding 缺字节填 0,不缺字节填⼀个块的 0
PKCS7Padding 缺⼏个字节就每字节都填⼏。不缺填⼀个块的块⻓

关于对称加密小木箱讲解到这里了,对称加密小木箱讲解了四种加密方式、对称加密破解思路、对称加密反破解、对称加密优缺点、对称加密作用和对称加密分组和填充方式。

其中对称加密的四种加密方式分为DES加密、3DES加密、AES加密和ChaCha20加密等。

如果想了解更多密码学知识内容,那么小木箱建议大家通过《图解密码技术》一书进行深度学习。下面我们将进入DH交换算法的讲解。

2.2 DH 交换算法

小木箱在加解密算法开篇说了,对称加密算法存在的困境冲突有密钥配送问题,解决密钥配送问题的解决⽅案有很多,下⾯介绍两种常⻅的解决密钥配送问题的⽅案:DH交换算法和⾮对称加密算法。

2.2.1 DH交换算法 简介

解决密钥配送问题第一种⽅案是DH交换算法,DH交换算法是由Diffie和Hellman在1976年发明的。

2.2.2 DH交换算法 历史意义

DH算法作为⾮对称密码技术的⿐祖,⼀⽅⾯将加密算法的基本⼯具从代换和置换扩展到数学函数,另⼀⽅⾯⾮对称的⽅式对密钥配送、数字认证等都有极其重要的作⽤。DH算法可以说是密码学史上最重要的⼀次⾰命。

2.2.3 DH交换算法 现状

⽬前DH算法被⼴泛应⽤在安全领域,⽐如Https中的TLS握⼿协议等。

2.2.4 DH交换算法 理论依据

DH交换算法求模公式 ( a x m o d   p ) y   m o d   p   =   a x y   m o d   p (a^x mod p)^y mod p = a^{xy} mod p ,DH交换算法离散对数难题 b   =   a x   m o d   p b = a^x mod p ,对于给定的素数a和p,已知x求b很容易,但是已知b求x很难,难度大概是 O ( 2 n ) O(2^n) ,其中n是p的位数。

2.2.5 DH交换算法 过程分析

  1. 小木箱选定公共参数a和p

  2. 小木箱选择一个私密的参数x,并且计算出 Y a Y_a

  3. 小木箱将a、p、 Y a Y_a 一起发送给粉丝

  4. 粉丝选定一个私密的参数y,并且计算出 Y b Y_b

  5. 粉丝将 Y b Y_b 发送给小木箱

  6. 小木箱算出 K   =   Y b y   m o d   p K = Y_b^y mod p ,粉丝算出 K   =   Y a y   m o d   p K = Y_a^y mod p ,K就是二者共享的秘钥

image.png

公开参数 a、p、 Y a Y_a Y b Y_b
私有参数 x和y

2.2.6 DH交换算法 测试代码

github.com/kelvinylon/…

2.3 非对称加密

说完解决密钥配送问题第一种⽅案是DH 交换算法,我们再说说解决密钥配送问题第二种⽅案非对称加密。

2.3.1 非对称加密简介

⾮对称加密就是加密和解密的密钥不同的加密算法。

2.3.2 非对称加密原理

  1. 可以在不可信网络上将双方的公钥传给对方,然后在发消息前分别对消息使用对方的公钥来加密和使用⾃己的私钥来签名,做到不可信网络上的可靠密钥传播及加密通信。

  1. 由于私钥和公钥互相可解,因此⾮对称加密还可以应⽤于数字签名技术。

  1. 使⽤公钥对数据进行加密得到密文;使用私钥对数据进行解密得到原数据。

2.3.3 非对称加密手段

非对称加密手段常见的手段有RSA、DSA、ECC和 ECDHE。

2.3.3.1 RSA

首先,我们来说一下RSA算法

2.3.3.1.1 RSA 简介

1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了⼀种崭新构思, 可以在不直接传递密钥的情况下,完成解密。

这被称为"Diffie-Hellman密钥交换算法"。这个算法启发了其他科学家。⼈们认识到,加密和解密可以使⽤不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。

这种新的加密模式被称为"⾮对称加密算法"。

2.3.3.1.2 RSA 历史

1977 年,三位数学家 Rivest、Shamir 和 Adleman 在 DH 算法的启发下,设计了⼀种⾮对称加密算法,命名为 RSA 算法。

2.3.3.1.3 RSA 现状

RSA 算法是使⽤最为⼴泛的⾮对称加密算法,可以说,有计算机⽹络的地⽅,就有 RSA 算法。

2.3.3.1.4 RSA 理论基础

涉及到互质关系、欧拉函数、欧拉定理、模反元素等数学知识。具体可以参考阮⼀峰的 RSA 算法原理

2.3.3.1.5 RSA 算法过程
2.3.3.1.5.1 加密

密文 = E   m o d   N 明文^E mod N ,公钥为(E,N)

2.3.3.1.5.2 解密

明文 = D   m o d   N 密文^D mod N ,公钥为(D,N)

2.3.3.1.5.3 公私钥的计算过程
  1. 随机选择两个不相等的质数 p & q

  2. 计算 N = p* q

  3. φ ( N )   =   ( p 1 ) ( q 1 ) \varphi(N) = (p -1)(q -1)

  4. 随机选择E,满足 1 < E < φ ( N )  且  g c d ( E , φ ( N ) )   =   1 1 < E <\varphi(N) 且 gcd(E,\varphi(N)) = 1

  5. 计算出D, 满足 1 <   D < φ ( N )  且  E     D     m o d   φ ( N ) =   1 1 < D <\varphi(N) 且 E * D * mod \varphi(N)= 1

  6. 公钥为(E,N),私钥为(D,N)

2.3.3.1.6 RSA 代码实现

github.com/ForTheDevel…

2.3.3.2 DSA

然后,我们来说一下DSA数字签名

2.3.3.2.1 DSA 简介

DSA数字签名可以理解为是单向加密的升级,不仅校验数据完整性,还校验发送者身份,同时还由于使用了非对称的密钥来保证密钥的安全,所以相比消息Hash算法更安全。

2.3.3.2.2 DSA 历史

DSA是美国NIST作为DSS(DigitalSignature Standard) 数字签名的标准。

2.3.3.2.3 DSA 现状

DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,DSA比RSA要快很多。

2.3.3.2.4 DSA 理论基础

DSA是一种更高级的验证方式,DSA是一种公开密钥算法,不能用来加密数据,一般用于数字签名和认证。

DSA 不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。

在DSA数字签名和认证中,发送者使用自己的私钥对文件或消息进行签名,接受者收到消息后使用发送者的公钥来验证签名的真实性,包括数据的完整性以及数据发送者的身份。

如果数据和签名不匹配则认为验证失败!DSA数字签名的作用就是校验数据在传输过程中不被修改。

2.3.3.2.5 DSA 签名过程
  1. 使用消息Hash算法将要发送数据加密生成信息摘要。
  2. 发送方用自己的DSA私钥对信息摘要再加密,形成数字签名。
  3. 将原报文和加密后的数字签名一并通过互联网传给接收方。
  4. 接收方用发送方的公钥对数字签名进行解密,同时对收到的数据用消息Hash算法产生同一信息摘要。
  5. 将解密后的信息摘要和收到的数据在接收方重新加密产生的摘要进行比对校验,如果两者一致,则说明在传送过程中信息没有破坏和篡改;否则,则说明信息已经失去安全性和保密性。

2.3.3.2.6 DSA 代码实现

github.com/ForTheDevel…

2.3.3.3 ECC

其次,我们来说一下ECC算法

2.3.3.3.1 ECC简介

ECC是 Elliptic Curves Cryptography 的缩写,意为椭圆曲线密码编码学。和RSA算法一样,ECC算法也属于公开密钥算法。

2.3.3.3.2 ECC历史

1985年, Koblitz 和 Miller 提出ECC算法,ECC算法的数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性

2.3.3.3.3 ECC现状

因为在安全性、加解密性能、网络消耗方面有较大优势,ECC加密算法大有取代RSA成为下一代主流加密算法的趋势。如今ECC应用范围很广,在TLS、区块链(比特币、以太坊等等)、SM2国密算法、证书、银行政府机构等许多方面都有大量应用。

A: 更适合于移动互联网

ECC加密算法的密钥长度很短(256位),意味着占用更少的存储空间,更低的CPU开销和占用更少的带宽。

目前手机已经越来越普及,随着越来越多的用户使用移动设备来完成各种网上活动,ECC加密算法为移动互联网安全提供更好的客户体验。

B: 更好的安全性

ECC加密算法提供更强的保护,比目前的其他加密算法能更好的防止攻击,使你的网站和基础设施比用传统的加密方法更安全,为移动互联网安全提供更好的保障。

C: 更好的性能

ECC加密算法。密钥短,所以相应的计算量、消耗的内存和带宽也就少。可以用较短的密钥长度来提供更好的安全

例如,256 位的 ECC密钥加密强度等同于 3072 位 RSA 密钥的水平(目前普通使用的 RSA 密钥长度是 2048 位)。其结果是你以更低的计算能力代价得到了更高的安全性。

经国外有关权威机构测试,在 Apache 和 IIS 服务器采用 ECC算法,Web服务器响应时间比 RSA 快十几倍。

D: 更大的IT投资回报

ECC可帮助保护您的基础设施的投资,提供更高的安全性,并快速处理爆炸增长的移动设备的安全连接。

ECC的密钥长度增加速度比其他的加密方法都慢(一般按 128 位增长,而 RSA则是倍数增长,如:1024 – 2048 - 4096),将延长您现有硬件的使用寿命,让您的投资带来更大的回报。

ECC算法的可以用较少的计算能力提供比RSA加密算法更高的安全强度,有效地解决了“提高安全强度必须增加密钥长度”的工程实现问题。

2.3.3.3.4 ECC理论基础

描述一条Fp上的椭圆曲线,常用到六个参量:T=(p,a,b,n,x,y)。

(p 、a 、b) 用来确定一条椭圆曲线;

p为素数域内点的个数;

a和b是其内的两个大数;

x,y 为G基点的坐标,也是两个大数;

n 为点G基点的阶;

以上六个量就可以描述一条椭圆曲线,有时候我们还会用到h(椭圆曲线上所有点的个数p与n相除的整数部分)。

2.3.3.3.5 ECC算法过程

  1. 选定一条椭圆曲线 Ep(a,b) 并取椭圆曲线上一点,作为基点P。
  2. 选择一个大数k作为私钥,并生成公钥 Q=kP。
  3. 将 Ep(a,b) 和点Q、P传给用户。
  4. 用户接到信息后 ,将待传输的明文编码到Ep(a,b)上的一点M,并产生一个随机整数r。
  5. 公钥加密(密文C是一个点对):C={rP, M+rQ}
  6. 私钥解密(M + rQ - k(rP) ,解密结果就是点M,公式如下:

M + rQ - k(rP) = M + r(kP) - k(rP) = M

  1. 对点M进行解码就可以得到明文假设在加密过程中,有一个第三者H,H只能知道椭圆曲线 Ep(a,b)、公钥Q、基点P、密文点C,而通过公钥Q、基点P求私钥k或者通过密文点C、基点P求随机数r都是非常困难的,因此得以保证数据传输的安全。
2.3.3.3.6 ECC代码实现

github.com/ForTheDevel…

2.3.3.4 ECDHE

最后,我们来说一下ECDHE算法

2.3.3.4.1 ECDHE 简介

HTTPS 常用的密钥交换算法有两种,分别是 RSA 和 ECDHE 算法。

ECDHE全称是椭圆曲线迪菲-赫尔曼秘钥交换(Elliptic Curve Diffie–Hellman key Exchange),主要是用来在一个不安全的通道中建立起安全的共有加密资料,一般来说交换的都是私钥,这个密钥一般作为“对称加密”的密钥而被双方在后续数据传输中使用。

2.3.3.4.2 ECDHE 历史

ECDHE 密钥协商算法是 DH 算法演进过来的,学好ECDHE 密钥协商算法前必须学好 DH 算法,上文我们说了 DH 算法,DH 算法是非对称加密算法, 用于密钥交换,而ECDHE 密钥协商算法的核心数学思想是离散对数

2.3.3.4.3 ECDHE 现状

当多个参与方共享同一个链路的时候,联盟链各参与方想要在同一个链路上实现通性的隔离,使用ECDHE算法既可以实现TCP链接的复用,避免频繁建立大量链接,又可以保证同一链接间的通信隔离。

2.3.3.4.4 ECDSA 签名算法

Alice想要用私钥签名一个数据,Bob想要使用Alice的公钥验证这个签名;只有Alice能够进行计算签名然后得到签名,每个人都能验证签名值。

首先,Alice和Bob拥有相同的椭圆曲线参数,算法被签名称之为ECDSA,是DSA算法的一个变体。

然后,ECDSA签名算法的输入是数据的hash值,而不是数据的本身,hash算法可自选且hash值会被截断。

最后,Alice使用私钥da对z进行签名,生成二元组(r, s)。Bob使用Alice的公钥对(r, s)和Z进行验证。

Bob的验证过程为:

  • 计算u1 = s^-1 * z mod n

  • 计算u2 = s^-1 * r mod n

  • 计算P = u1G + u2Ha

  • 如果r == xp mod n,则验证正确

需要注意的是:

当我们使用ECDSA进行签名的时候,k的保密性非常重要。如果我们对所有的签名操作都用一样的k或者我们的随机数生成器存在可预测性,一个攻击者可能会猜出私钥。

2.3.3.4.5 ECDHE 算法过程

首先,双方约定使用ECDHE秘钥交换算法,这个时候双方也知道了ECDHE算法里的一个大素数P,这个P可以看做是一个算法中的常量。

P的位数决定了攻击者破解的难度

还有一个整数g用来辅助整个秘钥交换,g不用很大,一般是2或者5,双方知道gp之后就开始了ECDHE交换秘钥的过程了。


Alice知道了共用参数pg,生成私有整数a作为私钥,公钥算法一般是公钥加密,私钥解密,公钥给对方来加密数据,拿到密文后私钥解密查看内容正确性,这个时候Alice直接通过线路告诉Bob自己的私钥a显然既不合理也是一件风险很大的事。


这个时候Alice需要利用pga通过公式g^a mod p = A生成A作为公钥传递。


Bob通过链路收到Alice发来的pgA,知道了Alice的公钥A。这个时候Bob也生成自己的私钥b,然后通过公式g^b mod p = B生成自己公钥B


在发送公钥B前,Bob通过A^b mod p = K生成K作为公共秘钥,但是并不发送给Alice,只通过链路发送B


Alice收到Bob发来的公钥B以后,同样通过B^a mod p = K生成公共秘钥K,这样Alice和Bob就通过不传递私钥ab完成了对公共秘钥K的协商。

2.3.3.4.6 ECDHE 代码实现

github.com/akhawaja/ja…

2.3.4 非对称加密过程

我们还是从小木箱和粉丝来看⼀下这个过程。

  1. ⾸先,粉丝⽣成两个密钥,公钥 B 和私钥 B。公钥 B 是可以公开的,私钥 B 是⾃⼰保管。
  2. 然后, 粉丝把 公钥 B 发送给 小木箱,小木箱将明⽂通过公钥 B 来加密成密⽂,发送给粉丝。
  3. 接着, 粉丝通过私钥 B 解密密⽂,得到明⽂。
  4. 这个过程中,黑粉即便截获了公钥 B 和密⽂,也⽆法解密。

image.png

2.3.5 非对称加密优缺点

非对称加密的优点是什么?

可以在不安全⽹络上传输密钥,可以解决“密钥交换”的问题。网站秘密保管私钥,在网上任意分发公钥,你想要登录网站只要用公钥加密就行了,密文只能由私钥持有者才能解密。

为什么不直接使用非对称加密?

非对称加密由于使用了复杂了数学原理,因此计算相当复杂,如果完全使用⾮对称加密来加密通信内容,会严重影响⽹络通信的性能。非对称加密的缺点是计算复杂,因此性能相⽐对称加密差很多。

2.3.6 非对称加密破解

和对称加密不同之处在于,⾮对称加密的公钥很容易获得,因此制造原文-密文对是没有困难的事。

⾮对称加密的关键只在于,如何找到⼀个正确的私钥,可以解密所有经过公钥加密过的密⽂文。找到这样的私钥即为成功破解。

⾮对称加密的自身特性,怎样通过公钥来推断出私钥通常是一种思路(例如 RSA),但往最佳手段依然是穷举法。

只是和对称加密破解的区别在于,对称加密破解是不断尝试自己的新密钥是否可以将⾃⼰拿到的原文-密文对进行加密和解密,而非对称加密时不断尝试自己的新私钥是否和公钥互相可解。

2.3.7 非对称加密反破解

⾮对称加密算法优秀的标准同样在于,让破解者找不到⽐穷举法更有效的破解手段,并且穷举法的破解时间足够长。

2.4 混合加密

说完非对称加密,我们再聊聊混合加密

2.4.1 混合加密简介

混合加密是结合对称加密非对称加密各自优点的一种加密方式。

混合加密具体的实现思路是首先使用对称加密算法对数据进行加密,然后使用非对称加密算法对 对称加密的密钥进行非对称加密,最后再把加密后的密钥和加密后的数据发送给接收方。

2.4.2 混合加密过程

在对数据安全要求较高的场景或传输敏感数据时,我们就可以考虑利用前面的混合加密方案对提交到服务端的数据进行混合加密,当服务端接收到对应的加密数据时,再使用对应的解密算法对加密的数据进行解密,从而进一步进行数据处理。

但是如果服务端也要返回敏感数据时,应该怎么办呢?可以参考下面的混合加密技术方案

2.4.3 混合加密技术方案

① 生成一个唯一的 reqId(请求 ID),用于标识当前请求;

② 分别生成一个随机的 AES Key 和 AES IV(采用 AES CBC 模式);

③ 采用 RSA 非对称加密算法,分别对 AES Key 和 AES IV 进行 RSA 非对称加密;

④ 采用随机生成的 AES Key 和 AES IV 对敏感数据进行 AES 对称加密;

⑤ 把 reqId 作为 key,AES Key 和 AES IV 组成的对象作为 value 保存到 Map 或 {} 对象中;

⑥ 把 reqId、加密后的 AES Key、AES IV 和加密后的数据保存到对象中提交到服务端;

⑦ 当服务端接收到数据后,对接收的数据进行解密,然后使用客户端传过来的解密后的 AES Key 和 AES IV 对响应数据进行 AES 对称加密;

⑧ 服务端在完成数据加密后,把 reqId 和加密后的数据包装成响应对象,返回给客户端;

⑨ 当客户端成功接收服务端的响应后,先获取 reqId,进而从保存 AES Key 和 IV 的 Map 获取该 reqId 对应的 AES 加密信息;

⑩ 客户端使用当前 reqId 对应的加密信息,对服务端返回的数据进行解密,当完成解密之后,从 Map 或 {} 对象中删除已有记录。

我们来对上述流程做个简单分析,首先 AES 加密信息都是随机生成的且根据每个请求独立地保存到内存中,把 AES 加密信息中的 Key 和 IV 提交到服务端的时候都会使用 RSA 非对称加密算法进行加密。

在服务端返回数据的时候,会使用当前请求对应的 AES 加密信息对返回的结果进行加密,同时返回当前请求对应的 reqId(请求 ID)。即服务端不需要再生成新的 AES 加密信息,来对响应数据进行加密,这样就不需要在响应对象中传递 AES 加密信息。

2.4.4 混合加密代码实现

github.com/Ccapton/and…

三、Hash算法

说完混合加密,我们说说Hash算法,Hash算法又叫摘要算法

3.1 Hash算法概念

Hash算法本质数据结构是散列函数、Hash函数,Hash算法用来实现完整性,能够为数据生成独一无二的“指纹”,因为不可逆性, Hash算法不是加密算法,不能用于加密(因为无法通过Hash反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令

3.2 Hash算法作用

Hash算法的作用有三个,第一个是防止直接看到明文,比如TLS安全通信防中间人攻击,第二个是防抵赖(数字签名),第三个是大文件比较。下面我们着重讲解防中间人攻击流程

3.3 防中间人攻击流程

小木箱和粉丝解决了密钥配送问题,这下可以秘密通信了吧?没那么容易,黑粉通过⾃⼰的聪明才智,想到了⼀个劫持+篡改的⽅案,再次攻破了 DH 密钥交换和⾮对称加密。这个就是⼤名⿍⿍的中间⼈攻击。

中间⼈攻击,反应了加密世界中的两⼤问题:篡改和伪装。这个难题如何解决呢?

3.3.1 单向散列

3.3.1.1 Hash简介

⾸先介绍我们的第⼀个武器:单向散列,简称Hash

单向散列函数也叫Hash函数、摘要函数、杂凑函数等,是单向的把任意⻓的输⼊消息串变化成固定⻓的⼀种函数。

单向散列函数可以把任意数据转换成指定大小范围(通常很小,例如 256 字节以内)的数据。

3.3.1.2 Hash特点

  1. 第⼀个是输⼊不定⻓,输出定⻓。

  2. 抗碰撞性。

    1. 2.1 弱碰撞性:找到和给定消息散列值相同的另外⼀条消息难。
    2. 2.2 强碰撞性:找到给定散列值的两条消息难。
  3. 单向性,⽆法通过输出反向计算出输⼊。

  4. 计算快速。

3.3.1.3 Hash算法

  1. MD5 算法。已经被攻破,不再推荐使⽤。

    1. github.com/ForTheDevel…
  2. CRC32 算法。在数据压缩领域被作为完整性校验

    1. github.com/MasGaNo/cor…
  3. SHA1 算法。已经被攻破,不再推荐使⽤。

    1. github.com/xiebiao/Sha…
  4. SHA2 算法。包括常⻅的 SHA256、SHA512 算法等。

    1. github.com/meyfa/java-…
  5. SHA3 算法。是 NIST 选拔的算法,推荐使⽤。

    1. github.com/ForTheDevel…
  6. MAC 算法。 MD5 和 SHA 结晶,安全程度高。 商业银行中POS 终端加密常用算法。

    1. github.com/ForTheDevel…

3.3.1.4 Hash作用

Hash相当于从数据中提出摘要信息,因此最主要⽤途是数字指纹。

3.3.1.5 Hash常见问题

Hash是编码吗?

不是,Hash 是单向过程,往往是不可逆的,⽆法进行逆向恢复操作,因此 Hash 不属于编码。

Hash是加密吗?

不是,Hash 是单向过程,⽆法进行逆向回复操作,因此 Hash 不属于加密。(记住,MD5 不是加密)

3.3.1.6 Hash用途

Hash实际用途有四个,第一个是唯一性验证,第二个是数据完整性验证,第三个是快速查找,最后一个是隐私保护

  1. 唯⼀性验证

    1. 例如 Java 中的 hashCode() ⽅法。
    2. 把 equals() ⽅法中的每个用于判断相等的变量都放进 hashCode() 中,一起生成一个尽量量不会碰撞的整数即可
  2. 数据完整性验证

    1. 从⽹络上下载文件后,通过比对文件的 Hash 值(例如 MD5、SHA1),可以确认下载的文件是否有损坏。如果下载的⽂件 Hash 值和文件提供方给出的 Hash 值一致,则证明下载的⽂文件是完好⽆损的。
  3. 快速查找

    1. HashMap
  4. 隐私保护

    1. 当重要数据必须暴露的时候,有事可以选择暴露它的 Hash 值(例如 MD5),以保障原数据的安全。
    2. 例如⽹站登录时,可以只保存用户密码的 Hash 值,在每次登录验证时只需要将输⼊的密码的 Hash值和数据库中保存的 Hash 值作比对就好,网站⽆需知道用户的密码。
    3. 这样,当⽹站数据失窃时,⽤户不会因为⾃己的密码被盗导致其他网站的安全也受到威胁。

说完了单向散列,我们会发现,篡改和伪装的问题都没有完全解决。这个难题如何优化呢?

3.3.2 消息验证码

3.3.2.1 MAC简介

在单向散列算法中引⼊⼀个共享秘钥,这样散列+加密的结果就是我们的消息验证码。

3.3.2.2 MAC作⽤

由于消息验证码只有拥有共享密钥的⼈才能算出。这样就解决了伪装和篡改的问题。

3.3.2.3 MAC使⽤

如果初始消息是很长的句子,那么初始消息被篡改后意思会变得很奇怪,所以接收者有可能会发现初始消息是被篡改过的。

但是,如果初始消息就是商品编号等无法被人们直接理解的内容,那么解密后接收者便很难判断初始消息是否被篡改。由于密码本身无法告诉人们消息是否被篡改,所以就需要使用消息认证码来检测初始消息是否真伪。也就是我们说的MAC

3.3.2.4 HMAC算法

HMAC 是Keyed-Hashing for Message Authentication的缩写。HMAC的MAC算法是hash

算法,它可以是MD5, SHA-1或者 SHA-256,他们分别被称为HMAC-MD5,HMAC-SHA1, HMAC-SHA256。

消息验证码在⼀定程度上解决了篡改和伪装的问题。那么如何进一步优化呢?

3.3.3 数字签名

3.3.3.1 数字签名简介

消息验证码是在单向散列的基础上引⼊了⼀个共享秘钥,数字签名则是在单向散列的基础上引⼊了⼀对公私钥

3.3.3.2 数字签名使用

如果想要将数据更小,我们通常会对原数据 hash 对 hash 签名,然后附加在原数据的后⾯面作为签名。这就是数据签名,详细流程可以参考下面的流程

3.3.3.3 数字签名优点

对⽐消息验证码,数字签名可以额外解决“⽆法向第三⽅证明” 和 “否认” 两个问题。

3.3.3.4 数字签名原理

数字签名技术是利用算法(一般是非对称算法)通过Hash(仅个人所有)加密,生成数字签名,与原文一起传送给接收者。

接收者只有用发送者的公钥才能解密被加密的信息,然后对内容执行Hash运算得到Hash值,与解密得到的数字签名Hash值比对。

如果比对结果一致,则说明收到的信息是完整的,在传输过程中没有被篡修改的,否则信息一定被修改过

3.3.3.5 与⾮对称加密的关系

数字签名也是⾮对称加密算法的应⽤,对⽅⽤公钥加密,我⽤私钥解密,就是⾮对称加密在消息传递上的应⽤。我⽤私钥加密,对⽅⽤公钥解密,就是数字签名。

数字签名还是要有⼀对公私钥,所以还是存在中间⼈攻击的问题的。那么我们该如何治理这个问题呢?

3.3.4 数字证书

我们引⼊了数字证书来解决中间⼈攻击的问题。

3.3.4.1 CA简介

数字证书,涉及到⼀个第三⽅的公正机构,Certificate Authority,也就是 CA。公钥的分发需要使用数字证书,必须由 CA 的信任链来验证,否则就是不可信的;

3.3.4.2 CA工作流程

服务器向CA中心申请证书,CA负责核实服务器的真实性,并在证书里内置服务器域名证书使用者信息客户浏览器或操作系统里内置有权威CA的公钥信息(即CA公钥不需要在网络中传输)

客户请求服务时,服务器把自己申请的数字证书和内容的数字签名一同发给客户

客户收到信息后在本地CA列表里查找CA公钥对数字证书解密,拿到真正的签名公钥,再用该公钥去解密数字签名,拿到HASH值去对比完整性

3.3.4.3 CA验证过程

  • 检验基本信息

    • 首先,浏览器读取证书中的证书所有者、有效期等信息进行一一校验
  • 校验CA机构

    • 然后,浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发;如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
  • 解密证书

    • 如果找到,那么浏览器就会从操作系统中取出颁发者CA的公钥,然后对服务器发来的证书里面的签名进行解密
  • 比对hash值

    • 其次,浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比

最后,对比结果一致,则证明服务器发来的证书合法,没有被冒充,浏览器可以读取证书中的公钥,用于后续加密

好了,利⽤上⾯这些武器,小木箱和粉丝终于可以联系和信任了。

3.4 Hash算法风险

Hash算法的风险在于碰撞,伪造证书攻击, 作为信任链的源头 CA 有时也会不可信,解决办法有 CRL、OCSP,还有终止信任,可能两个不同的数据通过某个Hash算法得到了相同的摘要

四、数据编解码

说完Hash算法,我们再聊聊数据编解码,根据5W2H分析法,我们将从编解码价值、编解码原因、编解码时机和编解码形式和使用五个维度讲解数据编解码

4.1 编解码简介

编码是信息从一种形式转换为另一种形式的过程。不同字符对应的二进制数的规则。

解码是编码的逆过程,解码将存储在计算机的二进制转换为可以看到的字符。

4.2 编解码价值

数据编解码是可逆的,数据编解码核心价值有两个。第一个是保证数据的准确性,一定程度上防止数据传输过程中被任意改造。第二个是为了方便数据存储和压缩。

4.3 编解码原因

未压缩的数据量非常大,存储困难,同时也不便于在网络中传输。

因此,数据编解码的最主要作用是将非标准格式的数据转为某种协议的标准格式,使这种协议可以传输、处理这种数据。

4.4 编解码时机

当我们在存储和传输数据的过程中,如果不改变数据空间结构加密数据,或不隐藏数据空间结构解密,那么我们可以考虑对数据进行编解码。数据加解密和数据编解码本质区别是数据加解密是对数据隐藏和保护,数据编解码是方便存储和传输数据。

4.5 编解码形式和使用

数据编解码有四种形式,第一种形式是Base64编解码,第二种形式是Hex编解码,第三种形式是URL编解码,第四种形式是压缩与解压。

4.5.1 Base64编解码

首先我们说说第一种形式Base64编解码

4.5.1.1 Base64定义

Base64是将⼆进制数据转换成由 64 个字符组成的字符串的编码算法

4.5.1.2 Base64用途

Base64将⼆进制数据扩充了储存和传输途径(例如可以把数据保存到⽂本文件、可以通过聊天对话框或短信形式发送⼆进制数据、可以在 URL 中加入简单的二进制数据)。

普通的字符串在经过Base64 编码后的结果会变得⾁眼不可读,因此可以适用于一定条件下的防偷窥(较少用)。

4.5.1.3 Base64缺点

因为⾃身的原理(6 位变 8 位),因此每次 Base64 编码之后,数据都会增大约 1/3,所以会影响存储和传输性能。

4.5.1.4 Base64问题

Base64加密图⽚传输更安全和高效?

Base64并不是加密, 另外,Base64 会导致数据增大 1/3,降低⽹网络性能,增⼤用户流量开销,是画蛇添⾜的手段。

Base64 对图⽚进行编码用处在于有时需要使用文本形式来传输图片。除此之外,完全没必要使用Base64对图片进行额外处理。

4.5.2 Hex编解码

然后我们说说第二种形式Hex编解码,

4.5.2.1 Hex编解码定义

Hex编码(十六进制编码)就是使用数字0到9加上字母A到F一共16个字符表示的一种编码解码方式,其中A到F相当于十进制的10到15,总计16个,这些称作十六进制数字。

常见的编解码方式如下:

# abc这3个英文字符会被echo编码为3个字节,然后被xxd编码为6个hex字符
$ echo -n abc|xxd -ps
616263 
# 解码hex数据
$ echo 616263|xxd -ps -r
abc
复制代码

4.5.2.2 Hex编解码用途

Hex编码最常用于二进制文件查看时展示的编码,如Hex Fiend就可以支持查看二进制文件。

4.5.2.3 Hex编解码场景

在XML、JSON等文本中包含不可见数据(二进制数据)时使用

4.5.2.4 Hex编解码代码

4.5.2.4.1 将字节数组转换为字符串
/**
       * 将字节数组转换为字符串
       * 一个字节会形成两个字符,最终长度是原始数据的2倍
       * @param data
       * @return
       */ 
      public static String toHex(byte[] data){
          String ret = null;
  
         //TODO 将字节数组转换为字符串
         if (data != null && data.length>0) {
             StringBuilder sb = new    StringBuilder();
             for (byte b: data){
                 //分别获取高四位,低四位的内容,将两个数值,转为字符15  
               int h = (b>>4)&0x0f;
                 int l = b&0x0f;
                 char ch ,cl;
                 if( h > 9 ){
                     ch = (char) ('A'+(h-10));
                 }else{  //0--9
                     ch = (char) ('0'+h);
                 }
 
                 if(l>9){
                     cl = (char) ('A'+(l-10));
}
              sb.append(ch).append(cl);
                 }
                   ret = sb.toString();
             }
 
         return ret;
     }
复制代码
4.5.2.4.2 将字符串转换为字节数组
  public static byte[] fromHex(String str) {
          byte[] ret = null;
  
          //TODO 将Hex编码的字符串,还原为 原始的字节数组 
         if (str != null) {
              int len = str.length();
              if (len > 0 && len % 2 == 0) {
                 char[] chs = str.toCharArray();
                  ret = new byte[len / 2];
                 for (int i = 0, j = 0; i < len; i += 2, j++) {
                     char ch = chs[i];                     char cl = chs[i + 1];
 
                     int ih = 0, il = 0, v = 0;          
                                if (ch >= 'A' && ch <= 'F') {
                         ih = 10 + (ch - 'A');               
                               } else if (ch >= 'a' && ch <= 'f') {
                         ih = 10 + (ch - 'a');

                     } else if (ch >= '0' && ch <= '9') {              
                                ih = ch - '0';
                    } 
                     if (cl >= 'A' && cl <= 'F') {                      
                        il = 10 + (cl - 'A');
                     } else if (cl >= 'a' && cl <= 'f') {
                         il = 10 + (cl - 'a');
                     } else if (cl >= '0' && cl <= '9') {
                         il = cl - '0';
                     } 
                     v = ((ih & 0x0f) << 4) | (il & 0x0f);
                     //赋值               
         ret[j] = (byte) v;
                 }             }
                 return ret;
     } 
复制代码

4.5.3 URL编解码

接着我们说说第三种形式URL编解码。

4.5.3.1 URL编解码定义

URI 是用来标记互联网上资源的一个名字,由“协议名 + 主机名 + 路径”构成,俗称URL 61e4f0a9-6af0-4832-83d4-a13a3a96d506.jpeg

4.5.3.2 URL编解码用途

Url的编码格式采用的是ASCII码,ASCII的用途就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。

4.5.3.3 URL编解码场景

  • Size过大
  • 包含隐私数据
  • URL字符有歧义

4.5.3.4 URL编解码问题

哪些字符需要编码?
  • 英文字母(a-zA-Z)
  • 数字(0-9)
  • -_.~4个特殊字符
  • 所有保留字符
如何对非法字符进行编码?
  • 对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到相应的字节,然后对每个字节执行百分号编码。

    • 如"中文"使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87"。

    • 如果某个字节对应着ASCII字符集中的某个非保留字符,则此字节无需使用百分号表示。

      • Url编码",使用UTF-8编码得到的字节是0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由于前三个字节对应着ASCII中的非保留字符"Url"
      • 因此这三个字节可以用非保留字符"Url"表示。最终的Url编码可以简化成"Url%E7%BC%96%E7%A0%81"
  • 对于Unicode字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。

4.5.4 压缩与解压

其次我们说说第四种压缩与解压。

4.5.4.1 压缩与解压定义

压缩是指将数据使用更具有存储优势的编码算法进⾏编码。而解压是指将压缩数据解码还原成原来的形式,以方便使用。

4.5.4.2 压缩与解压用途

压缩与解压⽬的是减小数据占用的存储空间。

4.5.4.3 压缩与解压问题

问题1: 压缩是编码吗?解压是解密过程吗?

是,所谓编码,即把数据从一种形式转换为另一种形式。压缩过程属于编码过程,解压缩过程属于解码过程。

问题2: 常见的压缩算法有哪些?

常见的压缩算法有五种,分别是 Gzip、Deflate、Brotli、JPEG和MP3

  1. Gzip

    • Gzip是GNU zip 压缩格式,也是互联网上最流行的压缩格式
  2. Deflate

    • zlib(deflate)压缩格式,流行程度仅次于gzip
  3. Brotli

    • Brotli是一种专门为 HTTP 优化的新压缩算法(Brotli)
  4. Jpeg

  5. MP3

问题3: 什么是图⽚、音频与视频编解码?

图⽚、音频和视频编解码是指将图像、音频、视频数据通过编码来转换成存档形式(编码),以及从存档形式转换回来(解码)。

问题4: 图⽚、音频与视频编解码有什么用?

图⽚、音频与视频编解码目的是存储和压缩媒体数据(⼤多数媒体编码算法会压缩数据,但不是全部)。

问题5: 什么是图⽚压缩粗暴算法?

图⽚压缩粗暴算法常见案例是将⼀张纯⽩(⽩⾊的 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]
复制代码

这就是图⽚压缩粗暴算法,通过字符集测量方式减少图片体积。

4.6 序列化和编解码比较

加解密算法快结束了,同学可能会将序列化和编解码混淆,下面就简单比较一下序列化和编解码简单的差异。

4.6.1 序列化定义

序列化是指把数据对象(⼀般是内存中的,例如 JVM 中的对象)转换成字节序列的过程。

对象在程序内存里的存放形式是散乱的(存放在不同的内存区域、并且由引用进行连接),通过序列化可以把内存中的对象转换成⼀个字节序列,从而使用 byte[] 等形式进行本地存储或网络传输,在需要的时候重新组装(反序列化)来使⽤。

4.6.2 序列化用途

序列化目的是让内存中的对象可以被储存和传输。

4.6.3 序列化和编解码区别

序列化不是编码,编码是把数据由一种数据格式转换成另一种数据格式,而序列化是把数据由内存中的对象(而不是某种具体的格式)转换成字节序列。

五、总结与展望

这一节,主要分为四部分,第一部分是加解密算法,第二部分是Hash算法, 第三部分是数据编解码,最后一部分是总结与展望。其中,加解密算法主要是分为四部分,第一部分是对称加密,第二部分是DH交换算法,第三部分是非对称加密,第四部分是混合加密。

熟悉密码学对于移动端开发者自定义数据格式、字符编解码和高性能日志库实现尤为重要,如果想成为一名不被时代遗弃的Android开发者,那么深层次了解的加解密并在合适的场景使用加解密,不仅能全方面构建全链路技术栈,而且在即将到来的Web3.0基础层技术奠定了良好基础。

下一节,小木箱将带大家从安卓签名机制、TLS握手协议、支付中台建设和日志安全等维度讲解密码学在移动端应用与实践。

我是小木箱,如果大家对我的文章感兴趣,那么欢迎关注小木箱的公众号小木箱成长营。小木箱成长营,一个专注移动端基础技术的互联网成长社区。

参考资料

猜你喜欢

转载自juejin.im/post/7192972910842085413
今日推荐