对称(DES/AES)与非对称(RSA/SSL/数字证书)加密介绍及实际应用

本文不对具体的算法作深刻研究,只是讲解各类安全算法的原理和使用场景。html


1、数据校验算法

数据校验,是为保护数据的完整性,用一种指定的算法对原始数据计算出的一个校验值。当接收方用一样的算法再算一次校验值,若是两次校验值同样,表示数据完整。android

一、奇偶校验git

          能检测出信息传输过程中的一位误码。出现错误不能检测出错误,只能要求重发。算法

二、 CRC循环冗余校验数组

         经过增长若干冗余位,能够检测出传输过程当中的错误。检错和纠错能力强,在通讯领域运用较普遍。浏览器

三、MD5校验安全

          MD5算法是一种信息摘要算法,是经过哈希映射的原理获得一个大文件简短的MD5值。该算法是一种不可逆算法,也就是说开发者不能经过MD5值获得原始文件的数据。这里有一种可能性,不一样的数据文件获得相同的MD5值,可是这种状况通常开发过程中都不予考虑(数据碰撞)。服务器

四、 SHA网络

       SHA(Secure Hash Algorithm)是由美国专门制定密码算法的标准机构——美国国家标准技术研究院(NIST)制定的,SHA系列算法的摘要长度分别为:SHA为20字节(160位)、SHA256为32字节(256位)、 SHA384为48字节(384位)、SHA512为64字节(512位),因为它产生的数据摘要的长度更长,所以更难以发生碰撞,所以也更为安全,它是将来数据摘要算法的发展方向。因为SHA系列算法的数据摘要长度较长,所以其运算速度与MD5相比,也相对较慢。dom

      同MD5算法相同,他也是一种不可逆的算法


2、对称加密算法

  • 一、Base64 编解码

     该算法只能称为一种校验,是对原始的数据进行了一个编码的过程。 有编码就有解码,该过程是一个可逆的。该算法安全性较差,能够很轻松的经过解码将密文转换为明文,从而获取信息。

  • 二、DES 数据加密算法

       是对称加密算法领域中的典型算法,如今认为是一种不安全的加密算法,由于如今已经有用穷举法攻破DES密码的报道了。尽管如此,该加密算法仍是运用很是广泛,是一种标准的加密算法。3DES是DES的增强版本。

      DES加密的秘钥是 56位,而3DES加密算法的秘钥是 112位或者168位。3DES加密处理速度较慢、密钥计算时间较长、加密效率不高。

  • 三、AES 数据加密算法(推荐使用)

Advanced Encryption Standard ,高级数据加密标准,AES算法能够有效抵制针对DES的攻击算法。

密钥创建时间短、灵敏性好、内存需求低、安全性高

DES/3DES/AES 三种加密算法的对好比下:

image

  • 四、异或加密

异或运算中,若是某个字符(或数值)x 与 一个数值m 进行异或运算获得y,则再用y 与 m 进行异或运算就能够还原为 x ,所以应用这个原理能够实现数据的加密解密功能。

这种加密算法较简单,只是简单的将明文转换为不易看出的密文,破解的复杂度彻底取决于秘钥的长度。


3、非对称加密算法

      公开密钥加密,又称 asymmetric cryptography (非对称加密),即存在两把不一样的密钥,分别称为公钥 Pu 和私钥 Pr,公钥一般用来加密明文 M,只有私钥才能解密密文 C,若是用 E 和 D 分别表示加密和解密算法,那么有:

C = E(M,Pu);   // 加密公式,M为明文,C为密文,

M = D(C,Pr);   // 解密公式

 image 

传统的对称加密需双方共享相同的密钥,通讯安全很大程度依赖双方是否能妥善的管理密钥。公开密钥加密发明是密码学最为重要的里程碑之一,它从数学的角度保证了通讯安全。公开密钥加密体系有三大范畴:

  • Encryption/Decryption:即加密与解密,发送方接收方的公钥加密消息(秘钥由接收方生成,传送给发送方)

  • Digital Signature:数字签名,发送方用公钥加密消息摘要生成签名,保证消息的完整性和可靠性

一、RSA加密

这种算法以欧拉函数为基础,这里不具体展开:

这种算法很是可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还没法破解(至少没人公开宣布,由于大数的因式分解计算量特别大)。所以能够认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。

具体原理能够见:公钥私钥的生成及加解密过程

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.htm

https://www.kancloud.cn/kancloud/rsa_algorithm/48488

二、SSL/TLS协议

         具体来讲,SSL/TLS 并非一种算法,而是为了保证通讯安全的一种协议,固然里面用到了相关加密算法如非对称加密算法、数字证书、HD秘钥交换算法等。Https多使用这种协议进行网络数据的传输。


         bg2014092003

经过上述这张图大体了解这种协议的通讯过程。上述过程的目的只是为了获取比较安全的Session Key,固然这个Key须要Client Random + Server Random + Permaster secret 三者共同生成,安全性较高。Session key 用于后面通讯对数据进行对称加密。 双方得到Session Key 后经过http协议进行数据传输,Session Key 用来对http传输的内容进行加密。

关于SSL/TLS的详细讲解请参考 阮一峰的博客连接。

http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html

TOTP

TOTP 的全称是"基于时间的一次性密码"(Time-based One-time Password)。它是公认的可靠解决方案,已经写入国际标准 RFC6238

它的步骤以下。

第一步:用户开启双因素认证后,服务器生成一个密钥。

