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 } } }
验证步骤
- 分别打印Python和Kotlin端的
sortedJsonStr,确认两者完全一致(无空格、键顺序完全相同)。 - 对比两者UTF-8编码后的字节数组,确保字节流完全匹配。
- 重新计算哈希,此时两端结果应完全一致。
内容的提问来源于stack exchange,提问作者Ganesh
相关产品推荐
相关产品推荐

