zoukankan      html  css  js  c++  java
  • Retrofit/OkHttp API接口加固技术实践(下)

    作者/Tamic
    http://blog.csdn.net/sk719887916/article/details/65448628

    上节加固介绍了APi单纯Post用对称加密(Base64 为列子)加密方式。这样的加密方式还是存在一定的风险,加密效率虽高,但易破解,本节将介绍怎么用非对称加密 来加解密okhttp的数据,本文採用RSA加密算法为栗子。

    对称加密

    对称加密是最传统的加密方式,比上非对称加密,缺少安全性,可是它依然是用的比較多的加密方法。


    对称加密採用单密钥加密方式,不论是加密还是解密都是用同一个密钥,即“一把钥匙开一把锁”。对称加密的优点在于操作简单、管理方便、速度快。它的缺点在于密钥在
    网络传输中easy被窃听,每一个密钥仅仅能应用一次。对密钥管理造成了困难。对称加密的实现形式和加密算法的公开性使它依赖于密钥的安全性。而不是算法的安全性。

    对称加密原理以及对称加密算法

    对称加密的核心——通信两方共享一个密钥 通信过程: A有明文m,使用加密算法E,密钥key。生成密文c=E(key,m); B收到密文c,使用解密算法D,密钥key。得到明文
    m=D(key,c); 比喻: 对称加密是最直观,也是历史最久远的加密手段,相似于加锁和解锁,仅仅只是钥匙的个数非常多(~~2^100)。一个人穷其一生也试不全然部可能的钥匙
    因此加密密钥能够从解密密钥中推算出来,同一时候解密密钥也能够从加密密钥中推算出来。

    而在大多数的对称算法中,加密密钥和解密密钥是同样的。所以也称这样的加密算法为秘
    密密钥算法或单密钥算法。

    它要求发送方和接收方在安全通信之前。商定一个密钥。

    对称算法的安全性依赖于密钥,泄漏密钥就意味着不论什么人都能够对他们发送或接收的消息解
    密,所以密钥的保密性对通信性至关重要。

    主要有DES算法。3DES算法,TDEA算法,Blowfish算法。RC5算法。IDEA算法。

    非对称加密

    非对称密算法是一种密钥的加密方法。

    非对称加密算法须要两个密钥:公钥(publickey)和私钥(privatekey)。公钥与私钥是一对存在,假设用公钥对数据进行加密,仅仅实用相应的私钥才干解密;假设用密钥对数据进行加密。那么仅仅实用相应的公钥才干解密。由于加密和解密使用的是两个不同的密钥,所以这样的算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将当中的一把作为公用密钥向其他方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的还有一把专用密钥对加密后的信息进行解密。

    还有一方面,甲方能够使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。
    甲方仅仅能用其专用密钥解密由其公用密钥加密后的不论什么信息。 非对称加密算法的保密性比較好,它消除了终于用户交换密钥的须要。


    非对称password体制的特点:算法强度复杂、安全性依赖于算法与密钥可是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称password体制中仅仅有一种密钥,而且是非公开的,假设要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,当中一个是公开的,这样就能够不须要像对称password那样传输对方的密钥了。这样安全性就大了非常多。

    列如 :支付宝的加密方式就採用非对称加密方式。支付宝会给客户提供支付宝证书,作为用户验证是否是来自支付宝的数据。防止第三方假冒支付宝,而客户手中持有私钥。用户支付宝发送的数据经过支付宝的公钥进项加密,则支付宝能够採用自己的的私钥进行解密。

    工作过程

    • 1.A要向B发送信息,A和B都要产生一对用于加密
    • 2.A的私钥保密,A的公钥告诉B。B的私钥保密。B的公钥告诉A。

    • 3.A要给B发送信息时,A用B的公钥加密信息。由于A知道B的公钥。
    • 4.A将这个数据发给B(已经用B的公钥加密消息)。

    • 5.B收到这个数据后后,B用自己的私钥解密A的消息。其他全部收到这个报文的人都无法解密,由于仅仅有B才有B的私钥。

    通俗点能够这么理解:

    • 浏览器向server发出请求,询问对方支持的对称加密算法和非对称加密算法;server回应自己支持的算法。
    • 浏览器选择两方都支持的加密算法,并请求server出示自己的证书;server回应自己的证书。
    • 浏览器随机产生一个用于本次会话的对称加密的钥匙,并使用server证书中附带的公钥对该钥匙进行加密后传递给server。server为本次会话保持
    • 该对称加密的钥匙。第三方不知道server的私钥,即使截获了数据也无法解密。非对称加密让不论什么浏览器都能够与server进行加密会话。

    浏览器使用对称加密的钥匙对请求消息加密后传送给server,server使用该对称加密的钥匙进行解密;server使用对称加密的钥匙对响应消息加密后传送给浏览器,浏览器使用该对称加密的钥匙进行解密。第三方不知道对称加密的钥匙,即使截获了数据也无法解密。对称加密提高了加密速度

    数字证书

    数字证书就是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式。数字证书不是数字身份证,而是身份认证机构盖在数字身份证上的一个章或印(或者说加在数字身份证上的一个签名)。

    它是由权威机构——CA机构。又称为证书授权(Certificate Authority)中心发行的。人们能够在网上用它来识别对方的身份。


    数字证书绑定了公钥及其持有者的真实身份,它相似于现实生活中的居民身份证,所不同的是数字证书不再是纸质的证照。而是一段含有证书持有者身份信息并经过认证中心审核签发的电子数据,广泛用在电子商务和移动互联网中。。


    通俗讲就是车管所会给每一个车辆进行认证颁发车牌。通过车牌我们能够查到全部车辆和驾驶员的信,二数字证书就辨别唯一身份,支付宝等的数字证书就是公开的。这不是支付宝自己决定。而是由国际组织认证,这样无论是哪个用户首先就能够依据浏览器返回的证书辨别支付宝的真伪。

    数字签名

    数字签名用来,保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。


    数字签名是将摘要信息用发送者的私钥加密。与原文一起传送给接收者。接收者仅仅实用发送者的公钥才干解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对照。假设同样,则说明收到的信息是完整的,在传输过程中没有被改动,否则说明信息被改动过,因此数字签名能够验证信息的完整性。假设中途数据被纂改或者丢失。

    那么对方就能够依据数字签名来辨别是否是来自对方的第一手信息数据。
    数字签名是个加密的过程,数字签名验证是个解密的过程。

    參数加解密

    首先。Android中生成了对称密钥:

    public static  SecretKeySpec generateSymmetric() {
    
        // Set up secret key spec for 128-bit AES encryption and decryption
        SecretKeySpec sks = null;
        try {
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed("any data used as random seed".getBytes());
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            kg.init(128, sr);
            sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
    
            System.out.println("AES KEY: " + sks);
        } catch (Exception e) {
            Log.e(TAG, "AES secret key spec error");
        }
        return sks;
    }
    

    然后将SecretKeySpec转换为Base64字符串格式:

    
    public static String ConvertSymmetricKeyToString(SecretKeySpec key) {
    
        String symmetric_key = null;
    
        symmetric_key = Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
        return symmetric_key;
    }
    

    调用函数:

    
        SecretKeySpec symmKey = generateSymmetric();
    
    
        newSymmetricKeyString = CreateEncryptedXml.ConvertSymmetricKeyToString(symmKey);
    

    用SecretKeySpec加密数据:

    
    private static String encryptDataWithSymmetricKey (SecretKeySpec symmKey, String data) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    
    
        // encryption
        byte[] toBeCiphred = data.getBytes("UTF-8");
        String encryptedData = null;
    
        try {
            Cipher c = Cipher.getInstance("AES");
            c.init(Cipher.ENCRYPT_MODE, symmKey);
            byte[] encodedBytes = c.doFinal(toBeCiphred);
            System.out.println("BYTE STRING (ASYMM): " + encodedBytes);
            encryptedData = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
    
        } catch (Exception e) {
            Log.e(TAG, "AES encryption error");
            throw new RuntimeException(e);
        }
    
    
        return encryptedData;
    }
    
    
     encryptedData = encryptDataWithSymmetricKey(symmKey, text);
    

    使用拦截器:

    然后将字符串秘密AES密钥和加密的数据(用这个AES密钥加密)使用okhttp使POST请求。字符串密钥使用的是RSA加密。

    
    public class EncryptionInterceptor implements Interceptor {
    
           private static final String TAG =   EncryptionInterceptor.class.getSimpleName();
    
           private static final boolean DEBUG = true;
    
           @Override
           public Response intercept(Chain chain) throws IOException {
    
    
           Request request = chain.request();
           RequestBody oldBody = request.body();
           Buffer buffer = new Buffer();
           oldBody.writeTo(buffer);
           String strOldBody = buffer.readUtf8();
           MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
           String strNewBody = encryptDataWithSymmetricKey(symmKey, text);
    
           RequestBody body = RequestBody.create(mediaType, strNewBody);
           request = request.newBuilder().header("Content-Type", body.contentType().toString()).header("Content-Length", String.valueOf(body.contentLength())).method(request.method(), body).build();
           return chain.proceed(request);
      }
    }
    

    在server端能够解密(从RSA)秘密AES密钥,并得到它的字符串表示。在client(Android)和server端(server)上是一样的。

    使用这个字符串AES密钥解密数据

    
      String encryptionMethod = "AES-128-CBC";  
    
      //decryptedAESKey is an Android AES SecretKeySpec converted  to string
      //in Android the string key was base64_encoded, 服务端解密 decode
    
      String secretHash = base64Decode(decryptedAESKey);
    
    
     // Decrypt
      String decryptedMessage = opensslDecrypt(base64Decode(encryptedData),  encryptionMethod, secretHash);
    

    总结

    完整的非对称加密过程

    假如如今 你向支付宝 转账(术语数据信息),为了保证信息传送的保密性、真实性、完整性和不可否认性,须要对传送的信息进行数字加密和签名,其传送过程为:

    • 1.首先你要确认是否是支付宝的数字证书,假设确觉得支付宝身份后。则对方真实可信。能够向对方传送信息,
    • 2.你准备好要传送的数字信息(明文)计算要转的多少钱。对方支付宝账号等。
    • 3.你 对数字信息进行哈希运算。得到一个信息摘要(client主要职责);
    • 4.你 用自己的私钥对信息摘要进行加密得到 你 的数字签名,并将其附在数字信息上。
    • 5.你 随机产生一个加密密钥,并用此password对要发送的信息进行加密(密文)。
    • 6.你用 支付宝的公钥对刚才随机产生的加密密钥进行加密,将加密后的 DES 密钥连同密文一起传送给支付宝。
    • 7.支付宝收到 你 传送来的密文和加密过的 DES 密钥,先用自己的私钥对加密的 DES 密钥进行解密,得到 你随机产生的加密密钥;
    • 8.支付宝 然后用随机密钥对收到的密文进行解密,得到明文的数字信息,然后将随机密钥抛弃;
    • 9.支付宝 用你 的公钥对 你的的数字签名进行解密。得到信息摘要;
    • 10.支付宝用同样的哈希算法对收到的明文再进行一次哈希运算,得到一个新的信息摘要。
    • 11.支付宝将收到的信息摘要和新产生的信息摘要进行比較。假设一致,说明收到的信息没有被改动过。
    • 12 确定收到信息。然后进行向对方进行付款交易,一次非对称密过程结束。在这后面的流程就不属于本次非对称加密的范畴,算支付宝个人的自我流程,也就是循环以上过程。

    作者/Tamic
    http://blog.csdn.net/sk719887916/article/details/65448628

    阅读推荐

    Retrofit/OkHttp API接口加固技术实践(上)

  • 相关阅读:
    document.getElementById("mytxt").style.left=""style.left在IE的FF中注意
    asp.net 用户控件中 使用相对路径的解决方法 图片路径问题(用户控件、图片路径) ,ResolveUrl
    探索 Block (一) (手把手讲解Block 底层实现原理)
    iOS 多线程开发 (概念与API简介)
    iOS 性能小点
    iOS runtime (二)(runtime学习之AutoCoding源码分析)
    探索 NSRunLoop (二)(NSRunLoop 自己动手实现SimpleRunLoop)
    iOS NSNotificationCenter (自己实现一个通知中心XMCNotificationCenter)
    iOS runtime (三)(runtime学习之YYModel源码分析)
    iOS runtime(一)(runtime 分析理解)
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7402610.html
Copyright © 2011-2022 走看看