我可以使用什么算法为唯一的mac地址生成48位哈希?

时间:2015-08-27 15:03:47

标签: linux hash mac-address

是否有任何简单易用的哈希算法来生成48位哈希?我需要从唯一的输入字符串生成唯一的MAC地址。这里没有安全问题,只是将其映射到MAC地址空间(48位)的问题。

我想过CRC32,它只有32位且很容易(并且每个Linux上都有cksum),并将它们用于低32位,但如果它不止一些,那么碰撞就相当高了主机。

如果我能得到48位散列,我可以屏蔽8个最高有效位的第二个最低有效位,以确保它是一个本地管理地址。单个位的丢失很小。

相反,我可以使用更长的散列算法(MD5,SHA1等),只取48个最重要或最不重要的位。

有一种简单的方法吗?

我的偏好是命令行实用程序,但如果我必须写短python或类似的,没什么大不了的。

1 个答案:

答案 0 :(得分:2)

2年后,这是一个想法,在一个真实的应用程序中(非常接近你需要的)。

对于没有非易失性存储器的自定义电路板,我只需要48位的序列号。该板具有STM32处理器,其唯一ID为96位(STM32_UUID)。

以下是完整的C代码:

#define STM32_UUID                      ((uint8_t*)0x1FFFF7E8)

// board SN 48 bit
static uint8_t BoardSerial[6]; 

void setBoardSerial(void)
{
  uint64_t hash = fastHash64(STM32_UUID, 12, 1234554321);
  memcpy(BoardSerial, &hash, 6);
}

static inline uint64_t mix(uint64_t h)
{
    h ^= h >> 23;
    h *= 0x2127599bf4325c37ULL;
    h ^= h >> 47;
    //
    return h;
}

uint64_t fastHash64(const void * buf, size_t len, uint64_t seed)
{
    const uint64_t m = 0x880355f21e6d1965ULL;
    const uint64_t * pos = (const uint64_t*)buf;
    const uint64_t * end = pos + (len / 8);
    const unsigned char * pos2;
    uint64_t h = seed ^ (len * m);
    uint64_t v;

    while(pos != end)
    {
        v  = *pos++;
        h ^= mix(v);
        h *= m;
    }

    pos2 = (const unsigned char*)pos;
    v = 0;

    switch(len & 7)
    {
        case 7: v ^= (uint64_t)pos2[6] << 48;
        case 6: v ^= (uint64_t)pos2[5] << 40;
        case 5: v ^= (uint64_t)pos2[4] << 32;
        case 4: v ^= (uint64_t)pos2[3] << 24;
        case 3: v ^= (uint64_t)pos2[2] << 16;
        case 2: v ^= (uint64_t)pos2[1] << 8;
        case 1: v ^= (uint64_t)pos2[0];
                h ^= mix(v);
                h *= m;
    }

    return mix(h);
}

我在一批约200个单位(板)上测试了这个解决方案,绝对没有问题,没有冲突。我看到很多人遇到这个问题,当他们需要一个较小的设备ID时,它会以某种方式来自一个大的唯一单元序列号。

或者,您可以搜索 Bobcat 48位哈希的实现。