2012-10-16 108 views
0

當用戶在我的網站上創建訂單時,訂單需要一個在應用程序中應該是唯一的代碼。我不想使用GUID,因爲它們長而笨拙 - 我只想要一個8個字符的字母數字代碼或其他東西。隨機字符串分開數據庫?

我認爲最好預先生成這些代碼,以便在運行時代碼不會卡住,尋找獨特的東西。

此外,我正在考慮將這些代碼放入一個單獨的數據庫中,以便備份和移動我的主數據庫不會涉及隨機字符串的隨機混洗 - 將使用的值複製到訂單表中主數據庫。

這聽起來像個好主意嗎?

回答

1

不需要數據庫。加密會給你一組隨機的唯一數字。 DES使用64位塊,所以通過加密0,1,2,3 ...,你將得到一組隨機出現的64位數字。

沒有32位塊大小的標準密碼,但是你可以自己寫一個簡單的Feistel cypher(見下面)或者使用具有可變塊大小的Hasty布丁密碼。

/** 
* IntegerPerm is a reversible keyed permutation of the integers. 
* This class is not cryptographically secure as the F function 
* is too simple and there are not enough rounds. 
* 
* @author rossum 
*/ 
public final class IntegerPerm { 
    ////////////////// 
    // Private Data // 
    ////////////////// 

    /** Non-zero default key, from www.random.org */ 
    private final static int DEFAULT_KEY = 0x6CFB18E2; 

    private final static int LOW_16_MASK = 0xFFFF; 
    private final static int HALF_SHIFT = 16; 
    private final static int NUM_ROUNDS = 4; 

    /** Permutation key */ 
    private int mKey; 

    /** Round key schedule */ 
    private int[] mRoundKeys = new int[NUM_ROUNDS]; 

    ////////////////// 
    // Constructors // 
    ////////////////// 
    public IntegerPerm() { this(DEFAULT_KEY); } 

    public IntegerPerm(int key) { setKey(key); } 


    //////////////////// 
    // Public Methods // 
    //////////////////// 
    /** Sets a new value for the key and key schedule. */ 
    public void setKey(int newKey) { 
     assert (NUM_ROUNDS == 4) : "NUM_ROUNDS is not 4"; 
     mKey = newKey; 

     mRoundKeys[0] = mKey & LOW_16_MASK; 
     mRoundKeys[1] = ~(mKey & LOW_16_MASK); 
     mRoundKeys[2] = mKey >>> HALF_SHIFT; 
     mRoundKeys[3] = ~(mKey >>> HALF_SHIFT); 
    } // end setKey() 

    /** Returns the current value of the key. */ 
    public int getKey() { return mKey; } 

    /** 
    * Calculates the enciphered (i.e. permuted) value of the given integer 
    * under the current key. 
    * 
    * @param plain the integer to encipher. 
    * 
    * @return the enciphered (permuted) value. 
    */ 
    public int encipher(int plain) { 
     // 1 Split into two halves. 
     int rhs = plain & LOW_16_MASK; 
     int lhs = plain >>> HALF_SHIFT; 

     // 2 Do NUM_ROUNDS simple Feistel rounds. 
     for (int i = 0; i < NUM_ROUNDS; ++i) { 
      if (i > 0) { 
       // Swap lhs <-> rhs 
       final int temp = lhs; 
       lhs = rhs; 
       rhs = temp; 
      } // end if 
      // Apply Feistel round function F(). 
      rhs ^= F(lhs, i); 
     } // end for 

     // 3 Recombine the two halves and return. 
     return (lhs << HALF_SHIFT) + (rhs & LOW_16_MASK); 
    } // end encipher() 


    /** 
    * Calculates the deciphered (i.e. inverse permuted) value of the given 
    * integer under the current key. 
    * 
    * @param cypher the integer to decipher. 
    * 
    * @return the deciphered (inverse permuted) value. 
    */ 
    public int decipher(int cypher) { 
     // 1 Split into two halves. 
     int rhs = cypher & LOW_16_MASK; 
     int lhs = cypher >>> HALF_SHIFT; 

     // 2 Do NUM_ROUNDS simple Feistel rounds. 
     for (int i = 0; i < NUM_ROUNDS; ++i) { 
      if (i > 0) { 
       // Swap lhs <-> rhs 
       final int temp = lhs; 
       lhs = rhs; 
       rhs = temp; 
      } // end if 
      // Apply Feistel round function F(). 
      rhs ^= F(lhs, NUM_ROUNDS - 1 - i); 
     } // end for 

     // 4 Recombine the two halves and return. 
     return (lhs << HALF_SHIFT) + (rhs & LOW_16_MASK); 
    } // end decipher() 


    ///////////////////// 
    // Private Methods // 
    ///////////////////// 

    // The F function for the Feistel rounds. 
    private int F(int num, int round) { 
     // XOR with round key. 
     num ^= mRoundKeys[round]; 
     // Square, then XOR the high and low parts. 
     num *= num; 
     return (num >>> HALF_SHIFT)^(num & LOW_16_MASK); 
    } // end F() 

} // end class IntegerPerm 
+0

難道這不會導致重複的隨機數? –

+0

不可以。因爲它是一種加密,它是可逆的,因此沒有重複。不同的輸入將總是*導致不同的輸出,只要您使用相同的密鑰即可。塊密碼(這是什麼)是塊的所有可能值的置換。域和範圍是相同的大小,所以沒有重複和沒有值遺漏。堅持一個單一的鍵值,並加密0,1,2,3,...按順序沒有重複和輸出保證永遠不會重複,直到你溢出回到0. – rossum

+0

聽起來不錯。一個問題是我已經在我的數據庫中預先生成了隨機訂購代碼幾年。所以我認爲我需要改變格式,否則這種機制可能會造成重複。如果密鑰和代碼也被泄露,也會出現同樣的問題。 (這個想法部分是爲了阻止用戶制定出多少訂單。) –