Android HTTP Retrofit 數(shù)據(jù)加密RSA+AES

1.背景

在不用https的情況下,網(wǎng)絡請求需要手動加密,加密的方式有很多,對稱加密或者非對稱加密,考慮到安全性的前提,非對稱加密是必須的,但是如果傳輸?shù)臄?shù)據(jù)量很大,例如傳輸一張人臉圖片,傳輸加上服務端解密會比較慢。

所以采取對稱加密+非對稱加密最佳,以下介紹RSA+AES的加密方式

2.實現(xiàn)方式

Android 持有服務端生成的RSA公鑰,數(shù)據(jù)用隨機生成的AES秘鑰加密,AES秘鑰用RSA公鑰加密,加密后的AES秘鑰通過請求頭的方式傳輸給服務端,服務端返回的數(shù)據(jù)再用AES解密,請求完成。因為AES每次請求都是重新生成,保證了安全性,沒有服務端RSA私鑰就算攔截到了請求也解不開。

3.代碼

  • Retrofit中添加攔截器
OkHttpClient.Builder okBuilder = new OkHttpClient.Builder().addInterceptor(new DataEncryptInterceptor());

 retrofit = new Retrofit.Builder().client(okBuilder.build()).build();
  • 攔截器代碼實現(xiàn)
    public class DataEncryptInterceptor implements Interceptor {


        @Override
        public Response intercept(Chain chain) throws IOException {
            //請求
            Request request = chain.request();
            MediaType mediaType = MediaType.parse("text/plain; charset=utf-8");
            //隨機生成AES秘鑰
            String aesKey = AESUtil.getAESKey();
            try {
                //獲取未加密數(shù)據(jù)
                RequestBody oldRequestBody = request.body();
                Buffer requestBuffer = new Buffer();
                oldRequestBody.writeTo(requestBuffer);
                String oldBodyStr = requestBuffer.readUtf8();
                requestBuffer.close();

                //未加密數(shù)據(jù)用AES秘鑰加密
                String  newBodyStr= EncryptionManager.getInstance().publicEncryptClient(oldBodyStr);
                //AES秘鑰用服務端RSA公鑰加密
                String key= EncryptionManager.getInstance().publicEncrypt(aesKey);
                //構成新的request 并通過請求頭發(fā)送加密后的AES秘鑰
                Headers headers = request.headers();
                RequestBody newBody = RequestBody.create(mediaType, newBodyStr);
                //構造新的request
                request = request.newBuilder()
                        .headers(headers)
                        .addHeader("Device-Key", key)
                        .method(request.method(), newBody)
                        .build();
            }catch (Exception e){

            }
            //響應
            Response response = chain.proceed(request);
            if (response.code() == 200) {
                try {
                    //獲取加密的響應數(shù)據(jù)
                    ResponseBody oldResponseBody = response.body();
                    String oldResponseBodyStr = oldResponseBody.string();
                    //加密的響應數(shù)據(jù)用AES秘鑰解密
                    String newResponseBodyStr="";
                    if (!TextUtils.isEmpty(oldResponseBodyStr)){
                        newResponseBodyStr = AESUtil.aesDecrypt(oldResponseBodyStr,aesKey);
                    }
                    oldResponseBody.close();
                    //構造新的response
                    ResponseBody newResponseBody = ResponseBody.create(mediaType, newResponseBodyStr);
                    response = response.newBuilder().body(newResponseBody).build();
                }catch (Exception e){
                    LogUtils.d("RetrofitLog","e"+e.getMessage());
                }finally {
                    response.close();
                }
            }
            //返回
            return response;
        }
    }

4.其他

AES和RSA的秘鑰生成和加解密就不寫了,網(wǎng)上一大堆

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容