使用 FPE 處理較長字元串的好方法是什麼?
在試驗這個基於 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 實現允許長時間的調整。