介绍伪随机数生成器、公钥密码、消息认证码、数字签名、密钥协商等密码技术的概念、应用、常见算法、攻击方法等,也会介绍些Android中可能使用的密码技术,后续会继续更新其他密码算法和攻击方式等。
消息直接明文传递是不安全的,可能会被窃听导致机密泄露,提高消息传递的安全性主要有两种方式,密码术和隐写术。
在计算机出现之前,密码学主要通过字符间的置换和代换实现信息加密。置换是把明文中的字母重新排列,字母本身不变,但其位置改变了;代换则是将明文中的字符替代成其他字符。
还有Vigenre多表代换密码、Scytale密码、轨道栅栏密码等算法,古典密码学中有些算法的密钥空间有限比如凯撒密码,对于这种算法可以直接采用暴力破解,穷举得到密钥;由于古典密码是基于字符,并且有些算法加密前后的字母是一一对应关系,对于这种算法可以采用频率分析法加快破译速度。
现代密码技术与古典密码的区别主要是由字符层加密转移到了字节层加密,安全性的保证也从保密算法转移到了保密密钥,主要包括以下技术:
加密密钥与解密密钥相同的密码技术,用于保证消息的机密性。
优点:通常所需密钥较小、效率高、速度快。
缺点:无法安全的将密钥送达到需要解密消息的人的手里。
又称为非对称密码,发送方使用公钥加密数据,接收方使用私钥解密数据,已知私钥可推导出公钥,但已知公钥不能推导出私钥。既可以用于保证消息的机密性,也可以用于认证。
过程:消息接收方提前生成一对公私钥,并将公钥广播出去,私钥自己保存,消息发送方获取被广播的公钥,使用公钥加密要传输的内容,加密后通过网络传输给接收方,接收方使用私钥解密。
优点:由于解密数据的私钥不需要在网络传输,降低了密钥泄露的风险,提高了安全性。
又称单向Hash函数、杂凑函数,输出的散列值称为消息摘要或者指纹。单向散列函数可以根据消息的内容计算出散列值,通过比对散列值就可以检查消息的完整性,散列值的长度固定与消息的内容无关,还具有弱抗碰撞性、强抗碰撞性、单向性的特点。
弱抗碰撞性:当给定某条消息的散列值时,单向散列函数必须确保要找到和该条消息具有相同散列值的另外一条消息是非常困难的。
强抗碰撞性:找到散列值相同的两条不同的消息是非常困难的。
单向性:无法通过散列值反算出消息。
应用:检查下载的软件是否被篡改(下载软件后计算散列值,跟官网网站公布的软件散列值对比)、基于口令的加密PBE、消息认证码、数字签名、伪随机数生成器、一次性口令。
攻击方法:暴力破解、生日攻击
一种能够模拟产生随机数列的算法,用于密钥生成,如果生成随机数算法不好,则密钥可能会被推测出带来风险。生成一个真正意义上的“随机数”对于计算机来说是不可能的,伪随机数也只是尽可能地接近其应具有的随机性。
内部状态:需要生成伪随机数时,伪随机数生成器根据内存中的数值(内部状态)进行计算得到伪随机数,生成后改变内部状态,为下一次伪随机数生成做准备,因此内部状态决定了下一个伪随机数的数值。
种子:一串随机比特数列,用于对伪随机数生成器内部状态进行初始化,因此根据种子就可以生成自己专属的随机数列。伪随机数生成器通常都是公开,种子需要自己保密,保密的种子让生成的伪随机数更难以预测。
与单向散列函数类似,发送方根据任意长度的消息生成MAC值,生成后将消息与MAC值一起发送给接收方,接收方接收后计算MAC与发送方发送的MAC比对,确定消息的完整性,但是不同之处在于消息认证码的发送方与接收方使用了共享密钥进行消息加密,而单向散列函数不需要密钥。由于MAC值是根据共享的密钥生成的,发送方与接收方的密钥不同则MAC值不会相同,所以比对MAC值也可以对发送方的身份进行认证。
攻击方法:暴力破解、生日攻击、共享密钥推测、重放攻击
无法解决的问题:对第三方证明、防止否认
否认:由于发送方和接收方共享了密钥,都可以生成消息正确的MAC值,对于第三方来说,无法确认消息究竟是由发送方还是接收方生成,因此发送方在可能会在发送生成的消息之后进行否认,第三方无法鉴别。
是一种相当于现实世界中的盖章、签字的功能在计算机世界中进行实现的技术,与消息认证码很相似,最大的不同在于数字签名的发送方与接收方各自使用不同的密钥,除了和消息认证码一样可以防篡改、认证外还可以防止否认。
签名者先将明文通过单向散列函数加密得到摘要,摘要通过私钥加密得到签名,将签名与明文传送,验证者接收后,使用公钥解密得到签名者的摘要,再通过单向散列函数计算得到摘要,两个摘要作对比。私钥为签名者所拥有,但公钥是对外公开的,因为任何人都可以成为验证者对签名进行验证。
防止否认:因为签名者和验证者使用了不同密钥,消息的签名一定使用了签名者的私钥才可以生成,接收方不可以生成正确消息的签名,因为签名者无法对消息进行否认。
应用:网站安全信息公告、下载的软件防篡改、公钥证书、SSL/TLS等。
攻击方法:中间人攻击、对使用的单向散列函数强抗碰撞性攻击、潜在伪造、对使用的签名算法针对性攻击。
无法解决的问题:公钥验证。因为验证者需要使用公钥对签名进行验证,但是数字签名本身无法确保公钥来自真正的发送者,因此可以使用证书,证书要由可信任的机构颁发,验证者通过证书链验证证书的合法、有效性来完成对公钥的验证。
数字签名需要用公钥来确认发送者的身份,但是无法确认公钥是确实来自真正的发送者的未被篡改的公钥,而公钥证书可以帮助验证公钥。
举例A向B发送密文场景说明下证书大致使用方式:首先B创建密钥对,将自己的个人信息以及公钥发送到认证机构C,认证机C构验证信息后对B的公钥加上数字签名形成证书(数字签名生成需要认证机构C自身的私钥),A从认证机构C处获取证书并验证证书合法性,验证通过后解析得到了B的公钥,A将要发送的消息通过B的公钥加密后发送给B,B接收后通过自己的私钥解密,完成通信。
X.509:证书是由不同认证机构颁发的,为了方便验证需要证书有特定的格式,于是人们制定了证书的标准规范,而X.509就是一套使用最广泛的证书标准,HTTPS协议依赖的SSL证书使用的就是这种格式,它是由国际电信联盟(ITU)和国际标准化组织(ISO)制定,发布后经过两次修订,目前版本是X.509V3。
CRL:证书作废清单,当用户的私钥丢失、被盗时,认证机构需要对证书进行作废,CRL是认证机构宣布作废的证书一览表,用户需要从认证机构获取最新的CRL并查询自己要用于验证签名的公钥证书是否已作废,一般来说,需要要由证书处理软件及时更新CRL。
证书链:除自签名证书外,大多数申请的证书是层级结构的,从下到上依次为"用户证书--中间证书--根证书",证书验证时也会沿着这个证书链依次验证。
密码算法可以分组密码与流密码两类。流密码是对数据流进行连续处理,处理过程需要保持内部状态的一类算法;分组密码是每次只能处理特定长度数据的一类算法,比如DES、3DES、AES。
因为分组密码只能处理固定长度的数据,当需要加密的数据超过分组长度时,就需要对算法进行迭代来将数据全部加密,迭代的方法就称为分组密码的模式,常见模式:
对称加密的加密速度快但无法无法抵御中间人攻击,非对称加密可以解决密钥配送问题但加密效率低,可以将对称加密和非对称加密结合起来组成混合密码系统,同时拥有两种加密方式的优势,比如SSL就是这样的混合密码系统。
加密流程:
解密流程:
即使在有攻击者在偷窥客户端与服务器的网络传输的情况下,客户端依然可以利用“密钥协商机制”与服务器端协商出一个只有二者可知的,用来数据加密的会话密钥。
1977年美国联邦信息处理标准中使用的一种对称加密算法,一直以来被很多国家的政府和银行等广泛使用。随着计算机算力的提高,如今DES已经能被暴力破解,强度大不如前,如今AES已经正式替代了DES。
密钥:8字节64位,每隔7位有一位用于错误检查,所以有效密钥为56位。
结构:16轮循环的Feistel网络。
攻击方法:暴力破解、差分分析攻击(改变一部分明文分析密文产生的改变)、线性攻击(将明文和密文一些对应位进行XOR计算结果位零的概率)。
因为DES已经能够被破解,为了增加强度,将DES重复三次得到的一种对称加密算法。但是由于处理速度不高,实际使用并不多。
一种对称加密算法,1997年NIST公开募集AES用于替代原先的DES,经过五年的甄选,最终比利时密码学家JoanDaemen和VincentRijmen设计的Rijdael算法力压群雄,被选定为AES标准,目前还没有针对AES的低复杂度有效的攻击算法。
密钥:128、192、256位三种。
分组:固定为128位。
结构:多轮SPN结构,每轮分为字节代换(SubByte)、行移位(ShiftRow)、列混合(MixColumn)、轮密钥加(AddRoundKey)步骤。
攻击方法:边信道攻击(利用测量物理数据的方式推测出可能的密钥)。
RSA是在1977年由麻省理工学院的RonRivest、AdiShamir、LeonardAdleman三人一起提出的公钥算法,利用了大整数因子分解的困难性,算法密钥越长越难破解,目前被破解的最长RSA密钥是768位,一般认为,1024位的密钥基本安全,2048位的密钥极其安全。
公私钥生成流程:
攻击方法:暴力破解、中间人攻击、选择密文攻击。
椭圆加密算法是一种公钥算法,最初由Koblitz和Miller两人于1985年提出,基于椭圆曲线上离散对数计算问题,利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。
与RSA相比具有所需密钥长度短、加密速度快、破解难度高、抗攻击性更强的优点。ECDH是基于ECC和DH的密钥协商协议,ECDSA是基于ECC和DSA的数字签名算法。
攻击方法:Pohlig-Hellman攻击、PollardRho攻击、中间人攻击。
目前安卓锁屏解锁方式主要有数字密码、手势密码、人脸识别、虹膜识别、指纹等方式,其中数字密码、手势密码比较简单,也不需要借助硬件层实现,这里先只介绍这两种解锁方式用到的密码技术(基于Android5.1版本,目前正在阅读Android11.0源码,如果实现方式不同,后续再更新):
数字密码:首先取设备信息做盐值,数字密码加盐值组成加盐密码,加密值=MD5(加盐密码).toHex()+SHA
-1(加盐密码).toHex(),然后把加密值保存在数据库中(数据库文件为"/data/system/locksettings.db"),使用了MD5和SHA-1两种散列算法。
手势密码:将手势密码转为对应的字节数组,使用SHA-1散列算法加密后存储。
应用与服务器的请求如果直接使用HTTP是极不安全的,可能会被人直接看得到请求明文内容,也可能会被人冒充和篡改,因此应该使用HTTPS协议。