我可以使用什么算法为唯一的mac地址生成48位散列? [英] What algorithm can I use to generate a 48-bit hash for unique mac addresses?

查看:1080
本文介绍了我可以使用什么算法为唯一的mac地址生成48位散列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有简单的使用散列算法来生成48位散列?我需要从唯一的输入字符串生成唯一的MAC地址。这里没有安全问题,只是将它映射到MAC地址空间(即48位)的问题。

我想到了CRC32,它只有32位和简单(每个Linux上都有 cksum ),并且将它们用于较低的32位,但如果超过几个主机,则冲突相当高。

如果我能得到48位散列值,我可以屏蔽8个最高有效位中的第二个最低有效位,以确保它是本地管理地址。相反,我可以使用更长的哈希算法(MD5,SHA1等),只需要48个最重要的或最少的重要的一点。

有没有简单的方法来做到这一点?



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

解决方案

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

我只需要一个只有48位的序列号,用于没有非易失性存储器的定制电路板。

该板采用STM32处理器,具有96位的唯一ID(STM32_UUID)。

这是完整的C代码:

  #define STM32_UUID((uint8_t *)0x1FFFF7E8)

// board SN 48位
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;
//
返回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;
情况6:v ^ =(uint64_t)pos2 [5]<< 40;
情况5:v ^ =(uint64_t)pos2 [4]<< 32;
情况4:v ^ =(uint64_t)pos2 [3]<< 24;
情况3:v ^ =(uint64_t)pos2 [2]<< 16;
情况2:v ^ =(uint64_t)pos2 [1]<< 8;
案例1:v ^ =(uint64_t)pos2 [0];
h ^ = mix(v);
h * = m;
}

return mix(h);
}

我在一批约200个单元(板)上测试了这个解决方案,是绝对没有问题,没有冲突。

我见过很多人有这个问题,当他们需要一个较小的设备ID,以某种方式来源于一个大的独特单位序列号。


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


Is there any simple to use hashing algorithm to generate a 48-bit hash? I need to generate unique MAC addresses from unique input strings. There are no security issues here, just a question of mapping it to MAC address space (which is 48 bits).

I thought about CRC32, which is just 32 bits and easy (and cksum is on every Linux), and use them for the lower 32 bits, but the collisions are pretty high if it is more than a few hosts.

If I could get 48 bit hash, I could mask the second least significant bit of the 8 most significant bits to ensure it is a Locally Administered Address. The loss of a single bit is minor.

Conversely, I could use a longer hashing algorithm (MD5, SHA1, etc.) and just take the 48 most significant or least significant bits.

Is there a simple way to do this?

My preference is command-line utility, but if I have to write short python or similar, no big deal.

解决方案

After 2 years, here's an idea, in a real application (very close to what you needed).
I just needed a serial number of only 48 bits for a custom board that doesn't have a non-volatile memory.
The board features a STM32 processor that has an unique ID of 96 bits (STM32_UUID).
Here is the complete C code:

#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);
}

I tested this solution on a batch of about 200 units (boards) and there was absolutely no problem, no conflicts.
I've seen a lot of people having this issue, when they needed a smaller device ID that somehow originates from a large unique unit serial number.

Alternatively, you may search for an implementation of Bobcat 48 bit hash.

这篇关于我可以使用什么算法为唯一的mac地址生成48位散列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