• Linux生成UUID的算法方式(序列号C/C++代码实现)


    Linux中想获取机器的唯一标识(UUID),只需要在命令行中输入uuid就可以看到类似格式为:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16)机器标识,通过该唯一标识生成注册码/序列号。有了设备的唯一编号,我们就可以实现更好的软件的授权机制,还可以利用它来限制客户端软件访问后台服务的权限,从而提高系统的安全性。

    使用UUID 的目的


    使用 UUID 的主要原因之一是不需要集中权限来管理它们(尽管一种格式使用 IEEE 802 节点标识符,其他格式则不使用)。因此,按需 生成可以完全自动化,并用于各种目的。。。

    生成 UUID 的几种算法

    UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。

    1.利用 802 MAC 地址的唯一值来保证唯一性。
    2.种使用伪随机数生成器。
    3.种使用加密哈希和应用程序提供的文本字符串。
    4.当前日期和时间。

    因此,根据此处的机制 生成的 UUID 将与所有其他已分配或将要分配的 UUID 不同。

    UUID 字符串表示的正式定义
    UUID 根据以下算法生成:

    time_low 字段设置为以相同的重要性顺序等于时间戳的最低有效 32 位(位 0 到 31)。
    time_mid 字段设置为等于时间戳中的第 32 位到第 47 位。
    time_hi_and_version 字段的 12 个最低有效位(位 0 到 11)设置为等于时间戳中的位 48 到 59,以相同的重要性顺序。
    time_hi_and_version 字段的四个最高有效位(位 12 到 15)设置为与正在创建的 UUID 版本对应的 4 位版本号。
    clock_seq_low 字段设置为8 个最低有效位(位 0 到 7)的时钟序列以相同的重要性顺序。
    clock_seq_hi_and_reserved 字段的6 个最低有效位(0 到5 位)设置为时钟序列的6 个最高有效位(8 到13 位)。
    clock_seq_hi_and_reserved 的两个最高有效位(位6 和7)分别设置为零和一。
    将节点字段设置为 48 位 IEEE 地址,其重要性顺序与地址相同。

    什么是 machine-id


    man 手册译文是这样讲的:

    etc/machine-id 文件包含一个 在安装或首次启动操作系统时生成的、专属于本系统的、独一无二的"machine ID"。 "machine ID"是一个32字符长度的十六进制小写字母字符串,并以换行符结尾。 其本质是一个128位二进制整数的16进制表示。 注意,"machine ID"不能为全零值。

    在这里插入图片描述

    “machine ID"通常在系统安装或首次启动时从一个随机数源生成, 并且之后无论经过多少次开关机,也一直保持不变。 另一方面,对于无状态系统,如果有必要,将在系统启动的早期自动随机生成一个"machine ID”。

    每台机器都应该具有一个独一无二的非空"machine ID"。 为了达到这个目标,可以使用多种不同的方法初始化 /etc/machine-id 文件。一般来说, /etc/machine-id 应该 在操作系统安装过程中完成初始化。

    linux 的uuid码

    linux的uuid码也是有内核提供的,在/proc/sys/kernel/random/uuid这个文件内。其实,random目录,里面还有很多其它文件,都与生成uuid有关系的。

    基于当前时间的 UUID

    ..
    int main (int argc, char **argv) {
      
      ...
    
    	struct timeval tv0;
    	gettimeofday(&tv0, NULL);
    	time_t t0 = (time_t)tv0.tv_sec;
    	struct tm *tm0 = gmtime(&t0);
    	char buffer[33];
    	// 00000000-yyyy-mmmm-dddd-hhhhhhnnnnnn
    	srand((unsigned int)tv0.tv_usec/100);
    	sprintf(buffer,"%04x%02x%02x%04x%06x%06x%02x%02x%02x",
    		(int)tm0->tm_year+1900, (int)tm0->tm_mon, (int)tm0->tm_mday, 0,
    		(int)tv0.tv_sec, (int)tv0.tv_usec, rand()%255, rand()%255, rand()%255);
    	
    	...
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    uuidtime 是一个 Linux 程序,用于生成基于当前时间的 UUID自纪元(1970)以来的秒数和微秒数。当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。

    UUID的弊端


    如果将一台机器的UUID拷贝到另一台机器,就类似修改Mac地址的方法达到欺骗的目的。

    根据型号和 MAC 地址的低 24 位构建序列号

    int get_sn(char *iface, int model_id, unsigned int *si)
    {
    	unsigned char mac_address[6];
    	unsigned char sn[4] = {0};
    	struct ifreq ifr;
    
    	assert(iface);
    	assert(si);
    
    	int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    	if (sock == -1) {
    		fprintf(stderr, "couldn't create socket\n");
    		return -1;
    	};
    
    	strcpy(ifr.ifr_name, iface);
    	if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
    		fprintf(stderr, "couldn't ioctl iface: %s\n",
    		        ifr.ifr_name);
    		return -1;
    	}
    
    	if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
    		memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
    		memcpy(sn, &mac_address[3], 3);
    
    		*si = sn[2] + 256 * sn[1] + 65536 * sn[0];
    		*si = *si / 4 - 64;
    		*si = *si + model_id;
    		return 0;
    	}
    	return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    运行结果:
    在这里插入图片描述

    总结

    UUID 是通用唯一识别码。由 32 位 16 进制数字组成,可以是纯 32 位 16 进制数字,也可以包含连接线(形式为 8-4-4-4-12),更新详细信息请参考RFC4122。

    欢迎关注微信公众号【程序猿编码】,需要 UUID完整源码 的添加本人微信号(c17865354792)

    参考:RFC 4122

  • 相关阅读:
    视频播放器的技术组成
    Vue之混入(mixin)
    38.CSS文本动画效果
    【从瀑布模式到水母模式】ChatGPT如何赋能软件研发全流程
    oracle10数据库迁移
    linux入门到精通-第一章-文件目录
    SpringBoot AOP + Redis 延时双删功能实战
    Sass 和 SCSS
    【备忘】git常用命令
    单链表排序
  • 原文地址:https://blog.csdn.net/chen1415886044/article/details/126355751