久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

如何從 Android 應用程序中的標頭數據驗證 Safety

How to validate Safety Net JWS signature from header data in Android app(如何從 Android 應用程序中的標頭數據驗證 Safety Net JWS 簽名)
本文介紹了如何從 Android 應用程序中的標頭數據驗證 Safety Net JWS 簽名的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我正在使用 SafetyNet API 來檢查設備是否已植根并使用以下有用的代碼,但這使用了 Android 驗證 API驗證 JWT 簽名:

https://github.com/scottyab/safetynethelper

我想在客戶端進行驗證只是為了減少另一個 Web 服務的開銷,此外它還限制每天只有 10k 個請求.

所以在解碼 JWS 后,我得到以下信息

示例 JWS 消息響應

xxxx.yyy.zzzz

標題數據

{"alg":"RS256","x5c":["<certificate1 string>","<certificate2 string>"]}

有效載荷數據

{"nonce":"<nounce>",時間戳":1472794339527,"apkPackageName":"<apkPackageName>","apkDigestSha256":"",ctsProfileMatch":真,"extension":"<擴展字符串>","apkCertificateDigestSha256":["<apkCertificateDigestSha256 字符串>"],"basicIntegrity":true}

簽名在這部分中,如果執行 Base64 解碼,它將變得不可讀,因此下面是 JWS 最后一個元素中收到的簽名字符串

<預> <代碼> Gw09rv1aBbtd4Er7F5ww_3TT1mPRD5YouMkPkwnRXJq8XW_cxlO4428DHTJdD8Tbep-Iv3nrVRWt2t4pH1uSr2kJ9budQJuXqzOUhN93r2Hfk-UAKUYQYhp89_wOWjSCG4ySVHD4jc9S1HrZlngaUosocOmhN4SzLZN5o8BXyBdXkjhWwgArd4bcLhCWJzmxz5iZfkhDiAyeNRq09CeqjRx_plqAy8eR_OaI_2idZBNIGfd2KmLK_CKaeVjDxuC4BzJsIlVRiuLrvP362Wwhz4r1bHh8flmHr88nK99apP2jkQD2l7lPv8y5F3FN3DKhJ15CzHR6ZbiTOw1fUteifg

現在根據谷歌

<塊引用>

"驗證兼容性檢查響應:提取 SSL 證書來自 JWS 消息的鏈.驗證 SSL 證書鏈并使用SSL 主機名匹配以驗證葉證書是否已頒發到主機名 attest.android.com.使用證書來驗證JWS 消息的簽名."

我確實有證書字符串和簽名我應該如何去驗證 SSL 證書,它是字符串和主機名匹配的第二個證書和如何驗證簽名.

我需要這方面的指針,并且代碼被剪斷會很有幫助.

解決方案

您要在設備上驗證 JWT 簽名的方式不安全.考慮下一個案例:

  • 設備已root,具有root權限的惡意軟件應用程序捕獲您對 Google 的 SafetyNet 的請求并返回自簽名回復.

  • 當您使用自己的服務器服務驗證響應時 - 您會發現您收到的響應不是由 Google 提供的.如果您在設備本地執行此操作 - 同一惡意軟件應用程序可能會捕獲您驗證 JWT 簽名的請求并以 true 進行響應.

無論如何,您可以在本地執行此操作:

  1. 您需要從 Google 開發人員處為您的應用獲取 API 密鑰.
  2. 使用 Android 設備驗證 API:

來自 Android 開發者:

<塊引用>

注意:驗證響應消息的 API 方法的固定速率限制為每個項目每天 10,000 個請求.您應該僅在初始開發階段使用 verify() 方法進行測試.您不應在生產場景中調用該方法.

[...]

要使用 Android 設備驗證 API:

創建包含 JWS 全部內容的 JSON 消息消息格式如下:

{ "signedAttestation": "<輸出>getJwsResult()>"}

使用 HTTP POST 請求發送帶有"application/json" 的 Content-Type 到以下 URL:https://www.googleapis.com/androidcheck/v1/attestations/verify?key=<你的 API 密鑰>

