2

I am trying to learn how to implement safetynet with the reference of a fellow member in stackover. SafetyNet: package name always return null

The first section of the code is a complete code of SafetyNetVerifier

package com.example.stack;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Base64;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Random;


public class SafetyNetVerifier implements GoogleApiClient.OnConnectionFailedListener {

    private final Random mRandom = new SecureRandom();
    private String mResult;
    private GoogleApiClient mGoogleApiClient;

    private FragmentActivity activity;

    public SafetyNetVerifier(FragmentActivity activity) {
        this.activity = activity;
        buildGoogleApiClient();
        sendSafetyNetRequest();
    }

    private byte[] getRequestNonce(String data) {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[24];
        mRandom.nextBytes(bytes);
        try {
            byteStream.write(bytes);
            byteStream.write(data.getBytes());
        } catch (IOException e) {
            return null;
        }

        return byteStream.toByteArray();
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(activity)
                .addApi(SafetyNet.API)
                .enableAutoManage(activity, this)
                .build();
    }

    private void sendSafetyNetRequest() {
        Log.e("hqthao", "Sending SafetyNet API request.");

        String nonceData = "Safety Net Sample: " + System.currentTimeMillis();
        byte[] nonce = getRequestNonce(nonceData);

        SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
                .setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {

                    @Override
                    public void onResult(SafetyNetApi.AttestationResult result) {
                        Status status = result.getStatus();
                        if (status.isSuccess()) {
                            mResult = result.getJwsResult();
                            Log.e("hqthao", "Success! SafetyNet result:\n" + mResult + "\n");
                            SafetyNetResponse response = parseJsonWebSignature(mResult);
                            Log.e("hqthao", response.toString());
                        }
                    }
                });
    }

    @Nullable
    private SafetyNetResponse parseJsonWebSignature(String jwsResult) {
        if (jwsResult == null) {
            return null;
        }
        //the JWT (JSON WEB TOKEN) is just a 3 base64 encoded parts concatenated by a . character
        final String[] jwtParts = jwsResult.split("\\.");

        if (jwtParts.length == 3) {
            //we're only really interested in the body/payload
            String decodedPayload = new String(Base64.decode(jwtParts[1], Base64.DEFAULT));

            return SafetyNetResponse.parse(decodedPayload);
        } else {
            return null;
        }
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e("hqthao", "Error connecting to Google Play Services." + connectionResult.getErrorMessage());
    }

}

When i tried to debug, it will always stop at

SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)

May I know why is it so? I look at the Safetynet example provide by google and they will usually pair the API Key with the nonce. How can i change mGoogleApiClient to a API KEY?

private void sendSafetyNetRequest() {
        Log.e("hqthao", "Sending SafetyNet API request.");

        String nonceData = "Safety Net Sample: " + System.currentTimeMillis();
        byte[] nonce = getRequestNonce(nonceData);

        SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
                .setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {

                    @Override
                    public void onResult(SafetyNetApi.AttestationResult result) {
                        Status status = result.getStatus();
                        if (status.isSuccess()) {
                            mResult = result.getJwsResult();
                            Log.e("hqthao", "Success! SafetyNet result:\n" + mResult + "\n");
                            SafetyNetResponse response = parseJsonWebSignature(mResult);
                            Log.e("hqthao", response.toString());
                        }
                    }
                });
    }
Camellia
  • 141
  • 14
twistofytd
  • 29
  • 2
  • 6

2 Answers2

3

You should use the SafetyNetClient interface to test. The sample code is as follows:

SafetyNetClient client = SafetyNet.getClient(getActivity());
Task<SafetyNetApi.AttestationResponse> task = client.attest(nonce, BuildConfig.API_KEY);

You can refer to the latest code on GitHub: https://github.com/googlesamples/android-play-safetynet/blob/master/client/java/SafetyNetSample/Application/src/main/java/com/example/android/safetynetsample/SafetyNetSampleFragment.java

ham
  • 96
  • 4
1

From my understanding, you will need an instance of SafetyNetClient to execute the attest method and not SafetyNetApi.attest, which is deprecated and now disabled

In order to get the Client, use:

SafetyNet.getClient(this).attest()

See here and the example here for more details

Jayrassic
  • 127
  • 11