第二步:服务器提示用户扫描二维码(或者使用其余方式),把密钥保存到用户的手机。也就是说,服务器和用户的手机,如今都有了同一把密钥。

第四步,服务器也使用密钥和当前时间戳,生成一个哈希,跟用户提交的哈希比对。只要二者不一致,就拒绝登陆。

注意,密钥必须跟手机绑定。一旦用户更换手机,就必须生成全新的密钥。

算法原理:

TC = floor((unixtime(now) − unixtime(T0)) / TS)

上面的公式中,TC 表示一个时间计数器,unixtime(now)是当前 Unix 时间戳,unixtime(T0)是约定的起始时间点的时间戳,默认是0,也就是1970年1月1日。TS 则是哈希有效期的时间长度,默认是30秒。所以,上面的公式就变成下面的形式。

TC = floor(unixtime(now) / 30)

因此,只要在 30 秒之内,TC 的值都是同样的。前提是服务器和手机的时间必须同步。

接下来,就能够算出哈希了。

TOTP = HASH(SecretKey, TC)

TOTP 有硬件生成器和软件生成器之分,都是采用上面的算法。


数字签名过程(防止公钥被伪造 ):

http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

一、经过公钥私钥进行加密通讯,发送方发送的内容只有经过私钥才能打开,因此保证了发送信息的私密性。

二、第三方能够把伪造的公钥给发送方,再截获发送的信息,经过本身的私钥解密信息。 这里Https协议中引入的CA(certificate authority)能够很好的解决这个问题。证书中心用本身的私钥为传输的公钥和一些信息进行加密,发送者能够经过证书中的公钥解密证书中的信息,这些信息中包含了须要传送的公钥。(暂且认为证书中的信息都是对的,通常证书中心都是可靠性比较高的机构颁发的)

经过Chrome打开百度网页的时候,F12建, Security菜单栏能够看到百度的证书。证书里面包含:颁发者、颁给者、公钥、有效期等信息。

a) 客户端向服务器发出加密请求

request

b) 服务器用本身的私钥加密网页之后,连同自己的数字证书,一块儿发送给客户端

response

c) 客户端(浏览器)的"证书管理器",有"受信任的根证书颁发机构"列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表以内。

camanager


Android端如何使用https发送请求

      网上关于https的使用文章大多数是关于浏览器如何经过签名进行验证的,浏览器会保存各个网站由CA认证中心颁发的数字签名并进行校验。那么问题来了,当客户端和服务端握手完成后,客户端如何判断服务端发送的公钥和相关信息没有被第三方篡改(对应c图)?  其实,客户端则须要提早将CA证书导入进来,当建立请求时将证书的相关信息添加进去便可完成https请求和验证。

android端实现https请求具体流程:https://developer.android.com/training/articles/security-ssl

客户端添加证书实现:

InputStream is = getAssets().open("srca.cer");
private SSLSocketFactory getSslSocketFactory(InputStream... certificates){
        try{
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates)
            {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

                if (certificate != null)
                    certificate.close();
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            trustManagerFactory.init(keyStore);
            sslContext.init
                    (
                            null,
                            trustManagerFactory.getTrustManagers(),
                            new SecureRandom()
                    );
            return sslContext.getSocketFactory();
        }catch (Exception e){

        }
        return null;

    }

建立HttpsURLConnection完成后将证书信息设置进去再发送请求:

httpsConn.setSSLSocketFactory(sslSocketFactory);


http网络请求中的token

      咱们都是知道HTTP协议是无状态的,这种无状态意味着程序须要验证每一次请求,从而辨别客户端的身份,那么如何经过只登录一次就能实现后续已登陆状态呢?

token


1.用户登陆校验,校验成功后就返回Token给客户端。

2.客户端收到数据后保存在客户端

3.客户端每次访问API是携带Token到服务器端。

4.服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

那么这里有个问题: 服务端怎么知道携带的token就是这个用户的token而不是伪造的? 后续补充

签名的实际应用

      如今有三个参数(A、B、C 封装在一个类Data中)须要传输到服务端,那么如何保证 这三个数据不是别人伪造发送的,能够在传这三个数据数据以外再添加一个数据 sign(String类型)。

  客户端sign的生成算法:

  第一步:对三个参数名称(与服务端提早约定好传输变量的名称)进行字典排序,拼接成字符串StringA(key1=value1&key2=value2&key3=value3),同时字符串的拼接遵循指定的规则。

  第二步:在stringA最后拼接秘钥key(只有服务端和客户端知道,第三方不能得到,这也是签名的关键)获得finalStringA

  第三部: 对finalStringA 作MD5计算,并将字符数组转换成16进制的字符串。

    自此sign生成过程结束。

生成根据Data 中A、B、C三个参数的值以及Key 生成了sign以后,将sign值赋给Data中的sign。将Data转换成JSONObject格式再转换成字符数组

经过 HttpURLConnection传送到服务端。服务端经过拿到A、B、C的数值后会本身经过一样的算法生成sign,若是和客户端传送的Sign不同则此次传送多是第三方伪造的。

  这种签名就保证了第三方不能伪造数据和服务端进行通讯。(具体的流程以下图所示)

未命名文件 (26)


可是这里有个问题,其它人员获取到了通讯秘钥secret,则能够伪造数据,毕竟客户端的代码颇有可能被破解的(就算放在native层均可以被破解),可是对于安全等级较低通讯这种加密措施也足够了。

相关文章
相关标签/搜索