protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); // Set our view from the "main" layout resource SetContentView (Resource.Layout.Main); buttonCheck = FindViewById<Button> (Resource.Id.buttonCheck); buttonVerify = FindViewById<Button> (Resource.Id.buttonVerify); buttonVerify.Enabled = false; googleApiClient = new GoogleApiClient.Builder (this) .EnableAutoManage (this, 1, result => { Toast.MakeText (this, "Failed to connect to Google Play Services", ToastLength.Long).Show (); }) .AddApi (SafetyNetClass.API) .Build (); buttonCheck.Click += async delegate { var nonce = Nonce.Generate (); // Should be at least 16 bytes in length. var r = await SafetyNetClass.SafetyNetApi.AttestAsync (googleApiClient, nonce); if (r.Status.IsSuccess) { // Store for future verification with google servers attestationResult = r; // Get the JSON from the JWS result by decoding var decodedResult = r.DecodeJwsResult (nonce); string error = null; // Try and verify the body of the response if (VerifyAttestResponse (decodedResult, nonce, out error)) { Toast.MakeText (this, "Compatibility Passed!", ToastLength.Long).Show (); buttonVerify.Enabled = true; } else { Toast.MakeText (this, "Compatibility Failed: " + error, ToastLength.Long).Show (); } } else { // Error Toast.MakeText (this, "Failed to Check Compatibility", ToastLength.Long).Show (); } }; buttonVerify.Click += async delegate { // Validate the JWS response with Google to ensure it came from them var valid = await attestationResult.ValidateWithGoogle (DEVELOPERS_CONSOLE_API_KEY); if (valid) Toast.MakeText (this, "Successfully validated response with Google!", ToastLength.Short).Show (); else Toast.MakeText (this, "Failed response validation with Google!", ToastLength.Short).Show (); }; }
public static async Task <bool> ValidateWithGoogle(this ISafetyNetApiAttestationResult result, string validationApiKey) { const string url = "https://www.googleapis.com/androidcheck/v1/attestations/verify?key="; var http = new HttpClient(); var jsonReq = "{ \"signedAttestation\": \"" + result.JwsResult + "\" }"; var content = new StringContent(jsonReq, Encoding.Default, "application/json"); var response = await http.PostAsync(url + validationApiKey, content); var data = await response.Content.ReadAsStringAsync(); response.EnsureSuccessStatusCode(); var json = JsonObject.Parse(data); if (json.ContainsKey("isValidSignature")) { return(json ["isValidSignature"].ToString().Trim('"').Equals("true")); } return(false); }
protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); buttonCheck = FindViewById <Button> (Resource.Id.buttonCheck); buttonVerify = FindViewById <Button> (Resource.Id.buttonVerify); buttonVerify.Enabled = false; googleApiClient = new GoogleApiClient.Builder(this) .EnableAutoManage(this, 1, result => { Toast.MakeText(this, "Failed to connect to Google Play Services", ToastLength.Long).Show(); }) .AddApi(SafetyNetClass.API) .Build(); buttonCheck.Click += async delegate { var nonce = Nonce.Generate(); // Should be at least 16 bytes in length. var r = await SafetyNetClass.SafetyNetApi.AttestAsync(googleApiClient, nonce); if (r.Status.IsSuccess) { // Store for future verification with google servers attestationResult = r; // Get the JSON from the JWS result by decoding var decodedResult = r.DecodeJwsResult(nonce); string error = null; // Try and verify the body of the response if (VerifyAttestResponse(decodedResult, nonce, out error)) { Toast.MakeText(this, "Compatibility Passed!", ToastLength.Long).Show(); buttonVerify.Enabled = true; } else { Toast.MakeText(this, "Compatibility Failed: " + error, ToastLength.Long).Show(); } } else { // Error Toast.MakeText(this, "Failed to Check Compatibility", ToastLength.Long).Show(); } }; buttonVerify.Click += async delegate { // Validate the JWS response with Google to ensure it came from them var valid = await attestationResult.ValidateWithGoogle(DEVELOPERS_CONSOLE_API_KEY); if (valid) { Toast.MakeText(this, "Successfully validated response with Google!", ToastLength.Short).Show(); } else { Toast.MakeText(this, "Failed response validation with Google!", ToastLength.Short).Show(); } }; }
public static string DecodeJwsResult(this ISafetyNetApiAttestationResult result, byte[] originalNonce) { return(JWT.JsonWebToken.Decode(result.JwsResult, originalNonce)); }