Java Google SafetyNet API JwsResult是一个哈希字符串,而不是JSON
我已经成功地实现了谷歌安全网API,甚至有一个成功的响应。问题是来自Java Google SafetyNet API JwsResult是一个哈希字符串,而不是JSON,java,android,safetynet,safetynet-api,Java,Android,Safetynet,Safetynet Api,我已经成功地实现了谷歌安全网API,甚至有一个成功的响应。问题是来自DetectionResponse的JWSResult是一个哈希字符串,而我的期望是在响应中得到一个JSON 请问我需要先在哪里查找问题 下面是调用assert()的代码: fun callSafetyNetAttentationApi(context: Activity, callback: SafetyNetCallback) { if (GoogleApiAvailability.getInstance(
DetectionResponse
的JWSResult
是一个哈希字符串,而我的期望是在响应中得到一个JSON
请问我需要先在哪里查找问题
下面是调用assert()
的代码:
fun callSafetyNetAttentationApi(context: Activity, callback: SafetyNetCallback) {
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS) {
val nonce: ByteArray? = getRequestNonce("Safety Net Sample: " + System.currentTimeMillis())
val client = SafetyNet.getClient(context)
nonce?.let {
val task: Task<AttestationResponse> = client.attest(it, BuildConfig.SAFETY_NET_KEY)
task.addOnSuccessListener { response -> safetyNetSuccess(response, callback) }
.addOnFailureListener { callback.isDeviceTrusted(false) }
} ?: kotlin.run {
callback.isDeviceTrusted(false)
}
} else {
MaterialDialog.Builder(context)
.title("The app cannot be used")
.content("Please update Google Play Services and try again.")
.cancelable(false)
.positiveText("Dismiss")
.onPositive { dialog, which -> context.finish() }
.show()
}
}
fun callsafetynetattentionapi(上下文:活动,回调:SafetyNetCallback){
if(GoogleAppAvailability.getInstance().isGooglePlayServicesAvailable(上下文)==ConnectionResult.SUCCESS){
val nonce:ByteArray?=getRequestNonce(“安全网示例:+System.currentTimeMillis())
val client=SafetyNet.getClient(上下文)
现在?让我来{
val task:task=client.authentice(it、BuildConfig.SAFETY\u NET\u KEY)
task.addOnSuccessListener{response->safetyNetSuccess(响应,回调)}
.addOnFailureListener{callback.isDeviceTrusted(false)}
}?:kotlin.run{
callback.isDeviceTrusted(false)
}
}否则{
MaterialDialog.Builder(上下文)
.title(“应用程序无法使用”)
.content(“请更新Google Play服务并重试。”)
.可取消(错误)
.positiveText(“驳回”)
.onPositive{dialog,其中->context.finish()}
.show()
}
}
这是一个典型的JSON响应,您将在执行safetyNetClient.attest(nonce,apiKey)
后收到该响应:
这里的foo.bar.zar
是一个base64编码字符串,类似于aisnfaksdf.8439hundf.ghbadsjn
,其中每个部分对应于:
<Base64 encoded header>.<Base64 encoded JSON data>.<Base64 encoded signature>
然后使用您喜欢的JSON库构造java对象,例如GSON:
val model = Gson().fromJson(extractJwsData(jws).toString(), SafetyNetApiModel::class.java)
其中SafetyNetApiModel
为:
class SafetyNetApiModel {
@SerializedName("nonce")
var nonce: String? = null
@SerializedName("timestampMs")
var timestampMs: Long? = null
@SerializedName("apkPackageName")
var apkPackageName: String? = null
@SerializedName("apkCertificateDigestSha256")
var apkCertificateDigestSha256: List<String>? = null
@SerializedName("apkDigestSha256")
var apkDigestSha256: String? = null
@SerializedName("ctsProfileMatch")
var ctsProfileMatch: Boolean? = null
@SerializedName("basicIntegrity")
var basicIntegrity: Boolean? = null
}
类安全Netapimodel{
@序列化名称(“nonce”)
变量nonce:字符串?=null
@SerializedName(“时间戳”)
var timestampMs:Long?=null
@SerializedName(“apkPackageName”)
var apkPackageName:字符串?=null
@SerializedName(“apkCertificateDigestSha256”)
var apkCertificateDigestSha256:列表?=空
@SerializedName(“apkDigestSha256”)
var apkDigestSha256:字符串?=null
@SerializedName(“ctsProfileMatch”)
var ctsProfileMatch:布尔?=null
@序列化名称(“基本完整性”)
变量基本完整性:布尔?=null
}
查看以供参考。JWS响应始终是符号结果。在获得JWS响应后,您必须使用nonce从服务器端代码验证它,然后服务器将验证该请求,如果它是有效的请求,那么它将返回如下JSON响应 查看链接 对于示例应用程序:
private OnSuccessListener<SafetyNetApi.AttestationResponse> mSuccessListener =
new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
@Override
public void onSuccess(SafetyNetApi.AttestationResponse attestationResponse) {
/*
Successfully communicated with SafetyNet API.
Use result.getJwsResult() to get the signed result data. See the server
component of this sample for details on how to verify and parse this result.
*/
mResult = attestationResponse.getJwsResult();
Log.d(TAG, "Success! SafetyNet result:\n" + mResult + "\n");
/*
TODO(developer): Forward this result to your server together with
the nonce for verification.
You can also parse the JwsResult locally to confirm that the API
returned a response by checking for an 'error' field first and before
retrying the request with an exponential backoff.
NOTE: Do NOT rely on a local, client-side only check for security, you
must verify the response on a remote server!
*/
}
};
private OnSuccessListener msSuccessListener=
新OnSuccessListener(){
@凌驾
成功时公共无效(SafetyNetApi.DetectionResponse-DetectionResponse-DetectionResponse){
/*
已成功与SafetyNet API通信。
使用result.getJwsResult()获取签名结果数据。请参阅服务器
有关如何验证和分析此结果的详细信息,请参阅此示例的组件。
*/
mResult=DetectionResponse.getJwsResult();
Log.d(标记“Success!SafetyNet result:\n”+mResult+“\n”);
/*
TODO(开发人员):将此结果连同
用于验证的临时值。
您还可以在本地解析JwsResult,以确认API
通过先检查“错误”字段,然后再检查返回响应
使用指数回退重试请求。
注意:不要依赖本地、客户端仅检查安全性,否则会导致
必须在远程服务器上验证响应!
*/
}
};
阅读成功响应中的注释,此代码来自我没有遵循您的代码,因为您无法将字节数组转换为json。因此,在转换为json之前,我将其转换为字符串,但这就是我得到的”[B@efc8722"这可能不是一个100%的解决方案,但我尝试只在应用程序级别应用它。请参阅我对第一个答案的评论。你不需要转换为Base64,只需将JWS响应哈希字符串发送到服务器进行验证,它总是有效的,我已经检查了客户端和服务器端的代码,它对我有效,但我的后端没有执行修订后的safetynet服务器端。因此,如何测试设备完整性,如果您正在将服务器代码写入客户端应用程序,那么它的用途是什么。您正在客户端应用程序中生成nonce,并验证响应是否也在客户端应用程序中。您将如何检查设备是否已根目录和设备完整性,任何黑客或攻击者都将绕过下载并将你的应用程序运行到根设备中。嘿@klutch,你是否在不从服务器调用API的情况下将JWS响应解析为JSON?如果完成了,请告诉我,这将对我有帮助。你需要Base64。解码jwsResult,以提取JSON。
class SafetyNetApiModel {
@SerializedName("nonce")
var nonce: String? = null
@SerializedName("timestampMs")
var timestampMs: Long? = null
@SerializedName("apkPackageName")
var apkPackageName: String? = null
@SerializedName("apkCertificateDigestSha256")
var apkCertificateDigestSha256: List<String>? = null
@SerializedName("apkDigestSha256")
var apkDigestSha256: String? = null
@SerializedName("ctsProfileMatch")
var ctsProfileMatch: Boolean? = null
@SerializedName("basicIntegrity")
var basicIntegrity: Boolean? = null
}
private OnSuccessListener<SafetyNetApi.AttestationResponse> mSuccessListener =
new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
@Override
public void onSuccess(SafetyNetApi.AttestationResponse attestationResponse) {
/*
Successfully communicated with SafetyNet API.
Use result.getJwsResult() to get the signed result data. See the server
component of this sample for details on how to verify and parse this result.
*/
mResult = attestationResponse.getJwsResult();
Log.d(TAG, "Success! SafetyNet result:\n" + mResult + "\n");
/*
TODO(developer): Forward this result to your server together with
the nonce for verification.
You can also parse the JwsResult locally to confirm that the API
returned a response by checking for an 'error' field first and before
retrying the request with an exponential backoff.
NOTE: Do NOT rely on a local, client-side only check for security, you
must verify the response on a remote server!
*/
}
};