【问题标题】:Not getting SafetyNet Api Attestation Response未获得 SafetyNet Api 证明响应
【发布时间】:2021-08-18 17:57:26
【问题描述】:

我遇到了关于 google 安全网 api 证明响应的问题。即使我向“client.AttestAsync()”方法提供了安全网客户端、nonce 和 apikey,它也不会返回 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('"');
}

【问题讨论】:

  • 您可以尝试集成Dotfuscator进行运行检查,以检测应用是否在root设备或模拟器上运行,请参考docs.microsoft.com/en-us/archive/msdn-magazine/2018/may/…
  • 我想改用safetynet(google play sevice api)
  • 会不会是死锁场景?我注意到您正在为正在开始的任务调用.Result,而您没有在等待的呼叫中添加.ConfigureAwait(false)
  • 你能不能让 OnCreate async voidawait RunSafetyNetCheck 调用。此外,在 RunSafetyNetCheck 方法中的等待调用中添加 .ConfigureAwait(false)
  • @Cheesebaron 我试过你上面提到的。但仍然没有得到任何回应。可能出了什么问题?

标签: xamarin xamarin.forms safetynet safetynet-api


【解决方案1】:

我在这里制作了自己的示例,无法重现您看到的行为。您可以在以下存储库中找到完整代码:https://github.com/Cheesebaron/Xamarin-SafetyNet

相关部分在我做的活动中:

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);
}

注意所有电话都有.ConfigureAwait(false)。我们不需要一直切换上下文。

这可以正常工作并按预期加载证明。

【讨论】:

    猜你喜欢
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 2020-07-25
    • 2018-05-21
    • 2020-08-25
    相关资源
    最近更新 更多