Ed25519

Ed25519(ref10)中的點加法和加倍?

  • May 9, 2014

我剛剛將 CodesInChaos 的 Ed25519(ref10) 的 C# 埠遷移到 Java,一切正常。(即我在密鑰生成、簽名和驗證方面得到相同的結果。)

現在,我想直接在 Ed25519 上進行 Diffie-Hellman 密鑰交換。因此,我正在研究點加法、加倍和乘法的函式。

經過幾次測試,似乎加倍了一個點

分貝(P)

提供與向自身添加相同點不同的結果

添加(P,P)。

即使我使用不同的點進行加法,結果仍然不同。例如:dbl(dbl(P)) 也不同於 add(add(dbl(P),P),P)。

這是正常的嗎?(我不熟悉 ECC,並且我曾期望這些函式會返回相同的值。)


更新

由於 CodesInChaos,我的程式碼中有一個錯誤現在已得到糾正。

這是我的 C# 測試程式碼:

using System;
using Chaos.NaCl.Internal.Ed25519Ref10;

namespace Chaos.NaCl
{
   public static class RunTest
   {
       static void Main ()
       {
           testAddition ();
       }


       public  static  void    testAddition    ()
       {
           Console.WriteLine ("============================= testAddition ");

           byte[]  l_Seed  =   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

           byte[]  l_PK    =   new byte[32];
           byte[]  l_SK    =   new byte[64];

           Ed25519Operations.crypto_sign_keypair (l_PK, 0, l_SK, 0, l_Seed, 0);

           byte[]  l_A =   add (l_PK, l_PK);
           byte[]  l_B =   dbl (l_PK);

           Console.WriteLine (CryptoBytes.ToHexStringUpper (l_A));
           Console.WriteLine (CryptoBytes.ToHexStringUpper (l_B));

           //  Output Java and C#:
           //  382CE0B6971265E859F317BBCD18F6ADF4517102055DEFA3ED7C4EBFD2C0D655
           //  382CE0B6971265E859F317BBCD18F6ADF4517102055DEFA3ED7C4EBFD2C0D655
           //  which is OK


           //  LETS DO IT AGAIN:

           byte[]  l_C =   add (l_B, l_B);
           byte[]  l_D =   dbl (l_B);

           Console.WriteLine (CryptoBytes.ToHexStringUpper (l_C));
           Console.WriteLine (CryptoBytes.ToHexStringUpper (l_D));

           //  Output Java port:
           //  40838B988FB4A3809EBEAA600604EAB4A39A75BD86509A73C40B5A2820BEB94E
           //  90A0F26E495C4A73BCE8BE36B361FF84F8CA8E19E15B9F623AC538E5F9646B63
           //  which is wrong ?

           //  Output C# (Mono):
           //  0000000000000000000000000000000000000000000000000000000000000040
           //  0000000000000000000000000000000000000000000000000000000000000040
           //  which is also wrong ?? :)

       }

       static byte[]   dbl (byte[] p_Element)
       {
           byte[]  l_Result    =   new byte[32];

           GroupElementP3 l_P3;
           GroupOperations.ge_frombytes_negate_vartime(out l_P3, p_Element, 0);

           GroupElementP1P1    l_P1P1;
           GroupOperations.ge_p3_dbl(out l_P1P1,ref l_P3);

           GroupElementP3  l_P3again;
           GroupOperations.ge_p1p1_to_p3(out l_P3again,ref l_P1P1);

           GroupOperations.ge_p3_tobytes(l_Result,0,ref l_P3again);
           // EVIL MISTAKE: ScalarOperations.sc_clamp(l_Result, 0);

           return  l_Result;
       }

       static byte[]   add (byte[] p_ElementA, byte[]p_ElementB)
       {

           byte[]  l_Result    =   new byte[32];

           GroupElementP3  l_A;
           GroupOperations.ge_frombytes_negate_vartime(out l_A, p_ElementA, 0);

           GroupElementP3  l_B;
           GroupOperations.ge_frombytes_negate_vartime(out l_B, p_ElementB, 0);

           GroupElementCached  l_Cached;
           GroupOperations.ge_p3_to_cached(out l_Cached,ref l_A);

           GroupElementP1P1    l_P1P1;
           GroupOperations.ge_add(out l_P1P1, ref l_B, ref l_Cached);

           GroupElementP3  l_P3again;
           GroupOperations.ge_p1p1_to_p3(out l_P3again, ref l_P1P1);

           GroupOperations.ge_p3_tobytes(l_Result, 0, ref l_P3again);
           // EVIL MISTAKE: ScalarOperations.sc_clamp (l_Result, 0);

           return  l_Result;
       }
   }
}

愛德華茲曲線具有統一的加法,因此向自身添加一個點會返回正確的結果。這與 Weierstrass 曲線不同,後者向自身添加一個點會產生錯誤的結果,您必須使用加倍。所以你期望加法和加倍應該返回相同的點是正確的。

ECC 的高性能實現使用某種形式的擴展或投影座標,您可以在其中為分母添加附加欄位。 $ (x,y) $ 可以表示為 $ (X, Y,Z) $ 和 $ x=X/Z $ 和 $ y=Y/Z $ . Ref10 使用了這些表示中的幾種不同,但想法保持不變。

所以你不能簡單地通過比較所有的來比較分數 $ X,Y,Z $ 因為同一點有多個表示。類似於如何 $ \frac{1}{3} $ 和 $ \frac{2}{6} $ 儘管看起來不同,但數字相同。加倍和加法返回相同的點,但表示不同。

比較分數

  • 最簡單的方法是ge_tobytes. 這將轉換為仿射座標,但需要昂貴的場反轉。
  • 或者,如果您想比較 $ \frac{X_1}{Z_1} $ 和 $ \frac{X_2}{Z_2} $ 你檢查一下 $ X_1 Z_2 = X_2 Z_1 $ .

這是從 $ \frac{X_1}{Z_1} = \frac{X_1 Z_2}{Z_1 Z_2} $ 和 $ \frac{X_2}{Z_2} = \frac{X_2 Z_1}{Z_1 Z_2} $ 由於分母相同,因此您只需要比較提名者即可。

對 $ Y/Z $ 或者 $ Y/T $ 適合您正在使用的點表示的部分。

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