服務驗證消息的完整性,如果消息有效,它返回一個 JSON 消息,內容如下內容:{ isValidSignature": true }

實際上(代碼來自 SafetyNet Helper):

/**** 使用 Android 設備驗證 API 驗證結果.** 注意:這僅驗證提供的 JWS(JSON Web 簽名)消息是從實際的 SafetyNet 服務接收到的.* 它*不*驗證負載數據是否與您的原始兼容性檢查請求相匹配.* 發布到 https://www.googleapis.com/androidcheck/v1/attestations/verify?key=<你的 API 密鑰>** 更多信息請參閱 {link https://developer.android.com/google/play/safetynet/start.html#verify-compat-check}** 由 scottab 于 27/05/2015 創建.*/公共類 AndroidDeviceVerifier {私有靜態最終字符串 TAG = AndroidDeviceVerifier.class.getSimpleName();//用于驗證安全網響應 - 10,000 個請求/天免費私有靜態最終字符串 GOOGLE_VERIFICATION_URL = "https://www.googleapis.com/androidcheck/v1/attestations/verify?key=";私有最終字符串 apiKey;私有最終字符串簽名驗證;私有 AndroidDeviceVerifierCallback 回調;公共接口 AndroidDeviceVerifierCallback{無效錯誤(字符串 s);無效成功(布爾 isValidSignature);}public AndroidDeviceVerifier(@NonNull String apiKey, @NonNull String signatureToVerify) {this.apiKey = apiKey;this.signatureToVerify = signatureToVerify;}公共無效驗證(AndroidDeviceVerifierCallback androidDeviceVerifierCallback){回調 = androidDeviceVerifierCallback;AndroidDeviceVerifierTask 任務 = new AndroidDeviceVerifierTask();任務.執行();}/*** 為 URL 連接提供信任管理器.默認情況下,這使用系統默認值加上 GoogleApisTrustManager (SSL pinning)* @return 包括系統默認值和 GoogleApisTrustManager(SSL pinning)的 TrustManager 數組* @throws KeyStoreException* @throws NoSuchAlgorithmException*/受保護的 TrustManager[] getTrustManagers() 拋出 KeyStoreException,NoSuchAlgorithmException {TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());//使用默認的系統信任管理器初始化trustManagerFactory.init((KeyStore)null);TrustManager[] defaultTrustManagers = trustManagerFactory.getTrustManagers();TrustManager[] trustManagers = Arrays.copyOf(defaultTrustManagers, defaultTrustManagers.length + 1);//添加我們的谷歌APIs pinning TrustManager以獲得額外的安全性trustManagers[defaultTrustManagers.length] = new GoogleApisTrustManager();返回信任管理器;}私有類 AndroidDeviceVerifierTask 擴展 AsyncTask<Void, Void, Boolean>{私人異常錯誤;@覆蓋protected Boolean doInBackground(Void...params) {//Log.d(TAG, "signatureToVerify:" + signatureToVerify);嘗試 {URL verifyApiUrl = 新 URL(GOOGLE_VERIFICATION_URL + apiKey);SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, getTrustManagers(), null);HttpsURLConnection urlConnection = (HttpsURLConnection) verifyApiUrl.openConnection();urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());urlConnection.setRequestMethod("POST");urlConnection.setRequestProperty("Content-Type", "application/json");//build post body { "signedAttestation": "<getJwsResult() 的輸出>"}字符串 requestJsonBody = "{ "signedAttestation": ""+signatureToVerify+""}";byte[] outputInBytes = requestJsonBody.getBytes("UTF-8");輸出流 os = urlConnection.getOutputStream();os.write(outputInBytes);os.close();urlConnection.connect();//resp ={ isValidSignature": true }InputStream = urlConnection.getInputStream();StringBuilder sb = new StringBuilder();BufferedReader rd = new BufferedReader(new InputStreamReader(is));字符串線;while ((line = rd.readLine()) != null) {sb.append(line);}字符串響應 = sb.toString();JSONObject responseRoot = new JSONObject(response);if(responseRoot.has("isValidSignature")){返回 responseRoot.getBoolean("isValidSignature");}}catch (異常 e){//請求驗證 JWS 消息時出錯錯誤 = e;Log.e(TAG, "驗證 JWS 消息時出現問題:" + e.getMessage(), e);返回假;}返回假;}@覆蓋受保護的無效 onPostExecute(Boolean aBoolean) {如果(錯誤!=空){callback.error(error.getMessage());}別的 {callback.success(aBoolean);}}}}

I'm using SafetyNet API for checking if device is rooted or not and using the below helpful code but this uses Android verification API to validate the JWT signature:

https://github.com/scottyab/safetynethelper

And I want to validate on client side only to reduce the overhead of another web service all and besides it has limitation on only 10k request per day.

So after decoding the JWS i'm getting the below info

Sample JWS message response

xxxx.yyy.zzzz

Header data

{"alg":"RS256","x5c":["<certificate1 string>","<certificate2 string>"]}

Payload data

{"nonce":"<nounce>",
"timestampMs":1472794339527,
"apkPackageName":"<apkPackageName>",
"apkDigestSha256":"<sha digest string>",
"ctsProfileMatch":true,
"extension":"<extension string>",
"apkCertificateDigestSha256":["<apkCertificateDigestSha256 string>"],"basicIntegrity":true}

Signature in this part if perform Base64 decoding it becomes unreadable so below is the Signature string as received in JWS last element

Gw09rv1aBbtd4Er7F5ww_3TT1mPRD5YouMkPkwnRXJq8XW_cxlO4428DHTJdD8Tbep-Iv3nrVRWt2t4pH1uSr2kJ9budQJuXqzOUhN93r2Hfk-UAKUYQYhp89_wOWjSCG4ySVHD4jc9S1HrZlngaUosocOmhN4SzLZN5o8BXyBdXkjhWwgArd4bcLhCWJzmxz5iZfkhDiAyeNRq09CeqjRx_plqAy8eR_OaI_2idZBNIGfd2KmLK_CKaeVjDxuC4BzJsIlVRiuLrvP362Wwhz4r1bHh8flmHr88nK99apP2jkQD2l7lPv8y5F3FN3DKhJ15CzHR6ZbiTOw1fUteifg

Now as per google

"Verify the compatibility check response: Extract the SSL certificate chain from the JWS message. Validate the SSL certificate chain and use SSL hostname matching to verify that the leaf certificate was issued to the hostname attest.android.com. Use the certificate to verify the signature of the JWS message."

I do have the cert string and signature how should I go about validating SSL certificate which is string and host name matching on second cert and how to validate signature.

I need pointers on this and code snipped would be very helpful.

解決方案

The way you want to validate JWT signature on the device is not secure. Think about next case:

  • the device is rooted, malware application with root privileges catches your request to Google's SafetyNet and returns self-signed response.

  • When you verify the response with your own server service - you will get that the response you've got wasn't provided by Google. If you do this locally on the device - the same malware app could catch you request to verify JWT signature and respond with true.

Anyway, you can do this locally:

  1. You need to get API key from Google developers for your application.
  2. Use the Android Device Verification API:

From Android Developers:

Note: The API method to verify response messages has a fixed rate limit of 10,000 requests per day, per project. You should use the verify() method only for testing during the initial development stage. You shouldn't call the method in a production scenario.

[...]

To use the Android Device Verification API:

Create a JSON message containing the entire contents of the JWS message in the following format:

{ "signedAttestation": "<output of> getJwsResult()>" }

Use an HTTP POST request to send the message with a Content-Type of "application/json" to the following URL: https://www.googleapis.com/androidcheck/v1/attestations/verify?key=<your API key>

The service validates the integrity of the message, and if the message is valid, it returns a JSON message with the following contents: { "isValidSignature": true }

So actually (code from SafetyNet Helper):

/**
 *
 * Validates the result with Android Device Verification API.
 *
 * Note: This only validates that the provided JWS (JSON Web Signature) message was received from the actual SafetyNet service.
 * It does *not* verify that the payload data matches your original compatibility check request.
 * POST to https://www.googleapis.com/androidcheck/v1/attestations/verify?key=<your API key>
 *
 * More info see {link https://developer.android.com/google/play/safetynet/start.html#verify-compat-check}
 *
 * Created by scottab on 27/05/2015.
 */
public class AndroidDeviceVerifier {

    private static final String TAG = AndroidDeviceVerifier.class.getSimpleName();

    //used to verifiy the safety net response - 10,000 requests/day free
    private static final String GOOGLE_VERIFICATION_URL = "https://www.googleapis.com/androidcheck/v1/attestations/verify?key=";

    private final String apiKey;
    private final String signatureToVerify;
    private AndroidDeviceVerifierCallback callback;

    public interface AndroidDeviceVerifierCallback{
        void error(String s);
        void success(boolean isValidSignature);
    }

    public AndroidDeviceVerifier(@NonNull String apiKey, @NonNull String signatureToVerify) {
        this.apiKey = apiKey;
        this.signatureToVerify = signatureToVerify;
    }

    public void verify(AndroidDeviceVerifierCallback androidDeviceVerifierCallback){
        callback = androidDeviceVerifierCallback;
        AndroidDeviceVerifierTask task = new AndroidDeviceVerifierTask();
        task.execute();
    }

    /**
     * Provide the trust managers for the URL connection. By Default this uses the system defaults plus the GoogleApisTrustManager (SSL pinning)
     * @return array of TrustManager including system defaults plus the GoogleApisTrustManager (SSL pinning)
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     */
    protected TrustManager[] getTrustManagers() throws KeyStoreException, NoSuchAlgorithmException {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        //init with the default system trustmanagers
        trustManagerFactory.init((KeyStore)null);
        TrustManager[] defaultTrustManagers = trustManagerFactory.getTrustManagers();
        TrustManager[] trustManagers = Arrays.copyOf(defaultTrustManagers, defaultTrustManagers.length + 1);
        //add our Google APIs pinning TrustManager for extra security
        trustManagers[defaultTrustManagers.length] = new GoogleApisTrustManager();
        return trustManagers;
    }



    private class AndroidDeviceVerifierTask extends AsyncTask<Void, Void, Boolean>{

        private Exception error;

        @Override
        protected Boolean doInBackground(Void... params) {

            //Log.d(TAG, "signatureToVerify:" + signatureToVerify);

            try {
                URL verifyApiUrl = new URL(GOOGLE_VERIFICATION_URL + apiKey);

                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, getTrustManagers(), null);

                HttpsURLConnection urlConnection = (HttpsURLConnection) verifyApiUrl.openConnection();
                urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Content-Type", "application/json");

                //build post body { "signedAttestation": "<output of getJwsResult()>" }
                String requestJsonBody = "{ "signedAttestation": ""+signatureToVerify+""}";
                byte[] outputInBytes = requestJsonBody.getBytes("UTF-8");
                OutputStream os = urlConnection.getOutputStream();
                os.write(outputInBytes);
                os.close();

                urlConnection.connect();

                //resp ={ "isValidSignature": true }
                InputStream is = urlConnection.getInputStream();
                StringBuilder sb = new StringBuilder();
                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = rd.readLine()) != null) {
                    sb.append(line);
                }
                String response = sb.toString();
                JSONObject responseRoot = new JSONObject(response);
                if(responseRoot.has("isValidSignature")){
                    return responseRoot.getBoolean("isValidSignature");
                }
            }catch (Exception e){
                //something went wrong requesting validation of the JWS Message
                error = e;
                Log.e(TAG, "problem validating JWS Message :" + e.getMessage(), e);
                return false;
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            if(error!=null){
                callback.error(error.getMessage());
            }else {
                callback.success(aBoolean);
            }
        }
    }

}

