亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為類似憑證的行為制作最佳的偽隨機唯一代碼生成器

為類似憑證的行為制作最佳的偽隨機唯一代碼生成器

PHP
森林海 2022-01-24 10:49:11
我正在為 IT 技術服務開發一個簡單的管理系統。該系統有一個網站,客戶可以通過輸入他們的唯一代碼來檢查他們的訂單的當前狀態。當然,這段代碼必須是唯一的,并且希望不容易(手動)暴力破解。我正在考慮在“XKF-042”行的某處輸出,易于閱讀和寫下。問題出現在這些值的生成上:我可以使用純隨機數據并生成兩段代碼,但這迫使我檢查代碼是否已經存在,這感覺就像是資源的指數浪費。一個簡單的答案是從任意數字開始計數,比如“ABC-001”,然后加 1,因此不需要檢查該值是否已經存在。問題在于暴力破解的容易程度。任何人都可以檢查 ABC-XXX 并檢查最后一千個連續訂單。數學不是我的強項,但我知道必須有一個更優雅的解決方案來解決這個問題。我正在考慮為代碼的每一側生成每一個可能的排列并將它們打亂,所以我有一個看似隨機的配對列表可供讀取,并且可能每 1000 個代碼移動一次“代碼右側”列表。編輯:無法猜測代碼并不重要;除了訂單信息和成本外,輸出不會有任何個人信息。我可以使用 4x4 代碼(如“SJDM-4823”)使其“更強大”。
查看完整描述

2 回答

?
拉丁的傳說

TA貢獻1789條經驗 獲得超8個贊

好吧,我建議使用 LCG,Linear Congruential Generator。它有非常好的屬性——給定正確的常量集(赫爾-多貝爾定理)輸出唯一地覆蓋所有 2 32空間(或 64 位空間,但據我記得 PHP 只有 32 位整數)?;旧纤菑?[0...2 32 ) 間隔到另一個 [0...2 32 ) 間隔的一對一映射器。它可以以兩種方式使用


一、ID next = LCG(ID prev ),就像典型的隨機數生成器一樣?;蛘咧皇菑木€性遞增計數器 ID next = LCG(1, 2, ...) 中輸入它。您可以將整數轉換為 8 個符號 base-16 字符串,應該足夠好了。


沒有 PHP 代碼,有一個 python 代碼


import numpy as np


class LCG:


    UZERO: np.uint32 = np.uint32(0)

    UONE : np.uint32 = np.uint32(1)


    def __init__(self, seed: np.uint32, a: np.uint32, c: np.uint32) -> None:

        self._seed: np.uint32 = np.uint32(seed)

        self._a   : np.uint32 = np.uint32(a)

        self._c   : np.uint32 = np.uint32(c)


    def next(self) -> np.uint32:

        self._seed = self._a * self._seed + self._c

        return self._seed


    def seed(self) -> np.uint32:

        return self._seed


    def set_seed(self, seed: np.uint32) -> np.uint32:

        self._seed = seed


    def skip(self, ns: np.int32) -> None:

        """

        Signed argument - skip forward as well as backward


        The algorithm here to determine the parameters used to skip ahead is

        described in the paper F. Brown, "Random Number Generation with Arbitrary Stride,"

        Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in

        O(log2(N)) operations instead of O(N). It computes parameters

        A and C which can then be used to find x_N = A*x_0 + C mod 2^M.

        """


        nskip: np.uint32 = np.uint32(ns)


        a: np.uint32 = self._a

        c: np.uint32 = self._c


        a_next: np.uint32 = LCG.UONE

        c_next: np.uint32 = LCG.UZERO


        while nskip > LCG.UZERO:

            if (nskip & LCG.UONE) != LCG.UZERO:

                a_next = a_next * a

                c_next = c_next * a + c


            c = (a + LCG.UONE) * c

            a = a * a


            nskip = nskip >> LCG.UONE


        self._seed = a_next * self._seed + c_next



#%%

np.seterr(over='ignore')


a = np.uint32(1664525)

c = np.uint32(1013904223)

seed = np.uint32(1)


rng = LCG(seed, a, c)


print(rng.next())

print(rng.next())

print(rng.next())



查看完整回答
反對 回復 2022-01-24
?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

我寫的一篇文章包含有關唯一隨機標識符的建議。從您的問題來看,您似乎面臨以下困境:生成隨機唯一標識符——

  • 足夠長以至于難以猜測,但是

  • 足夠短,便于最終用戶輸入。

那篇文章中的建議解釋了如何生成唯一的隨機 ID(128 位或更長,使用加密 RNG,例如random_bytesbin2hexPHP 中)。但出于您的目的,生成的 ID 可能太長而不適合。有一些方法可以處理如此長的 ID,包括——

  1. 將 ID 劃分為可記憶的塊(例如:“374528294473”變為“374-538-294-473”),

  2. 將 ID 轉換為一系列容易記住的單詞(如比特幣的 BIP39),或

  3. 在 ID 的末尾添加一個所謂的“校驗和數字”以防止輸入錯誤。

在決定使用比該文章中的建議更短的 ID 之前,您應該嘗試 (1) 或 (2)。

此外,您的應用程序通常必須根據已生成的 ID 數據庫檢查 ID 的唯一性;但是,這種唯一性檢查可能會或可能不會成為您的應用程序的性能瓶頸,唯一的方法是嘗試并查看?;蛘?,您可以將 ID 表的記錄號(對于每條記錄應該是唯一的)包含在 ID 本身中。


如果訂單 ID 是唯一授予訪問該訂單信息的權限,則也可能存在嚴重的安全問題。理想情況下,應該有其他形式的授權,例如只允許登錄用戶或某些登錄用戶訪問與訂單 ID 關聯的訂單信息。另請參閱此問題。


查看完整回答
反對 回復 2022-01-24
  • 2 回答
  • 0 關注
  • 162 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號