0

我需要在 Python 中生成字符串的 ODIN-1。官方文档指定将SHA-1应用于输入字符串/标识符,但我不确定是否需要事先对其执行其他操作?另外,最终输出是 SHA-1 的十六进制摘要还是其他什么?

例如,如何在 Python 中将此 MAC 转换为 ODIN-1?“74e2f543d2ce”

提前致谢!

4

2 回答 2

1
from hashlib import sha1

def odin1(mac_addr):
    """SHA1 hexdigest of hex representaiton of MAC address"""
    to_hash ''.join([i.decode('hex') for i in mac_addr.split(':')])
    return sha1(to_hash).hexdigest()

>>> odin1('1a:2b:3c:4d:5e:6f')
'82a53f1222f8781a5063a773231d4a7ee41bdd6f'

让我们在您链接到的文档和我的答案之间逐行分解:

// NOTE: iOS returns MAC Address NOT a string, but a 6-byte array. 

// A human readable MAC Address may be represented as the following:

@"1a:2b:3c:4d:5e:6f";
@"1A2B3C4D5E6F";

在蟒蛇中:

>>> '1A'.decode('hex') == '1a'.decode('hex')
True

所以我们可以将给我们的字符串转换成更合适的格式(减少“标点符号和大写的任何歧义”):

>>> mac = "1a:2b:3c:4d:5e:6f".split(':')
>>> hex_mac = [m.decode('hex') for m in mac]
>>> hex_mac
['\x1a', '+', '<', 'M', '^', 'o']

我们可以将此列表视为一个字符串(就像我们使用字节数组一样)以从 SHA1 哈希函数中获得相同的结果。

当然,我们可以这样接收 MAC 地址:

>>> mac = '1A2B3C4D5E6F'
>>> hex_chunks = lambda s: [s[i: i+2] for i in range(0, len(s), 2)]
>>> [m.decode('hex') for m in hex_chunks(mac)]
['\x1a', '+', '<', 'M', '^', 'o']

因此,我们有责任适当地统一单个函数的输入,以便在所有可能的形式上运行。无论如何,我们的函数可以采用任何一种形式,最终结果才是最重要的:

>>> sha1(''.join(['\x1a', '+', '<', 'M', '^', 'o'])).hexdigest()

将产生正确的哈希(根据您发布的链接)。

希望这有助于使我的答案更清楚。

于 2012-12-21T20:14:21.750 回答
1

我需要在 Python 中生成字符串的 ODIN-1。

不,你没有,不是根据文档。

您生成 802.11 MAC 地址、ANDROID_ID 或 DeviceUniqueID 的 ODIN-1。一些相关的引用:

种子应该与操作系统返回的格式保持不变。

注意:iOS 返回的 MAC 地址不是字符串,而是图表下方的 6 字节数组。

... 将其表示为原始字节数组可防止标点符号和大写的任何歧义:

而 IIRC,ANDROID_ID是一个 64 位整数,既不是 MAC 也不是字符串。(我不知道DeviceUniqueId在 Windows Phone 上。)

因此,您可能需要生成 6 字节数组的 ODIN-1 [0x74, 0xe2, 0xf5, 0x43, 0xd2, 0xce],而不是 12 字符的字符串"74e2f543d2ce"。该示例展示了如何在 Objective-C 中做到这一点;在 Python 中,它是:

mac = bytes([0x74, 0xe2, 0xf5, 0x43, 0xd2, 0xce])

或者,由于您的问题指定了 Android,因此您可能根本不想要任何格式的 MAC 地址……但我认为这只是一个错误的标签,并且您使用的是 iOS,并且确实想要 MAC 地址。

你是怎样做的?

散列步骤:通过 SHA-1 散列函数传递标识符种子。

在 Python 中,这是:

hash = hashlib.sha1(mac)

生成的消息摘要是 ODIN-1。

在 Python 中,这是:

digest = hash.hexdigest()

把它放在一起:

hashlib.sha1(bytes([0x74, 0xe2, 0xf5, 0x43, 0xd2, 0xce])).hexdigest()

结果是“40 个小写字符串”,正如文档所说的那样:

'10f4ab0775380aceaca5a2733604efa6d6364b08'

此外,如果您正在寻找关于发布在 wiki 页面上的初步规范的说明,您为什么要在 SO 上询问它而不是在该页面上发表评论?

要回答您的第一个具体问题:

我不确定是否需要事先对其执行其他操作?

规范说:

种子应该与操作系统返回的格式保持不变。

回答你的第二个:

另外,最终输出是 SHA-1 的十六进制摘要还是其他什么?

规范说:

生成的消息摘要是 ODIN-1。

// 此哈希的格式应为 40 个小写字符串:

同时,项目附带了示例代码(正如您所期望的那样,因为它位于 googlecode 中)……但这并没有那么有用。

iOS 示例完全缺少相关代码。它是由向导生成的通用 GUI 应用程序#import "ODIN.h"textView.text = [ODIN1() lowercaseString];viewDidLoad. 但是那个ODIN.h文件,以及相应的ODIN.morlibODIN.a或任何东西似乎都不在任何地方。(简要浏览一下project.pbxproj,显然应该有更多文件,他们显然只是没有签入。)

Android 示例确实有相关代码,但它显然违反了规范。它获取ANDROID_IDUnicode 字符串,然后将其编码为 iso-8859-1,在结果字节上调用 SHA-1,并从中生成十六进制摘要。文档明确表示要完全按照操作系统返回的方式使用操作系统值;代码 Latin-1 对其进行编码。

另一方面,Windows sample 似乎确实像文档所说的那样 - 它获取 DeviceUniqueId 作为 a ,并按byte[]原样使用它。(然而,代码实际上并不能工作,因为它使用了一个过时的 API 调用,它会抛出一个异常而不是返回一个byte[]......)

在这一点上,我不得不问你为什么首先要遵循这个规范。如果您尝试与其他人的代码进行互操作,您可能会关心该代码正在使用哪种相互矛盾的方式来解释此规范,而不是试图猜测设计者的意图。

更何况苹果已经明确告诉人们不要使用任何基于 MAC 的东西来代替 UDID,而 ODIN 是一个基于 MAC 来代替 UDID 的琐碎的东西……</p>

于 2012-12-21T20:14:25.747 回答