如何在Python中生成ODIN-1

时间:2012-12-21 19:58:01

标签: android python encoding udid sha1

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

E.g。如何在Python中将此MAC转换为ODIN-1? “74e2f543d2ce”

提前致谢!

2 个答案:

答案 0 :(得分: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";

在python中:

>>> '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()

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

希望这有助于使我的回答更清晰。

答案 1 :(得分:1)

  

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

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

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

  

种子应该保持不变,不受操作系统返回的格式的影响。

     

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

     

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

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

因此,您可能需要生成6字节数组[0x74, 0xe2, 0xf5, 0x43, 0xd2, 0xce]的ODIN-1,而不是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'

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

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

  

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

规范说:

  

种子应该保持不变,不受操作系统返回的格式的影响。

回答你的第二个问题:

  

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

规范说:

  

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

     

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

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

iOS sample完全没有相关代码。它是向导生成的通用GUI应用程序,在#import "ODIN.h"中添加了textView.text = [ODIN1() lowercaseString];viewDidLoad。但是,ODIN.h文件以及相应的ODIN.mlibODIN.a或其他任何内容似乎都没有。 (从简短的一瞥project.pbxproj,显然应该有更多的文件,他们显然只是没有登记。)

Android sample确实有相关代码,但它显然违反了规范。它将ANDROID_ID作为Unicode字符串,然后将其编码为iso-8859-1 ,在结果字节上调用SHA-1,并从中生成十六进制摘要。文档明确指出要使用操作系统返回的操作系统值;代码Latin-1代之以编码。

另一方面,Windows sample似乎确实做了文档所说的内容 - 它将DeviceUniqueId作为byte[],并按原样使用它。 (但是,代码实际上不起作用,因为它使用的是过时的API调用,它抛出异常而不是返回byte[] ...)

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

更不用说Apple已经明确告诉人们不要使用基于MAC的任何东西来替换UDID,ODIN是基于MAC替换UDID的简单方法......