為什麼在 secp256k1 中使用 int128?
當已經有任意長度的有理數時,他們為什麼要在 secp256k1 中編寫 int128 類型?
那是花哨的嗎?無聊?secp256k1 不只是用於密鑰對,並且很少使用密鑰對算法,所以為了證明將原生較小的 int 類型粘貼在一起而不是使用任意長度的數據類型是合理的?
我假設您指的是 secp256k1 算術的 C 實現,也許特別是這個拉取請求?如果沒有,請發表評論,我會修改我的答案。
當已經有任意長度的有理數時,他們為什麼要在 secp256k1 中編寫 int128 類型?
電腦通常不能對任意長度的數字進行運算,更不用說有理數了。硬體通常只能執行最大為 32 或 64 位大小的整數運算,或使用 32 位、64 位或 80 位大小的浮點數進行近似運算(帶舍入)。出於加密目的,我們需要精確的算術,所以任何帶有捨入的東西都是禁止的。
其他任何事情最終都必須在軟體中實現。許多語言提供了隱藏這種複雜性的便利功能。例如,Python 將通用任意長度整數和分數作為其標準庫的一部分,但這僅僅意味著 Python 解釋器正在將對這些明顯數據類型的操作轉換為許多單獨的小指令,每個指令僅對 64 位整數進行操作,通常。如果您想知道它是如何工作的,請想像一下您曾經如何使用超過 1 位的數字來學習數學。這裡的“數字”本身就是 64 位整數,因此 256 位整數可以看作是由 4 個這樣的數字組成的數字。對它們的許多操作(加法、乘法……)與您在紙上對十進制數所做的操作非常相似。
libsecp256k1 不是用 Python 編寫的,而是用 C 編寫的,而且 C 通常不支持大於 CPU 內部支持的整數類型。因此,它不能只使用現成的程式碼進行大整數運算,它必須手動實現。當然,這就是重點:libsecp256k1 旨在快速,並且通過使用專門為此應用程序設計的自定義整數程式碼,它可以比 Python 實現希望達到的速度快很多倍。
此外,這是必要的。任意長度的整數類型,即使它們可用,通常也不適合實現加密。我們的目標是設計在恆定時間內執行的程式碼,這樣攻擊者就無法通過觀察對它的操作需要多長時間來了解有關我們私鑰的任何資訊。可變長度類型顯然不能是恆定時間的,因為對它們進行操作取決於數字的長度。
那是花哨的嗎?無聊?
這個拉取請求的重點是測試、平台支持和可驗證性。
讓我解釋。為了實現橢圓曲線運算,libsecp256k1 需要推理相當大的整數(大部分時間為 256 位,偶爾可達 512 位),通常以一些大(256 位)素數為模。
為了用 256 位長的數字實現算術,操作通常被分解成更小的位,正如我上面解釋的那樣。但是有多小取決於您擁有的硬體。現代 x86_64 CPU (例如 Intel 和 AMD 的 CPU)本身可以執行 64 位算術,包括將兩個 64 位數字相乘以獲得 128 位數字(然後將其儲存在兩個 64 位寄存器中)。這非常有用,但並非在任何地方都可行。大多數 Raspberry Pi 系統在 32 位模式下執行,硬體中沒有 64 位整數類型可用。
為了解決這個問題,libsecp256k1 有多個版本的專用 256 位算術程式碼。稍微簡化一下,它有一個用於 32 位系統的版本和一個用於 64 位系統的版本。第一個使用 8 到 10 個 32 位的“數字”來表示 256 位數字,而第二個使用 4 到 5 個 64 位來代替。
所有這些當然都有測試,但由於這是一個關鍵的密碼程式碼庫,其中的錯誤可能非常直接地影響使用它的許多比特幣軟體的安全性,包括比特幣核心,更多的測試/驗證/分析總是受歡迎的. Russell O’Connor 一直在為這項工作做出貢獻,其中包括正確性的形式驗證證明。但是,他使用的系統不支持 64x64->128 位乘法。我們當然只能測試 256 位整數邏輯的 32 位實現,但我們想更進一步。
這就是 128 位整數類型的用武之地。它只是在 libsecp256k1 本身中實現的一種類型。在 64 位系統上,它會立即遵循 C 中可用的實際 64x64->128 邏輯。在其他系統上,它會通過將事物拆分為對 32 位整數的操作來模擬它。這意味著 256 位實現可以使用我們新的 128 位類型(而不是直接使用 C 類型),這將適用於 32 位和 64 位系統。更重要的是,它可以在原生不支持 128 位類型的形式驗證工具中工作。
還有另一個優點,雖然這還沒有在這個 PR 中實現。這就是 MSVC (Microsoft Visual C)確實支持 128 位操作,但不通過 128 位類型來實現。相反,它具有僅使用 64 位整數執行這些操作的特殊功能。因此,通過引入這種中間 128 位類型,然後為 MSVC 添加一個實例化,我們可以自動使我們的 256 位邏輯為 MSVC 工作,而不會導致只使用 32 位程式碼的性能損失。如果我們想在不引入 128 位包裝器類型的情況下實現類似的東西,我們需要為 MSVC 創建整個 256 位整數邏輯的新實現,而不僅僅是 128 位包裝器的實現。這可能聽起來微不足道,但它是幾百行非常棘手的程式碼,並且這樣的程式碼實際上在其他庫(包括 OpenSSL)中存在錯誤。
secp256k1 不是只針對密鑰對,很少使用密鑰對算法
不僅僅是密鑰對;libsecp256k1 為涉及私鑰、公鑰或兩者的各種操作提供實現。這包括密鑰生成(計算給定私鑰的公鑰)、密鑰派生(例如 BIP32)以及簽名和驗證數字簽名(ECDSA,最近還有 BIP340 Schnorr)。
特別是,簽名驗證是節點花在同步和處理區塊和交易上的時間的重要組成部分。libsecp256k1 的主要目標是提高效率(除了安全和經過良好測試),特別是因為簽名操作是比特幣的瓶頸。