在 Python 和 Kotlin Android 中获取不同的 SHA-224 值

问题描述 投票:0回答:1

需要验证从后端收到的 Json 响应的 Hash 值。哈希值在Python中正确计算并与后端服务器哈希值匹配,这是正确的。我在 Kotlin Android 中总是得到不同的哈希值。分享下面的代码片段。

Python:

import json
import hashlib
import base64

msg = {
    "name": "Alice",
    "age": 25,
    "address": {
        "city": "Wonderland",
        "street": "Rabbit Hole"
    }
}

# Sort keys and ensure ASCII encoding
json_str = json.dumps(msg, ensure_ascii=False, sort_keys=True)
print(f"Serialized JSON (Python): {json_str}")

json_bin = json_str.encode('utf-8')

# Create SHA-224 hash and take first 16 bytes
hash_calculator = hashlib.sha224(json_bin)
hash_digest = hash_calculator.digest()[:16]

# Print hex digest
print(f"Hex digest (Python): {hash_digest.hex()}")

# Base64 encode
hash_encoded64 = base64.urlsafe_b64encode(hash_digest).decode('utf8')
print(f"Base64 encoded hash (Python): {hash_encoded64}")

但是当我将相同的 python 代码转换为 Kotlin 并运行时,我得到了不同的值。谁能检查一下并让我知道出了什么问题吗?

科特林:

    fun calculateHas(){
        // Original JSON message as a string
        val msg = """
        {
    "name": "Alice",
    "age": 25,
    "address": {
        "city": "Wonderland",
        "street": "Rabbit Hole"
      }
    }
        """.trim().trimIndent().replace("\n","")

        // Parse the JSON string into a JSONObject
        val jsonObj = JSONObject(msg)

        // Serialize the JSONObject into a string with sorted keys
        val sortedJsonObj = JSONObject()
        val keys = jsonObj.keys().asSequence().toList().sorted()
        for (key in keys) {
            sortedJsonObj.put(key, jsonObj.get(key))
        }
        val sortedJsonStr = sortedJsonObj.toString().replace("\n","").toByteArray(StandardCharsets.UTF_8)

        // Create a SHA-224 hash of the JSON byte array
        val sha224Digest = MessageDigest.getInstance("SHA-224")
        val hashBytes = sha224Digest.digest(sortedJsonStr)

        // Get the first 16 bytes of the hash
        val truncatedHash = hashBytes.sliceArray(0 until 16)

        // Encode the truncated hash in Base64 (URL-safe, without padding)
        val hashBase64 = Base64.encodeToString(truncatedHash, Base64.URL_SAFE or Base64.NO_WRAP)

        // Print the Base64-encoded hash
        println(hashBase64)
        Log.e("Code:" , hashBase64)
    }
python android kotlin hash sha
1个回答
0
投票

您正在获取 JSON 字符串的哈希值。 JSON 对象作为字符串的表示形式并未标准化,这样做会让您面临很大的风险。碰巧,Python 和 Kotlin 生成的 JSON 字符串是不同的:

由Python使用

json.dumps
生成:

{"address": {"city": "Wonderland", "street": "Rabbit Hole"}, "age": 25, "name": "Alice"}

由 Kotlin 使用

JSONObject.toString
制作:

{"address":{"city":"Wonderland","street":"Rabbit Hole"},"name":"Alice","age":25}

我假设您正在使用 JSON-Java 库中的

org.json.JSONObject
(如果您指定它将会有所帮助)。该库创建一个没有空格的字符串。可能还有其他 JSON 库会在冒号后创建一个空格,就像 Python 一样,但我不知道有哪一个。

手动在冒号后添加空格是错误的,因为这也会对属于数据一部分的冒号执行此操作,而您不想更改冒号。

更改 Python 的输出以匹配 Kotlin 的输出会更简单。您可以使用分隔符参数来执行此操作:

json.dumps(msg, ensure_ascii=False, sort_keys=True, separators=(',',':'))

当然,这意味着您必须重新散列服务器上的任何现有哈希值,以便它们不使用空格。

© www.soinside.com 2019 - 2024. All rights reserved.