未获得 SafetyNet Api 证明响应
Not getting SafetyNet Api Attestation Response
我遇到了 google safetynet api 认证响应的问题。即使我向“client.AttestAsync()”方法提供了 safetynet 客户端、nonce 和 apikey,它也不会 return SafetyNetApiAttestationResponse。下面的代码可能有什么问题?如何获得证明响应以检查 android 设备在模拟器上是 运行 还是在 xamarin 表单中的 root 设备?
protected override void OnCreate(Bundle bundle)
{
Instance = this;
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
BackgroundAggregator.Init(this);
base.OnCreate(bundle);
DependencyService.Register<ToastNotification>();
ToastNotification.Init(this);
Rg.Plugins.Popup.Popup.Init(this);
global::Xamarin.Forms.Forms.Init(this, bundle);
micService = DependencyService.Resolve<IMicrophoneService>();
if (GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this, 13000000) == ConnectionResult.Success)
{
SafetyNetClient client = Android.Gms.SafetyNet.SafetyNetClass.GetClient(this);
byte[] nonce = Android.Gms.SafetyNet.Nonce.Generate();
bool valid = Task.Run(() => RunSafetyNetCheck(client, nonce)).Result;
if (!valid)
LoadApplication(new App());
else
Toast.MakeText(this, "Failed response validation with Google!", ToastLength.Short).Show();
}
else
{
Toast.MakeText(this, "Update Google Play services.!", ToastLength.Short).Show();
}
}
private async Task<bool> RunSafetyNetCheck(SafetyNetClient client, byte[] nonce)
{
bool valid = false;
SafetyNetApiAttestationResponse r = await client.AttestAsync(nonce, apiKey);
if (r != null && !string.IsNullOrEmpty(r.JwsResult))
{
attestationResponse = r;
var decodedResult = r.DecodeJwsResult(nonce);
string error = null;
if (VerifyAttestResponse(decodedResult, nonce, out error))
{
valid = await attestationResponse.ValidateWithGoogle(apiKey);
}
else
{
Toast.MakeText(this, "Compatibility Failed: " + error, ToastLength.Long).Show();
}
}
else
{
Toast.MakeText(this, "Failed to Check Compatibility", ToastLength.Long).Show();
}
return valid;
}
private bool VerifyAttestResponse(string data, byte[] sentNonce, out string errorMessage)
{
errorMessage = null;
var json = JsonObject.Parse(data);
var error = GetValue(json, "error");
var nonce = GetValue(json, "nonce");
var timestampMs = GetValue(json, "timestampMs");
var apkPackageName = GetValue(json, "apkPackageName");
var apkCertDigestSha256 = GetValue(json, "apkCertificateDigestSha256");
var apkDigestSha256 = GetValue(json, "apkDigestSha256");
var ctsProfileMatch = GetValue(json, "ctsProfileMatch") == "true";
if (!string.IsNullOrEmpty(error))
{
errorMessage = "Response Contained an Error: " + error;
return false;
}
var sentNonceStr = Convert.ToBase64String(sentNonce);
if (!nonce.Equals(sentNonceStr))
{
errorMessage = "Nonce's do no match";
return false;
}
if (PackageName != apkPackageName)
{
errorMessage = "Package Names do not match";
return false;
}
if (!ctsProfileMatch)
{
errorMessage = "CTS Profile was false";
return false;
}
return true;
}
private string GetValue(JsonValue json, string field)
{
if (!json.ContainsKey(field))
return string.Empty;
return json[field].ToString().Trim('"');
}
我在这里制作了自己的示例,无法重现您看到的行为。您可以在以下存储库中找到完整代码:https://github.com/Cheesebaron/Xamarin-SafetyNet
相关部分在我的Activity我做的:
protected override async void OnCreate(Bundle savedInstanceState)
{
...
var attestation = await safetynetHelper.RequestAttestation();
ctsProfileMatch.Text = $"{attestation.ctsProfileMatch}";
basicIntegrity.Text = $"{attestation.basicIntegrity}";
}
在我的安全网助手内部,我执行以下操作:
public async Task<(bool ctsProfileMatch, bool basicIntegrity)> RequestAttestation()
{
SafetyNetClient client = SafetyNetClass.GetClient(context);
var nonce = Nonce.Generate(24);
try
{
var response = await client.AttestAsync(nonce, attestationApiKey).ConfigureAwait(false);
var result = response.JwsResult;
var validSignature = await VerifyAttestationOnline(result).ConfigureAwait(false);
...
}
catch (Exception)
{
// handle errors here
}
return (false, false);
}
注意 all 个调用有 .ConfigureAwait(false)
。我们不需要一直切换上下文。
这工作正常并按预期加载证明。
我遇到了 google safetynet api 认证响应的问题。即使我向“client.AttestAsync()”方法提供了 safetynet 客户端、nonce 和 apikey,它也不会 return SafetyNetApiAttestationResponse。下面的代码可能有什么问题?如何获得证明响应以检查 android 设备在模拟器上是 运行 还是在 xamarin 表单中的 root 设备?
protected override void OnCreate(Bundle bundle)
{
Instance = this;
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
BackgroundAggregator.Init(this);
base.OnCreate(bundle);
DependencyService.Register<ToastNotification>();
ToastNotification.Init(this);
Rg.Plugins.Popup.Popup.Init(this);
global::Xamarin.Forms.Forms.Init(this, bundle);
micService = DependencyService.Resolve<IMicrophoneService>();
if (GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this, 13000000) == ConnectionResult.Success)
{
SafetyNetClient client = Android.Gms.SafetyNet.SafetyNetClass.GetClient(this);
byte[] nonce = Android.Gms.SafetyNet.Nonce.Generate();
bool valid = Task.Run(() => RunSafetyNetCheck(client, nonce)).Result;
if (!valid)
LoadApplication(new App());
else
Toast.MakeText(this, "Failed response validation with Google!", ToastLength.Short).Show();
}
else
{
Toast.MakeText(this, "Update Google Play services.!", ToastLength.Short).Show();
}
}
private async Task<bool> RunSafetyNetCheck(SafetyNetClient client, byte[] nonce)
{
bool valid = false;
SafetyNetApiAttestationResponse r = await client.AttestAsync(nonce, apiKey);
if (r != null && !string.IsNullOrEmpty(r.JwsResult))
{
attestationResponse = r;
var decodedResult = r.DecodeJwsResult(nonce);
string error = null;
if (VerifyAttestResponse(decodedResult, nonce, out error))
{
valid = await attestationResponse.ValidateWithGoogle(apiKey);
}
else
{
Toast.MakeText(this, "Compatibility Failed: " + error, ToastLength.Long).Show();
}
}
else
{
Toast.MakeText(this, "Failed to Check Compatibility", ToastLength.Long).Show();
}
return valid;
}
private bool VerifyAttestResponse(string data, byte[] sentNonce, out string errorMessage)
{
errorMessage = null;
var json = JsonObject.Parse(data);
var error = GetValue(json, "error");
var nonce = GetValue(json, "nonce");
var timestampMs = GetValue(json, "timestampMs");
var apkPackageName = GetValue(json, "apkPackageName");
var apkCertDigestSha256 = GetValue(json, "apkCertificateDigestSha256");
var apkDigestSha256 = GetValue(json, "apkDigestSha256");
var ctsProfileMatch = GetValue(json, "ctsProfileMatch") == "true";
if (!string.IsNullOrEmpty(error))
{
errorMessage = "Response Contained an Error: " + error;
return false;
}
var sentNonceStr = Convert.ToBase64String(sentNonce);
if (!nonce.Equals(sentNonceStr))
{
errorMessage = "Nonce's do no match";
return false;
}
if (PackageName != apkPackageName)
{
errorMessage = "Package Names do not match";
return false;
}
if (!ctsProfileMatch)
{
errorMessage = "CTS Profile was false";
return false;
}
return true;
}
private string GetValue(JsonValue json, string field)
{
if (!json.ContainsKey(field))
return string.Empty;
return json[field].ToString().Trim('"');
}
我在这里制作了自己的示例,无法重现您看到的行为。您可以在以下存储库中找到完整代码:https://github.com/Cheesebaron/Xamarin-SafetyNet
相关部分在我的Activity我做的:
protected override async void OnCreate(Bundle savedInstanceState)
{
...
var attestation = await safetynetHelper.RequestAttestation();
ctsProfileMatch.Text = $"{attestation.ctsProfileMatch}";
basicIntegrity.Text = $"{attestation.basicIntegrity}";
}
在我的安全网助手内部,我执行以下操作:
public async Task<(bool ctsProfileMatch, bool basicIntegrity)> RequestAttestation()
{
SafetyNetClient client = SafetyNetClass.GetClient(context);
var nonce = Nonce.Generate(24);
try
{
var response = await client.AttestAsync(nonce, attestationApiKey).ConfigureAwait(false);
var result = response.JwsResult;
var validSignature = await VerifyAttestationOnline(result).ConfigureAwait(false);
...
}
catch (Exception)
{
// handle errors here
}
return (false, false);
}
注意 all 个调用有 .ConfigureAwait(false)
。我们不需要一直切换上下文。
这工作正常并按预期加载证明。