前言
- 本文梳理主要基于书籍《Java加密与解密的艺术》、维基百科、百度百科以及网络上众多资料,如有涉及版权问题,请联系我删除相关内容。
- 本篇内容主要梳理了基本的摘要算法、对称密码加密算法、密钥交换算法、非对称加密算法、数字签名算法等,我们日开发中涉及到加解密的一些解决方案都跟下文中提到的内容相关,尤其经常跟第三方系统交互的时候,比如下文提到的微信支付平台和蚂蚁开放平台上面接口的签名认证方案,理解了这些算法概念,对我们对接其它系统或自己设计接口的安全方案时都会有很大帮助,当然如果需要理解每一个算法的原理,数学公式、推理等更深层次的内容,建议去查看相关RFC文档或其它网络资料。
1.定义
密码学是研究编制密码和破译密码的技术科学。
2.历史
密码学的历史最早可以追溯到几千年以前,古今中外都有密码学运用的记载,从历史看,战争很大程度给密码学提供了应用环境,推动了密码学的发展,密码学按照发展历程,大体可以分为三个阶段,手工加密、机械加密和计算机加密阶段,下面是近代密码学的一些重要进展。
1949年,信息论始祖克劳德·艾尔伍德·香农(Claude Elwood Shannon)发表了《保密系统的通信理论》一文,把密码学建立在严格的数学基础之上,奠定理论基础,从此成为真正的科学。
1976年,密码学专家惠特菲尔德·迪菲(Bailey Whitfield Diffie)和马丁·赫尔曼(Martin Edward Hellman)两人发表了《密码学的新方向》一文,解决了密钥管理的难题,把密钥分为加密的公钥和解密的私钥,提出了密钥交换算法Diffie-Hellman。
1977年,美国国家标准技术研究所制定数据加密标准(Data Encryption Standard ),将其颁布为国家标准。
1977年,麻省理工学院的罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出RSA加密算法,RSA就是他们三人姓氏开头字母拼在一起组成的。
1997年4月,美国ANSI发起征集AES(advanced encryption standard)的活动,并为此成立了AES工作小组,经过几年的时间筛选,最终采用了由比利时的Joan Daemen和Vincent Rijmen设计的Rijndael算法,并在2002年5月26日成为有效的加密标准。
3.密码学分类
按密码体制划分:对称密码体制密码学和非对称密码体制密码学对应的有对称密码算法和非对称密码算法。
- 对称密码算法(Symmetric Cipher):单钥密码算法或私钥密码算法,常见的有DES、AES算法。
- 非对称密码算法(Asymmetric Ciper):又称双钥密码算法或公钥密码算法,常见的有RSA算法。
4.算法介绍
4.1消息摘要算法
4.1.1 简述
消息摘要算法又称散列算法,其核心在于散列函数的单向性,即通过散列函数可获得对应的散列值,但不可通过该散列值反推其原始信息,这是消息摘要算法的安全性的根本所在,我们通常使用该算法判断数据的完整性。
- 简单的说:A 通过摘要算法计算得到B, B不能反推出A,且不存在C摘要算法计算也得到B。
4.1.2 详细介绍
消息摘要算法我们常见比如MD(Message Digest)、SHA(Secure Hash Algorithm)、HMAC(Hash Message Authentication Code)等,常用于验证数据的完整性,是数字签名算法的核心算法。
- MD系列:MD2、MD4、MD5
- SHA系列:SHA-1、SHA-2系列算法(包含SHA-224、SHA-256、SHA-384和SHA-512)
- HMAC系列:MAC算法综合了上述两种算法,主要包括HmacMD5、HmacSHA1、HmacSHA256、HmacSHA384、HmacSHA512
常用消息摘要算法比较:
| 算法 | 摘要长度
| :-------: |:-------------:|
| MD2 | 128 |
| MD4 | 128 |
| MD5 | 128 |
| SHA-1 | 160 |
| SHA-224 | 224 |
| SHA-256 | 256 |
| SHA-384 | 384 |
| SHA-512 | 512 |
| HmacMD2 | 128 |
| HmacMD4 | 128 |
| HmacMD5 | 128 |
| HmacSHA-1 | 160 |
| HmacSHA-224 | 224 |
| HmacSHA-256 | 256 |
| HmacSHA-384 | 384 |
| HmacSHA-512 | 512 |
- MD系列算法长度是固定的128位,目前已经不安全,不建议使用在安全要求高的场景。
- MD、SHA系列算法可以通过加盐的方式提高安全性,比如MD5(message) 加盐后变成MD5(message+salt),至于salt可以是随机值,也可以是固定值,这样攻击者如果要根据摘要值反推原始值难度会大大加大。
- HMAC系列算法长度跟使用的摘要算法一样,比如HmacSHA-256 ,因为SHA-256的摘要长度是256,对应的HmacSHA-256摘要长度也是256,HMAC算法跟MD,SHA算法最大的差别增加了一个密钥,这里的密钥我理解是跟前面说的salt类似,只是HMAC把salt融入到算法里面,更加标准化和安全。
4.1.3 应用场景
我们以微信支付的接口调用分析一下摘要算法怎么应用的,首先可以打开微信支付如下相关文档:
微信支付统一下单接口文档
微信支付签名过程
-
微信支付统一下单接口请求参数有两个字段,签名值和签名类型,其中签名类型算法有HMAC-SHA256和MD5
- 生成签名值过程
- 首先按照一定的规则组装待计算摘要的数据stringA
- stringSignTemp=stringA+“&key=xxxxx”,这里其实就是加盐,把在微信支付平台设置的秘钥key作为salt
- 使用MD5加密MD5(stringSignTemp),或者使用hash_hmac("sha256",stringSignTemp,key),这里设置HMAC算法使用的key就是微信支付平台设置的key。
这样做的好处是怎么呢?我的理解大概有这么几点:
更安全:通过引入这样一个签名值,即使攻击者拿到了这个数据,它如果修改请求参数值,比如把金额修改,因为没有这个key,攻击者无法重新生成一个正确的摘要值,接收请求方计算摘要值比对后不匹配,直接拒绝请求就行了。
验证身份:因为涉及两个系统交互,怎样证明对方的身份?这里没有用户登录,没有token,而是依赖摘要值比对,摘要一致就可以确定是合法的,所以我们的key保护也很重要,不能泄露。
4.2 对称加密算法
4.2.1 简述
对称加密简单的说就是加密和解密使用同一个密钥,解密算法是加密算法的逆运算。
4.2.2 算法介绍
对称加密算法主要有DES、DES算法的变种DESede、DES替代者AES算法、IDEA、PBE等
- DES:1973年,美国国家标准局征求国家密码标准标准方案,IBM公司提交了自己的算法(Luciffer算法,1971年末提出),1977年7月15日,该算法被正式采纳,后面成为数据加密标准(Data Encryption Standard ,DES),但是DES算法秘钥偏短只有56位,且算法半公开,被怀疑存在美国安全局安置的后门,由于现在已经很容易破解DES算法,不推荐使用,但是作为对称加密算法中的经典算法,是值得去了解和学习的。
- DESede:DES算法的一种改良,针对DES算法的密钥长度偏短和迭代次数偏少等问题做了改进,密钥长度增至112位或168位,抗穷举法攻击的能力显著增强。
- AES:1997年,NIST发起了征集DES替代算法-AES(Advanced Encryption Standard,高级数据加密标准),经过多次筛选后,最终比利时人Joan Daemen和Vincent Rijmen设计的Rijndael算法被采用。
- IDEA:IDEA(International Data Encryption Algorithm,国际数据加密标准)算法是由旅居瑞士的中国青年学者来学嘉和著名密码专家James Massey于1990提出的一种对称分组密码,并于1992年修改完成,算法使用长度为128位的密钥,数据块大小为64位。
算法 | 密钥长度 | 密钥长度默认值 |
---|---|---|
DES | 56,64 | 56 |
DESede | 112、168、128、192 | 168 |
AES | 128、192、256 | 128 |
IDEA | 128 | 128 |
4.3 非对称加密算法
4.3.1 简述
非对称加密算法称为双钥或公钥加密算法,跟对称加密算法不同的是,对称加密算法只一个密钥,非对称加密算法 一个公钥和一个私钥,一个用于加密,另外一个用于解密。
简单的说:一对密钥公钥A和私钥B,A加密只能B解密,B加密只能A解密。
4.3.2 算法介绍
非对称加密算法源于DH算法(Diffie-Hellman,密钥交换算法)由W.Diffie和 M.Hellman共同提出,该算法为非对称加密算法奠定了基础,下面我们先来了解下密钥交换算法DH和ECDH算法。
为什么需要密钥交换算法?前面我们提到对称加密算法加解密都是用同一个密钥,我们可以想一下,我们怎样能安全的把一个密钥给到对方呢?比如我们经常用到HTTPS,大家都说HTTPS加密了是安全的,那它加密的密钥怎么来的呢?很显然我们在访问一个https地址的时候,事先并没有密钥,访问过程中客户端跟服务端通过握手协议协商出来的密钥,如果服务端直接把密钥在网络上传输那肯定不安全的,所以这过程到底发生了什么?后面专门分析https的时候会详细写,这里先了解下该算法。
DH密钥交换算法的安全性基于有限域上的离散对数难题
ECDH密钥交换算法是基于椭圆曲线加密
从上面图中可以看出,DH&ECDH密钥交换算法交互双方都会向对方公开一部分信息,即所谓的公钥,这部分即使被别人拿到了也不会威胁到最终的密钥,这里很关键的一点是甲乙两方公布的公钥是不相同的,但是最终生成的密钥两边是一致的,这里是利用的算法原理,有兴趣的可以去查阅详细的算法公式,因为最终的密钥不需要传输给对方,所以很大程度保证安全性。
非对称加密算法:
比较典型的非对称加密算法有RSA、ECC、ElGamal,RSA算法基于大数因子分解难题,而ElGamal和ECC算法则是基于离散对数难题。
- RSA:1977年,麻省理工学院的Ron Rivest、Adi Shamir、Leonard Adleman一起提出RSA加密算法,RSA就是他们三人姓氏开头字母拼在一起组成的。
- EIGamal:1985年,Taher EIGamal提出了一种基于离散对数问题的非对称加密算法,该算法即可用于加密,又可用于数字签名,美国数字签名标准(Digital Signature Standard ,DSS)就是采用了EIGamal签名方案的一种变形-DSA(Digital Signature Algorithm)。
- ECC:椭圆加密算法(ECC)是一种公钥加密体制,最初由Koblitz和Miller两人于1985年提出,其数学基础是利用椭圆曲线上的有理点构成Abel加法群上椭圆离散对数的计算困难性。
从上面消息传递模型我们可以看出,非对称加密算法遵循“私钥加密,公钥解密”和“公钥加密,私钥解密”的原则,但是有一点需要注意,公钥是公开的,所以用在什么场景是需要根据该算法的特征来考虑的,比如既然公钥是公开的,你用私钥加密敏感数据传递给第三方合适么?显然不合适,因为公钥公开的,别人都可以拿到公钥,也就意味着你加密的数据都可以解密,所以适合的场景比如私钥加密,公钥只是用来验证加密的内容,每个人都可以来验证,该场景是不在乎加密内容被其它攻击者看到的,甚至说内容本来就是公开的,对于接收者用公钥确保内容没有被篡改即可,所以我们通常说非对称算法“私钥签名,公钥验证签名”,另外一点,“公钥加密,私钥解密”,因为私钥只有我们自己手上有,所以理论上也只有我们自己可以解密,这样是安全的,https证书验证以及握手协议过程中会体现这一点。
4.4 数字签名算法
4.4.1 简述
数字签名算法可以看做是一种带有密钥的消息摘要算法,并且这种密钥包含了公钥和私钥。也就是说数字签名算法是非对称加密算法和消息摘要算法的结合体,遵循“私钥签名,公钥验证”的签名认证方式。
数字签名算法是公钥基础设施(Public Key Infrastructure,PKI)以及许多网络安全机制(SSL/TLS,VPN等)的基础。
数字签名算法要求能够验证数据完整性、认证数据来源,并起到抗否认的作用。
4.4.2 算法介绍
数字签名算法主要包括RSA、DSA、ECDSA共3种算法,其中RSA算法源于整数因子分解问题,DSA和ECDSA算法源于离散对数问题。
- RSA:典型的非对称加密算法,结合摘要算法可形成对应的签名算法,如结合MD5或者SHA 等摘要算法
- DSA:继RSA算法后出现的基于DSS的数字签名算法,旨在形成数字签名标准,为后续数字签名算法的形成奠定基础
-
ECDSA:椭圆曲线加密算法ECC与DSA算法的结合,相对于传统签名算法,具有速度快、强度高、签名短等优点,其用途也越来越广泛。
数字签名的算法传递模型:
- 甲方使用非对称加密算法构建密钥对。
- 甲方公布甲方公钥
- 使用私钥对数据签名,这里一般是结合摘要算法,比如摘要算法对数据进行摘要计算,私钥对摘要值加密。
- 发送签名值以及数据。
- 使用公钥对签名进行验证,这里一般是公钥对签名数据解密出来得到摘要值,对数据进行摘要计算,然后比对摘要值是否一致。
4.4.3 应用场景
我们以蚂蚁金服开放平台上接口签名方案为例,详细说明可以打开如下文档:
蚂蚁开放平台签名专区
- 跟前面微信支付平台上的方案不一样,微信支付采用的HMAC,通过摘要计算过程中的密钥以及摘要值比对确定合法性,蚂蚁金服采用的RSA和SHA,具体如下:
- 生成RSA密钥。
- 上传公钥到平台并获取支付宝公钥。
- 使用私钥对请求签名。
- 使用支付宝公钥对请求验证签名。
-
蚂蚁开放平台支持的签名算法,建议使用RSA2,安全性更高。
- 从上面我们可以看出,蚂蚁开放平台接口签名就是采用的非对称加密算法RSA和摘要算法SHA1和SHA256,第三方发给支付宝的请求采用自己的私钥签名,蚂蚁平台用你上传的公钥对我们的请求进行签名认证,同样的我们收到的蚂蚁平台的请求,我们用支付宝公钥进行签名认证,这跟我们前面提到的数字签名传递模型是符合的。