相同明文的RSA不同密文
一般的
我的目標是加密一些字元串並將它們儲存在數據庫中。
我在 Go (Golang) 中使用 RSA OAEP:
rsa.EncryptOAEP(sha256.New(), rng, rsaPublickey, plaintext, nil) rsa.DecryptOAEP(sha256.New(), rng, rsaPrivatekey, ciphertext, nil)
我生成了一個 4096 位的公鑰/私鑰對。
我對 RSA 的理解非常基礎。我閱讀了一些關於堆棧溢出的類似問題,這些問題說 RSA OAEP 添加了填充以確保為相同的明文生成不同的密文以實現安全目的。
我對使用 AES 更有信心,因為如果您提供相同的對稱密鑰和相同的初始化向量,您將始終獲得相同的密文。
PS:我知道 RSA 和 AES 在通過網路發送數據時有不同的案例,我不應該把它們一視同仁,但對於我個人的案例,我想用它們來加密/解密字元串。
問題
- 由於為相同的明文生成了不同的密文,是否可以保證我將來能夠解密這些 RSA OAEP 密文?
實現改變,使用新的庫、函式和新版本的程式語言執行時等。
只要我可以從密文中獲取明文,我對將用於解密(Go、Java、Python、openssl ……)的 RSA OAEP 實現漠不關心。
Go 文件說
Encryption and decryption of a given message must use the same hash function
。在我的例子中,這個雜湊函式是 SHA256。此外,Go 文件說
The random parameter is used as a source of entropy to ensure that encrypting the same message twice doesn't result in the same ciphertext.
我還沒有看到其他程式語言中使用的這個隨機參數(在我的例子中是 rng)。它似乎特定於 Go RSA OAEP 實現。因此,如果我使用相同的 RSA OAEP 解密實現:
- 私鑰
- 雜湊函式
我應該能夠從所有加密字元串中獲取明文。從我所見,這兩件事似乎是解密所需的唯一要求。這個對嗎 ?答案可能是肯定的,但如果可能的話,很高興收到更多關於此的資訊以增加我的信心。
對於相同明文的每次加密,每種非對稱加密方法都必須返回不同的密文。否則,給定密文和公鑰,但沒有對應的私鑰,攻擊者可以嘗試猜測明文:攻擊者可以通過嘗試加密並將實際密文與他們計算的密文進行比較來驗證猜測。
為了確保每次加密都返回不同的密文,加密的結果需要依賴於一個僅從密文、明文和公鑰中無法找到或猜測的值。隨機值是唯一實際的選擇。根據庫設計者的選擇,生成隨機值的方式可以是實現的內部細節,也可以是加密介面的參數。在內部執行它會使介面更易於使用,這通常更好,但將其作為參數有一些優點:它允許重複一系列操作以進行審計或調試並獲得完全相同的輸出,並且它允許實現不依賴於全域狀態,例如 RNG 狀態(純函式式語言的必要性)。
對稱加密的介面通常是不同的,因為安全特性不同,常見用法也不同。對稱加密通常用於多個消息使用相同密鑰的協議中,並且該協議指定在加密和解密時使用什麼唯一輸入(IV/nonce)(這允許不儲存或傳輸此唯一輸入)。使用 RSA-OAEP,隨機隨機數無論如何都會在密文中進行編碼。對稱加密通常不需要 nonce 保密,而我們已經看到它對於非對稱加密很重要。對稱加密實際上可以在沒有隨機數的情況下進行:您獲得確定性加密,其中密文僅取決於密鑰和明文。當相同的明文被加密兩次時,確定性加密就很明顯了,但由於攻擊者沒有加密密鑰(與解密密鑰相同),因此無法利用它來猜測未知密文的明文。正如我們所看到的,由於攻擊者擁有加密密鑰,這將是非對稱加密的一個主要問題。
您無法通過將結果與已知值進行比較來驗證非對稱加密是否成功。您需要應用解密過程(這需要擁有私鑰)。(同樣,許多非對稱簽名方法是隨機的,因此您無法通過將簽名與已知值進行比較來檢查簽名是否正確——但是,可以設計一種安全的、確定性的非對稱簽名機制,例如 PSS 就是其中之一如果您使用空鹽。)
RSA-OAEP 有一個精確的規範。要解密,您只需要指定:
- 用於標籤的雜湊函式;
- 遮罩生成函式,實際上始終是具有相同散列函式的 MGF1;
- 私鑰;
- 密文。
使用這些輸入,解密過程指定如何將密文轉換為數字,應用 RSA 私鑰操作來獲得另一個數字,將該數字轉換為填充和屏蔽的明文,將其分解並取消屏蔽屏蔽部分以獲得密文。(可以選擇使用標籤——但您可以在事先不知道標籤的情況下解密。)相反,加密過程需要 5 個輸入:散列函式、遮罩生成函式、公鑰、明文和隨機種子。(加上一個影響遮罩和填充的可選標籤。)給定這些輸入,它指定如何將隨機種子轉換為遮罩,將該遮罩應用於明文並填充結果,轉換填充和遮罩的明文變成一個數字,應用 RSA 公鑰運算得到另一個數字,並將該數字轉換為密文字元串。如果給定相同的輸入,包括隨機數(通常不是由呼叫者單獨傳遞,而是由實現直接獲得),則 RSA-OAEP 加密的兩個實現將始終產生相同的密文。如果給定相同的輸入,則 RSA-OAEP 解密的兩種實現將始終產生相同的明文。
聽起來不錯。
特別是在OAEP中,由加密器創建一次性隨機種子,該種子確定填充消息的遮罩,然後種子本身被遮罩並包含在有效負載中。解密器不必能夠以與加密器相同的方式重新創建種子,因為它們可以從解密的有效負載中獲取被屏蔽的種子,並且應該能夠通過移除遮罩來恢復種子。
當然,恢復的有效負載需要與發送的有效負載相同,以便解密器必須擁有與加密器使用的公鑰相關聯的私鑰。同樣,解密器必須能夠重建與加密器相同的遮罩,因此必須使用相同的遮罩偏差函式 (MDF)。在您的實現中,聽起來像使用加密散列函式作為 MDF,因此加密器和解密器必須使用相同的散列。
假設密文沒有被改變,並且解密者同時擁有解密密鑰和用於生成遮罩的函式,那麼恢復是有保證的。