希望有人能帮助我。
我想生成一个个人 ID。由于 Moodle 的插件,我有以下限制:
- ID不能超过9
- ID 只能包含数字 [0-9]
ID 不应是随机数。如果可能的话,我希望能够使用此人的一些基本信息重新创建它。
我的方法:
目前我执行以下步骤来生成 ID。
1) 我获取主键、名字和姓氏并进行 MD5 哈希。
USE `bpmspace_coms_v1`;
DELIMITER //
DROP PROCEDURE IF EXISTS demo_data;
//
CREATE PROCEDURE demo_data()
begin
DECLARE x SMALLINT DEFAULT 0;
while x < 100
do
SET @lastname = generate_lname();
SET @firstname = generate_fname();
INSERT INTO .`coms_participant` (`coms_participant_lastname`, `coms_participant_firstname`, `coms_participant_public`, `coms_participant_placeofbirth`, `coms_participant_birthcountry`) VALUES (@lastname, @firstname, '0', str_random('Cccc(4)'), str_random('Cccc(7)'));
SET @lastid = LAST_INSERT_ID();
INSERT INTO `coms_participant_identifier` (`coms_participant_id`, `coms_participant_matriculation`, `coms_participant_md5`) VALUES (@lastid, @lastid, md5(concat(@lastid,@firstname,@lastname)));
set x = x+1;
end while;
END;
//
DELIMITER ;
call demo_data()
2) 然后我剪切前 7 个十六进制值 (fffffff = 268.435.455 ) 并将它们转换为数字
UPDATE `coms_participant_identifier` set `coms_participant_matriculation` = CONV(SUBSTRING(coms_participant_md5,1,7),16,10) where true;
有没有更好的方法?您预计什么时候会发生碰撞?
谢谢你的帮助,
罗布
下面是涉及到的2个表的创建语句
CREATE TABLE `coms_participant` (
`coms_participant_id` int(11) NOT NULL AUTO_INCREMENT,
`coms_participant_lastname` varchar(60) DEFAULT NULL,
`coms_participant_firstname` varchar(60) DEFAULT NULL,
`coms_participant_public` tinyint(4) DEFAULT '0',
`coms_participant_placeofbirth` varchar(60) DEFAULT NULL,
`coms_participant_birthcountry` varchar(60) DEFAULT NULL,
`coms_participant_dateofbirth` date DEFAULT NULL,
`coms_participant_LIAM_id` int(11) NOT NULL,
PRIMARY KEY (`coms_participant_id`)
) ENGINE=InnoDB AUTO_INCREMENT=52807563 DEFAULT CHARSET=utf8;
CREATE TABLE `coms_participant_identifier` (
`coms_participant_identifier_id` int(11) NOT NULL AUTO_INCREMENT,
`coms_participant_id` int(11) NOT NULL,
`coms_participant_matriculation` double NOT NULL,
`coms_participant_md5` varchar(32) DEFAULT NULL,
PRIMARY KEY (`coms_participant_identifier_id`),
UNIQUE KEY `coms_participant_identifier_id_UNIQUE` (`coms_participant_identifier_id`)
) ENGINE=InnoDB AUTO_INCREMENT=229583147 DEFAULT CHARSET=utf8;
我使用来自 https://thecodecave.com/tag/mysql/ 的 generate_lname() 和 generate_fname() 和来自 http://moinne.com/blog/ronald/mysql/howto-generate-meaningful-test-data-using-a-mysql-function 的 str_random()
最佳答案
1) I take the primary key, the firstname and the lastname and do an MD5 hash.
如果您不必使用 MD5,请不要使用。它完全坏了。 SHA-1 也在崩溃。使用 SHA-256。虽然由于下一部分而有点没有实际意义......
I want to generate a personal ID. I have - due to a Plugin of Moodle - the following limitations:
- the ID must not be longer than 9
- the ID must contain only digits [0-9]
这很糟糕。这意味着只有 10 亿个可能的 ID,这可能看起来很多,但它非常小,大约 30 位。使用这么小的 key 空间,您将发生哈希冲突。您的实现仅使用其中的 28 个位,使其更小。别担心,这 2 位无关紧要。
当两个字符串具有相同的哈希时,就会发生哈希冲突。通常这不是问题,因为散列空间很大,但您的空间很小。例如,SHA-1 是 160 位或大 40 个数量级。 40 orders of magnitude is the difference between the size of a virus and the size of a planet.只有 10 亿种可能性,您很可能会发生碰撞,比您想象的可能性大得多。
您可能会想“如果我有 10 亿个 ID 并且我有 100 万用户,那么发生冲突的可能性只有 1/1000”,但事实并非如此。这被称为 the Birthday Problem它的漏洞被称为the Birthday Attack .长话短说,在大约 10,000 到 20,000 名用户处发生碰撞的几率为 50/50。
我使用 /usr/share/dict/words
运行了一个简短的模拟,并在 11371 个单词后发生了碰撞。
require "digest"
hashes = {}
count = 0
File.new("/usr/share/dict/words").each { |line|
line.chomp!
count += 1
hash = Digest::MD5.hexdigest(line)[0..6]
if hashes[hash]
puts "#{line} collides with #{hashes[hash]} after #{count} words: #{hash}"
end
hashes[hash] = line
}
aplasia collides with antefurcal after 11371 words: 7417bf5
circumvolant collides with angelicalness after 36704 words: d8ae33c
debord collides with Actinopteri after 49183 words: c43674a
dichromasy collides with acetolytic after 53190 words: 102ef7d
diplosphene collides with aruke after 54247 words: cdce4ec
divaricate collides with chemurgic after 56200 words: b7d936c
draftily collides with backvelder after 57533 words: dcb75a2
firefall collides with Cytophaga after 70180 words: ae25f13
...
这意味着您需要某种方式 resolving that collision .这意味着无法预测给定用户获得的哈希值,因为哈希值的顺序很重要。
对于如此小的 key 空间,某人通过蛮力生成有效 key 将相对简单。
鉴于如此小的键空间,我会问一些基本问题。
- 这真的是一个限制吗?
- 如果是这样,我真的需要这个插件吗?
- 为什么我需要能够重新创建他们的散列?
- 可以为它们分配一个像 UUID 这样的哈希值吗?
关于mysql - 可重复生成有限制的个人 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43198499/