這篇關于如何從 Android 應用程序中的標頭數據驗證 Safety Net JWS 簽名的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How to wrap text around components in a JTextPane?(如何在 JTextPane 中的組件周圍環繞文本?)
MyBatis, how to get the auto generated key of an insert? [MySql](MyBatis,如何獲取插入的自動生成密鑰?[MySql])
Inserting to Oracle Nested Table in Java(在 Java 中插入 Oracle 嵌套表)
Java: How to insert CLOB into oracle database(Java:如何將 CLOB 插入 oracle 數據庫)
Why does Spring-data-jdbc not save my Car object?(為什么 Spring-data-jdbc 不保存我的 Car 對象?)
Use threading to process file chunk by chunk(使用線程逐塊處理文件)
主站蜘蛛池模板: 久久久久久亚洲精品 | 亚洲一区二区三区在线 | 久草中文在线观看 | 午夜视频在线观看网址 | 91精品国产91久久久久久吃药 | 亚洲第一在线 | 久久人人网 | 国产一区二区三区免费 | 奇色影视| 久草福利 | 国产精品毛片一区二区在线看 | av网站免费 | 国产精品成人国产乱一区 | 久久久久久高潮国产精品视 | 日本久久精品视频 | 精久久 | 日本网站免费在线观看 | 国产精品久久久久久一区二区三区 | 亚洲精品在 | 国产精品视频中文字幕 | 久久久久久成人 | 久久综合久久综合久久综合 | 久久99精品久久久久 | 国产精品免费一区二区三区 | 日本超碰 | 精品成人一区二区 | 国产精品一区二区福利视频 | 日本三级网址 | 午夜色播 | 国产综合第一页 | 亚洲人成免费 | 午夜一区二区三区视频 | 精品国产一区二区三区性色 | 色婷婷国产精品综合在线观看 | 亚洲精品乱 | 亚洲成人一区 | 亚洲自拍偷拍av | 在线国产视频观看 | 在线观看成人 | 精品国产91亚洲一区二区三区www | 国产一区二区三区免费 |