Format-Preserving

使用 FPE 處理較長字元串的好方法是什麼?

  • May 6, 2015

在試驗這個基於 FE1 的 FPE 時

http://botan.randombit.net/manual/fpe.html

(實際上是它在 C# 中的一個埠)我發現當字元串長度太長(字元數 N)時,它基本上是為了拋出異常而設計的

所以模數的字節數組被限制在這個值

   // Normally FPE is for SSNs, CC#s, etc, nothing too big
   private const int MAX_N_BYTES = 128 / 8;

這是我們檢查字節數組長度的地方

   /// <summary>
   /// A simple round function based on HMAC(SHA-256)
   /// </summary>
   private class FPE_Encryptor
   {
       private System.Security.Cryptography.HMACSHA256 mac;

       private byte[] mac_n_t;

       internal FPE_Encryptor(byte[] key,
                        BigInteger n,
                        byte[] tweak)
       {
           mac = new System.Security.Cryptography.HMACSHA256(key);

           mac.Initialize();

           byte[] n_bin = n.encode();

           if (n_bin.Length > MAX_N_BYTES)
               throw new Exception("N is too large for FPE encryption");

           var ms = new MemoryStream();

           ms.update_be(n_bin.Length);
           ms.update(n_bin);

           ms.update_be(tweak.Length);
           ms.update(tweak);

           mac_n_t = mac.ComputeHash(ms.ToArray());
       }

       internal BigInteger F(int round_no, BigInteger R)
       {
           byte[] r_bin = R.encode();
           var ms = new MemoryStream();
           ms.update(mac_n_t);
           ms.update_be(round_no);

           ms.update_be(r_bin.Length);
           ms.update(r_bin);

           byte[] X = mac.ComputeHash(ms.ToArray()).Reverse().ToArray();
           var X_ = new byte[X.Length + 1];
           X.CopyTo(X_, 0);
           X_[X.Length] = 0; // guarantee a positive interpretation
           BigInteger ret = new BigInteger(X_);
           return ret;
       }
   }

但是說我想編碼一個像“Asddasdasdasdasdasdasdasd”這樣的長字元串

我在 Base 52 中,所以我的模數非常大 7944811378381908491977011631194721432371200

使用轉換為字節數組後

   internal static byte[] encode(this BigInteger n)
   {
       if (n.IsZero) return new byte[0];
       else return n.ToByteArray().Reverse().SkipWhile(h => h == 0).ToArray();
   }

給出的長度為 18,大於最大值 16。

有沒有人建議如何處理要加密的明文中的大量字元?如果字元串長度超過最大值,我正在考慮將其切成碎片並加密碎片。這可以接受嗎?

FE1 沒有固有的最大長度;該限制是由實施強加的。第一個明顯的建議是使用沒有這種限制的替代實現。

現在,讓我們假設這不是一個可行的選擇;你必須使用這個特定的 FE1 實現。

現在,將明文分割成片段並分別加密的問題在於,如果有人只修改其中一個加密片段,他們將修改解密後的明文的一部分,但不是全部。

我會建議一種解決方法,使用 FE1 還提供的“調整”。這個“調整”值是修改數據加密方式的 FE1 算法的另一個輸入;它不假定是秘密的,但不會同時呈現給加密和解密。它的目的是將密文綁定到特定的上下文(以便密文不能在任何其他上下文中使用)。

這個想法是拆分明文,並分別加密每一個;但是,我們將消息的其餘部分用作調整。例如,如果我們將明文分成三個部分 $ P_1, P_2, P_3 $ ,我們生成密文為:

$$ C_1 = FE1_k( P_1, 0 || P_2 || P_3 ) $$ $$ C_2 = FE1_k( P_2, 1 || C_1 || P_3 ) $$ $$ C_3 = FE1_k( P_3, 2 || C_1 || C_2 ) $$ (在哪裡 $ FE1_k(A, B) $ 意思是“ $ FE1 $ 的加密 $ A $ , 使用鍵 $ k $ , 帶有微調 $ B $ ).

一般來說,密文 $ C_i $ 定義為 $ C_i = FE1_k( P_i, i || C_1 || C_2 || … || C_{i-1} || P_{i+1} || P_{i+2} || … || P_n ) $

要解密,您只需按相反的順序執行操作:

$$ P_3 = FE1^{-1}_k( C_3, 2 || C_1 || C_2 ) $$ $$ P_2 = FE1^{-1}_k( C_2, 1 || C_1 || P_3 ) $$ $$ P_1 = FE1^{-1}_k( C_1, 0 || P_2 || P_3 ) $$ 通過將每個密文塊綁定到前面和後面的塊,您可以防止任何人修改部分消息而不影響所有內容。這確實假設您的 FE1 實現允許長時間的調整。

引用自:https://crypto.stackexchange.com/questions/25461