RSA 中是否存在任何實際弱點,其中私鑰用於加密消息(簽名),沒有填充?
我最近遇到了這種情況,想了解是否有針對此實現的實際攻擊。
RSA 私鑰用於“加密”數據。公鑰包含在分發給使用者的軟體組件中,用於“解密”這些數據。我知道這不提供機密性,但它確實可以防止數據被篡改,因為使用者無法訪問私鑰。
“解密”是使用從公鑰中提取的指數和模數完成的,並使用 Java ModPow 函式。
鑑於明文是已知的並且沒有使用填充,是否有任何實際的攻擊可以讓私鑰被恢復,或者選擇的明文被“加密”?
這裡沒有加密或解密,因為該方案不旨在提供任何機密性。該方案旨在提供真實性。操作是簽名(使用私鑰)和驗證(使用公鑰)。
這個方案沒有按原樣使用的原因是它內部有某種形式的填充或格式化(通常是PKCS#1指定的兩種簽名模式之一),因為它有漏洞。這些漏洞是否可利用取決於確切的數據格式:畢竟,如果簽名者只簽署有效的 PKCS#1 填充,而驗證者總是驗證是否存在正確的 PKCS#1 填充,那麼該方案將是安全的。
該方案的問題在於它允許各種形式的偽造。讓 $ n $ 是模數, $ e $ 公共指數和 $ d $ 私人指數。消息的簽名 $ M $ 是 $ M^d \bmod n $ . 聲稱的簽名 $ S $ 是一個有效的簽名 $ M $ 如果 $ S^e \bmod n = M $ . 這裡有一些偽造簽名的簡單方法,即產生一個私鑰持有者沒有產生的有效簽名。(那些都是著名的經典;我不知道是誰先寫了這些。)
如果 $ e $ 很小,可能會偽造某些消息的簽名。 $ e $ 通常很小,因為這會使計算更快;尤其是 $ e=3 $ (最小的可能值)是一種比較流行的選擇。讓 $ x $ 是一個整數,使得 $ x^e \lt n $ . 然後 $ x $ 是一個有效的簽名 $ x^e $ . PKCS#1 簽名格式化方案通過確保沒有小消息來避免這種攻擊:v1.5 強制 $ m \gt n/2^16 $ ,並且 PSS 最多有 8 個最高位設置為 0,後跟至少 64 個偽隨機位(通常更多),所以少於 $ 1/2^{64} $ 有機會 $ m \lt n/2^{72} $ .
如果攻擊者已經知道一些有效的簽名,就有可能構造更多的有效簽名。這是由於一個非常簡單的數學性質:如果 $ S_1^e = M_1 $ 和 $ S_2^e = M_2 $ 然後 $ (S_1 \cdot S_2)^e \bmod n = (M_1 \cdot M_2) \bmod n $ . 根據消息的編碼, $ (M_1 \cdot M_2) \bmod n $ 可能有趣也可能不有趣。例如,假設消息是帶有“admin”位的命令,並且大多數管理命令會導致不良結果,但簽名者通常非常小心,不會簽署不受歡迎的管理命令。將兩個隨機的非管理員命令相乘大約有二分之一的機會產生一條設置了管理員位的消息。更一般地說,給定一個有效簽名池,攻擊者可以暴力破解一條消息 $ k $ 位設置為所需的值 $ 2^k $ 嘗試。PKCS 方案通過對消息進行散列處理來避免這種攻擊(至少是我在這裡介紹的簡單變體),因此攻擊者既不能製造 $ M $ 並反轉散列函式以找到原像,也不將散列設置為目標並正確獲取所有位(這將花費例如大約 $ 2^{128} $ 嘗試在使用 128 位散列函式時生成給定消息的簽名)。
它使用 RSA 私鑰來簽署¹消息² $ m\in[0,n) $ 根據教科書 RSA 簽名 $ m\mapsto s:=m^d\bmod n $ ,並從簽名 $ s $ 簽名的消息 $ m $ 使用公鑰恢復³ $ s\mapsto m:=s^e\bmod n $ 在使用者軟體中。
鑑於明文是已知的並且沒有使用填充,是否有任何實際的攻擊可以讓私鑰被恢復?
沒有。一個有效的⁴私鑰 $ (n,d) $ 不會從範例中洩漏 $ (m,s) $ 對和公鑰 $ (n,e) $ , 即使 $ m $ 被對手選中。這是為了正確生成、保存和使用的密鑰對。
或者選擇的明文被“加密”簽名?
對於任意隨機消息 $ m $ 在 $ [0,n) $ ,不,但是有可能獲得與某些選定標準匹配的消息的簽名,這可能是有害的。
RSA 中是否存在任何實際弱點,其中私鑰用於加密簽名消息,無需填充?
是的,很多。不知結果如何 $ m:=s^e\bmod n $ 使用,以及攻擊者在獲取簽名消息時可能有什麼緯度,無法判斷系統是否可以被攻擊。從安全的角度來看,負責任的事情是假設它可以。這就是為什麼我們有正確的 RSA 簽名(例如RSASSA-PSS、ISO/IEC 9796-2),而不是眾所周知的不安全的教科書 RSA 簽名。針對後者的攻擊範例:
- 反複試驗允許找到 $ s $ 這樣 $ m $ 以某個短字節串開頭,例如 $ m $ 解析為
LICNB:
後跟十進制數字和終止零。- 如果 $ e $ 很小而且眾所周知 $ s $ 產生一條消息 $ m $ 和 $ n/m>2^{k,e} $ 那麼計算起來很簡單 $ s’=2^k,s $ 產生 $ m’ $ 和 $ m’=2^{k,e},m $ . 為了 $ k=8 $ , $ m’ $ 可能是有意義的。
- 如果可以獲得 $ s_i $ 被選中的簽名 $ m_i $ (例如價格),也許可以設計 $ m_0 $ , $ m_1 $ , $ m_2 $ , $ m_3 $ 符合某些標準(例如,以某個常數開頭)並且使得 $ m_0,m_1=m_2,m_3 $ , 合法獲取簽名 $ s_0 $ , $ s_1 $ , $ s_2 $ 的 $ m_0 $ , $ m_1 $ , $ m_2 $ ,並從中計算簽名 $ s_3 $ 的 $ m_3 $ 作為 $ s_3=s_0,s_1,s_2^{-1}\bmod n $ .
這不提供任何機密性。
的確。這就是為什麼它不是加密的原因。
但是,它確實可以防止數據被篡改,因為使用者無法訪問私鑰。
這是假設對手無法更改軟體,或者它是公鑰。在許多應用程序中,這是沒有根據的。正確的簽名並不能解決這個問題。
¹“加密”是不合適的,因為加密意味著希望讓對手無法理解數據,而事實並非如此。
² “數據”比“明文”更可取,因為沒有加密。
³ “解密”是不合適的,因為一開始就沒有加密。
⁴ 更不用說私鑰了,因為有幾個功能等效的私鑰 $ (n,d) $ 匹配給定的 $ (n,e) $ .