问题描述
我正在使用 SafetyNet 来验证 Android 应用程序的完整性。
这是目前的流程。
我得到一个 base64 字符串。我解码它并得到如下响应。
{
"evaluationType": "BASIC","ctsProfileMatch": false,"apkPackageName": "com.test.safetynetproject","apkDigestSha256": "CbU9JzwRzQneYqnEXewB56ZzPm1DgQ4LGUK0eGlWmyM=","nonce": "U2FnYXI=","apkCertificateDigestSha256": [
"AJRBzWCfJIY7QD2cp4sv9t0cCGMRGdxuID9VdplV1H4="
],"timestampMs": 1624099377557,"basicIntegrity": false
}
现在我想验证 apkCertificateDigestSha256。使用 cmd 从我的系统创建的 sha256 是 -
C:\Program Files\Java\jdk-11.0.11\bin>keytool -list -v -alias androiddebugkey -keystore C:\Users\.android\debug.keystore
Enter keystore password:
Alias name: androiddebugkey
Creation date: May 25,2021
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: C=US,O=Android,CN=Android Debug
Issuer: C=US,CN=Android Debug
Serial number: 1
Valid from: Tue May 25 11:48:00 IST 2021 until: Thu May 18 11:48:00 IST 2051
Certificate fingerprints:
SHA1: 43:16:E2:63:DB:2A:53:7C:7D:BB:E9:80:7B:05:1C:74:7C:84:66:A2
SHA256: 00:94:41:CD:60:9F:24:86:3B:40:3D:9C:A7:8B:2F:F6:DD:1C:08:63:11:19:DC:6E:20:3F:55:74:F2:D5:D4:7E
Signature algorithm name: SHA1withRSA (weak)
Subject Public Key Algorithm: 2048-bit RSA key
Version: 1
Warning:
The certificate uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
SHA256
00:94:41:CD:60:9F:24:86:3B:40:3D:9C:A7:8B:2F:F6:DD:1C:08:63:11:19:DC:6E:20:3F:55:74:F2:D5:D4:7E
问题- 我想验证 apkCertificateDigestSha256 是否与应用程序证书相同。 Bt无法找到任何方法来做到这一点。
尝试- 我尝试对 AHRBzWCfJIY7QD2cp4sv9t0cCGMRGdxuID9VdplV1H4= 进行 base64 解码,并得到一个与 cmd 中创建的 sha256 不匹配的随机字节数组。
代码 -
val decode =
String(
Base64.decode(
responseJws!!.apkCertificateDigestSha256!![0],Base64.DEFAULT
),StandardCharsets.UTF_8
)
输出 -
���A�`�$�;@=���/��c�n ?Ut���~
这与 43:16:E2:63:DB:2A:53:7C:7D:BB:E9:80:7B:05:1C:74:7C:84:66:A2 不匹配。
更新-
找到了一些参考,但真的不知道如何实现。 Ref1
如何进行匹配?
解决方法
我使用 SafetyNet API 来访问设备的运行时环境。我一直在服务器上签署应用程序证书,以根据我们在 SafetyNet 响应中得到的内容验证其 sha256。以下是您可以参考的步骤(如果也适用于您)。
-
获取签署 X509Certificate 的 SHA256 指纹
MessageDigest md = MessageDigest.getInstance("SHA-256"); 字节[] der = cert.getEncoded(); md.update(der); byte[] sha256 = md.digest();
-
将 sha256 编码为 base64 字符串
String checksum = Base64.getEncoder().encodeToString(sha256)
-
将校验和与SafetyNet响应的apkCertificateDigestSha256匹配
我认为这可以帮助您
1.在 GG 示例中查找 AttestationStatement 文件。并添加此功能:
public String bytesToHex(byte[] bytes) {
StringBuffer result = new StringBuffer();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100,16).substring(1));
return result.toString();
}
2.找到 getApkCertificateDigestSha256 函数并像这样编辑:
public byte[][] getApkCertificateDigestSha256() {
byte[][] certs = new byte[apkCertificateDigestSha256.length][];
for (int i = 0; i < apkCertificateDigestSha256.length; i++) {
certs[i] = Base64.decodeBase64(apkCertificateDigestSha256[i]);
System.out.println(bytesToHex(certs[i]));
}
return certs;
}
3.在 OnlineVerrify 中找到 process() 函数并添加如下:
if (stmt.getApkPackageName() != null && stmt.getApkDigestSha256() != null) {
System.out.println("APK package name: " + stmt.getApkPackageName());
System.out.println("APK digest SHA256: " + Arrays.toString(stmt.getApkDigestSha256()));
System.out.println("APK certificate digest SHA256: " +
Arrays.deepToString(stmt.getApkCertificateDigestSha256()));
}
- 现在,运行,您将看到 SHA-256 并进行比较。
不是:没有“:”字符 bettwen sha-256 生成,因为我很懒。 ^^。