可重复生成具有限制的个人ID

时间:2017-04-04 04:49:47

标签: mysql hash

希望,有人可以帮助我。

我想生成一个个人ID。由于Moodle的插件,我有以下限制:

  • ID不得超过9
  • ID必须仅包含数字[0-9]

ID不应该是随机数。如果可能的话,我希望能够通过该人的一些基本信息重新创建它。

我的方法:

目前,我执行以下步骤来生成ID。

1)我接受主键,firstname和lastname并执行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 个答案:

答案 0 :(得分:1)

  

1)我接受主键,firstname和lastname并执行MD5哈希。

如果您不必使用MD5,请不要这样做。它完全坏了。 SHA-1也在摇摇欲坠。使用SHA-256。虽然因为下一部分而有点没有实际意义......

  

我想生成一个个人ID。由于Moodle的插件,我有以下限制:

     
      
  • ID不得超过9
  •   
  • 该ID必须仅包含数字[0-9]
  •   

这很糟糕。这意味着只有10亿个可能的ID可能看起来很多,但它非常小,大约30位。使用小的密钥空间发生哈希冲突。您的实现仅使用其中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亿种可能性,你很可能会发生碰撞,这比你想象的要大得多。

您可能会认为&#34;如果我有10亿个ID并且我有100万用户,那么只有1/1000的碰撞机会&#34;但它并没有这样做。这称为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的某种方式。这意味着无法预测给定用户获得的哈希值,因为它们被散列的顺序很重要。

有了这么小的键空间,人们通过蛮力制作有效的密钥会相对简单。

考虑到这么小的密钥空间,我会问一些基本的问题。

  • 这真的是一个限制吗?
    • 如果是这样,我真的需要这个插件吗?
  • 为什么我需要能够重新创建他们的哈希?
    • 是否可以像UUID一样分配哈希值?