UUID简介

UUID简介

什么是UUID

  UUID即Unique Device Identifier,唯一设备识别符。iOS上的IDFA/IDFV/OpenUDID/macho-uuid,都采用UUID4格式。UUID是RFC定义的高随机性的标识字符串,结构说明在https://www.ietf.org/rfc/rfc4122.txt

struct rfc_uuid {
    uint32_t  time_low;
    uint16_t  time_mid;
    uint16_t  time_hi_and_version;          // v=(v&0xfff)|0x400
    uint8_t   clock_seq_hi_and_reserved;    // v=(v&0x3f)|0x80
    uint8_t   clock_seq_low;
    uint8_t   node[6];
};

  UUID目前有多个版本,包括UUID1/UUID3/UUID4/UUID5,一个典型的UUID4串ef9cbf1e-3560-4555-b1aa-81bf4773cd9e。注意uuid4的结构和其他类型不同,有些bit位固定为0或1,其他bit位完全随机(********-****-4***-(8|9|a|b)***-************),因此如果用上面的结构体解析UUID4串是没有意义的。正如rfc所述:

4.4.  Algorithms for Creating a UUID from Truly Random or
      Pseudo-Random Numbers
   The version 4 UUID is meant for generating UUIDs from truly-random or
   pseudo-random numbers.
   The algorithm is as follows:
   o  Set the two most significant bits (bits 6 and 7) of the
      clock_seq_hi_and_reserved to zero and one, respectively.
   o  Set the four most significant bits (bits 12 through 15) of the
      time_hi_and_version field to the 4-bit version number from
      Section 4.1.3.
   o  Set all the other bits to randomly (or pseudo-randomly) chosen
      values.

  使用ObjC和Python生成uuid4

// Objective-C生成UUID
NSString* myuuid = NSUUID.UUID.UUIDString;
// Python生成UUID
import uuid
myuuid = str(uuid.uuid4())

  讲一个趣事,之前一个朋友不知道IDFA用UUID4格式生成,用Hook修改系统IDFA获取的部分,改为纯随机,结果跑起来莫名其妙就是崩。。。。改机软件模拟的UUID均为上述方式生成。

怎样生成相对固定的uuid4

  此需求看似有点奇怪,但是其实是有用的。在模拟参数的时候如果uuid需要和其他参数配套,那么固定一个参数去生成uuid就十分必要了。这里提供一个使用时间戳生成uuid4的实例

void uuid4_format(unsigned char* buf) { // bufsize=16
    struct rfc_uuid* uuid = (struct rfc_uuid*)buf;
    uuid->time_hi_and_version = (uuid->time_hi_and_version & 0xff0f) | 0x0040;
    uuid->clock_seq_hi_and_reserved = (uuid->clock_seq_hi_and_reserved & 0x3f) | 0x80;
}

NSString* uuid4_init_with_ts(time_t ts) {
    unsigned char uuid[16];
    if (ts == 0) {
        ts = time(0);
    }
    ((uint32_t*)uuid)[0] = crc32_for_byte(ts & 0xff);
    ((uint32_t*)uuid)[1] = crc32_for_byte((ts >> 8) & 0xff);
    ((uint32_t*)uuid)[2] = crc32_for_byte((ts >> 16) & 0xff);
    ((uint32_t*)uuid)[3] = crc32_for_byte((ts >> 24) & 0xff);
    uuid4_format(uuid);
    NSUUID* nsuuid = [[NSUUID alloc] initWithUUIDBytes:uuid];
    return nsuuid.UUIDString;
}