2017-04-04 55 views
1

希望有人能幫助我。可重複生成有限制的個人ID

我想生成一個個人ID。餘有 - 由於的Mo​​odle的插件 - 的folwowing限制:

  • 的ID必須不大於9
  • 更長的ID必須只containe數字[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個hexvalues(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/ 和str_random(generate_lname()generate_fname())從http://moinne.com/blog/ronald/mysql/howto-generate-meaningful-test-data-using-a-mysql-function

+0

「*我希望能夠與人的一些基本的相關信息重新創建它。*」我問的第一個問題是:爲什麼?這似乎是一個奇特的特徵。 「*由於Moodle的插件[我有]以下限制*」你確定嗎?也許你應該問一個關於這個限制的問題。 – Schwern

回答

1

1)我把主鍵,名字和姓氏,並做一個MD5散列。

如果您不必使用MD5,請不要。它完全破碎。 SHA-1也崩潰了。使用SHA-256。雖然由於下一個部分而沒有實際意義...

我想生成一個個人ID。餘有 - 由於的Mo​​odle的插件 - 以下限制:

  • 的ID必須不大於9
  • 更長的ID必須只包含數字[0-9]

這很糟糕。這意味着只有10億個可能的ID可能看起來很多,但它非常小,大約30位。有一個關鍵空間很小,你有散列衝突。你的實現只使用了28個這樣的位,使它更小。別擔心,這兩個比特無關緊要。

當兩個字符串具有相同的散列值時發生散列衝突。通常這不是問題,因爲哈希空間非常大,但是你的非常小。例如,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。長話短說,你有50/50的機會在大約1萬到2萬用戶的碰撞。

我用/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一樣分配散列?
+0

我會將問題轉移到評論中,因爲答案只是答案。 – Shadow

+0

@Shadow有時答案在於質疑這個問題。 – Schwern

+0

@Schwern 感謝您的解釋和你的問題 - 這些問題是 - 是的 - 是的 - 我必須考慮 - UUID太長 看起來我只是在創建數據時使用「INT」和「自動增量」 –