You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python与Kotlin Android中SHA-224哈希值不一致问题求助

问题排查:Kotlin与Python SHA-224哈希不一致

你的问题核心是Python和Kotlin生成的待哈希JSON字节流不匹配,导致最终哈希结果不同,具体问题点如下:

1. 嵌套JSON对象未递归排序

Python的json.dumps(msg, sort_keys=True)会递归对所有层级的JSON键排序(包括address下的city、street),但你的Kotlin代码仅处理了顶层键的排序,嵌套对象内部的键顺序未做处理,直接导致序列化后的JSON结构差异。

2. JSON序列化格式不一致

Python的json.dumps默认生成无额外空格的紧凑JSON字符串(比如{"name":"Alice","age":25}),而Kotlin的JSONObject.toString()默认会在键值对、逗号后添加空格(比如{"name": "Alice", "age": 25}),两者的字节流完全不同,哈希自然无法一致。

修正后的Kotlin代码

以下代码解决了递归排序和紧凑序列化的问题,确保与Python端生成的JSON字节流完全一致:

import android.util.Base64
import org.json.JSONObject
import java.security.MessageDigest
import java.nio.charset.StandardCharsets

fun calculateHash() {
    // 直接用Map构建数据,避免字符串处理引入格式问题
    val msg = mapOf(
        "name" to "Alice",
        "age" to 25,
        "address" to mapOf(
            "city" to "Wonderland",
            "street" to "Rabbit Hole"
        )
    )

    // 递归排序所有层级的JSON键
    val sortedJsonObj = buildSortedJsonObject(msg)
    // 生成无空格的紧凑JSON字符串
    val sortedJsonStr = sortedJsonObj.toString().replace(" ", "")
    val jsonBytes = sortedJsonStr.toByteArray(StandardCharsets.UTF_8)

    // 计算SHA-224哈希并截取前16字节
    val sha224Digest = MessageDigest.getInstance("SHA-224")
    val hashBytes = sha224Digest.digest(jsonBytes)
    val truncatedHash = hashBytes.sliceArray(0 until 16)

    // URL安全Base64编码(无填充)
    val hashBase64 = Base64.encodeToString(truncatedHash, Base64.URL_SAFE or Base64.NO_PADDING)

    println(hashBase64)
    android.util.Log.e("HashResult", hashBase64)
}

// 递归构建键排序的JSONObject
private fun buildSortedJsonObject(data: Any): JSONObject {
    return when (data) {
        is Map<*, *> -> {
            val sortedObj = JSONObject()
            // 对键排序后插入
            data.keys.filterIsInstance<String>().sorted().forEach { key ->
                val value = data[key]
                sortedObj.put(key, buildSortedJsonObject(value!!))
            }
            sortedObj
        }
        is List<*> -> {
            // 若存在数组可递归处理(按需启用)
            org.json.JSONArray().apply {
                data.forEach { item ->
                    put(buildSortedJsonObject(item!!))
                }
            }
        }
        else -> {
            // 基础类型直接返回
            data
        }
    }
}

验证步骤

  1. 分别打印Python和Kotlin端的sortedJsonStr,确认两者完全一致(无空格、键顺序完全相同)。
  2. 对比两者UTF-8编码后的字节数组,确保字节流完全匹配。
  3. 重新计算哈希,此时两端结果应完全一致。

内容的提问来源于stack exchange,提问作者Ganesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 16:50:55