【问题标题】:Match Android apk SHA256 with SafetyNet apkCertificateDigestSha256将 Android apk SHA256 与 SafetyNet apkCertificateDigestSha256 匹配
【发布时间】:2021-09-03 20:57:45
【问题描述】:

我正在使用 SafetyNet 来验证 android 应用的完整性。

这是目前的流程。

  1. 我在服务器中生成一个 nonce 值并将其发送到 SafetyNet 服务以获取响应。
  2. 我得到了服务器的响应。现在我想在服务器上验证结果。

我得到一个 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, O=Android, 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 找不到任何方法。

尝试- 我尝试对 AJRBzWCfJIY7QD2cp4sv9t0cCGMRGdxuID9VdPLV1H4= 进行 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

如何进行匹配?

【问题讨论】:

    标签: android safetynet


    【解决方案1】:

    在此处查看代码作为如何进行验证的参考:https://github.com/Gralls/SafetyNetSample/blob/master/Server/src/main/java/pl/patryk/springer/safetynet/Main.kt

    我只是在搜索相同的东西时发现了它,所有的功劳都归于拥有该 repo 的人。

    【讨论】:

      【解决方案2】:

      我认为这可以帮助你

      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()));
          }
      
      1. 现在,运行,您将看到 SHA-256 并进行比较。

      不:没有“:”字符 bettwen sha-256 生成,因为我很懒。 ^^.

      【讨论】:

        【解决方案3】:

        我使用 SafetyNet API 来访问设备的运行时环境。我一直在服务器上签署应用程序证书,以根据我们在 SafetyNet 响应中获得的内容验证其 sha256。如果您也适用,以下是您可以参考的步骤。

        1. 获取签名 X509Certificate 的 SHA256 指纹

          MessageDigest md = MessageDigest.getInstance("SHA-256"); 字节[] der = cert.getEncoded(); md.update(der); byte[] sha256 = md.digest();

        2. 将 sha256 编码为 base64 字符串

          字符串 校验和 = Base64.getEncoder().encodeToString(sha256)

        3. checksum 与 SafetyNet 响应的 apkCertificateDigestSha256 匹配

        【讨论】:

        • 你能分享你的代码作为一个合适的例子吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-18
        • 2022-08-16
        • 2019-10-11
        • 1970-01-01
        • 1970-01-01
        • 2020-06-30
        • 2021-05-26
        相关资源
        最近更新 更多