Abnormal cryptography, or how I verified Ed25519 signatures on Solidity

When writing about how to develop secure applications, one of the most common advice is: don't write crypto yourself, but use some trusted library. Unfortunately, when developing blockchains, this advice often does not work: the required algorithms are either not implemented at all, or the existing implementations are not suitable for many possible reasons - even because they are not secure enough . In this case, too , it was necessary to check signatures using Ed25519 - a very popular type of signatures for which there are many implementations, none of which, however, suited us. This is because the verification had to be performed from a smart contract running on the Ethereum blockchain.



What is a smart contract

- β€” , Β« Β». : , , - , , , . - : , , , , - ́ . - - , . , , .



What is the problem?



In Ethereum, smart contracts are executed in a special environment - the so-called Ethereum virtual machine (EVM).



What is EVM

EVM β€” , -. : , , β€” , . , , -, .



EVM , , . , , , , , . - . EVM , , , , EVM. EVM-, - Ed25519 β€” , , , , . , EVM , β€” Solidity.



EVM differs significantly both from popular processor architectures and from commonly used abstract virtual machines such as JVM or WASM. While most architectures contain 32- and 64-bit operations, in EVM the only data type is a 256-bit integer. This is very convenient for the implementation of Ed25519, since all the necessary calculations are performed on numbers that fit into 256 bits.



How Ed25519 signature works

Ed25519 β€” Curve25519. (x,y), p, 2255βˆ’19 β€” . , , 8β‹…l, l=2252+27742317777372353535851937790883648493 β€” . l.



. β€” , , , β€” . : β€” a, β€” A=aβ‹…G (G β€” , l). a, A, , , ( ).



Ed25519 r R=rβ‹…G. SHA-512 R, A ( ) : h=H(R||A||m) ( H β€” -, || , ). s=r+hamodl β€” . (R,s). r , , , , .



h=H(R||A||m) , sβ‹…G=R+hβ‹…A. , . , , , , .



EVM β€” . «» , EVM , - . , (gas), , , , . : , . , , 256- , , , . EVM . , , , EVM .



EVM : , (storage). , -. . , , , , . Ed25519 . , , . , Solidity - ( Solidity «» , ). , Solidity (, ), . Solidity JavaScript.



, , JavaScript-, Solidity, Solidity.



: - SHA-512



, Ed25519 β€” - SHA-512. . EVM -: SHA-256, Keccak-256 ( SHA-3-256), RIPEMD-160, SHA-512 . SHA-512 . EVM β€” , Solidity . 1024 , 16 . , 16, β€” , , , .



SHA-512 β€” :



w[0..15] :=  
for i in 16 .. 79:
    s0 := (w[i-15] ror 1) ^ (w[i-15] ror 8) ^ (w[i-15] >> 7)
    s1 := (w[i-2] ror 19) ^ (w[i-2] ror 61) ^ (w[i-2] >> 6)
    w[i] := w[i-16] + s0 + w[i-7] + s1

a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
for i in 0 .. 79:
    S0 := (a ror 28) ^ (a ror 34) ^ (a ror 39)
    S1 := (e ror 14) ^ (e ror 18) ^ (e ror 41)
    ch := (e & f) ^ (~e & g)
    maj := (a & b) ^ (a & c) ^ (b & c)
    temp1 := h + S1 + ch + k[i] + w[i]
    temp2 := S0 + maj
    a, b, c, d, e, f, g, h := temp1 + temp2, a, b, c, d + temp1, e, f, g
h0, h1, h2, h3 := h0 + a, h1 + b, h2 + c, h3 + d
h4, h5, h6, h7 := h4 + e, h5 + f, h6 + g, h7 + h


, 16 , , . , : , , , , . : (e & f) ^ (~e & g) (e & (f ^ g)) ^ g, (a & b) ^ (a & c) ^ (b & c) β€” (a & (b | c)) | (b & c) ( (a & (b ^ c)) ^ (b & c)). : x, x | (x << 64) ( x, 64). , x | (x << 64) .



w[i] w[i-2] (. . w[i-1] ), w ( 256- SIMD). , .



: 16 w, 16 , , . w , , . ( 16 ) , , 4,5 .





: . Curve25519 (x,y), : x y, . : y , , , x . p=2255βˆ’19, 32 . , , x.



x x=Β±(y2βˆ’1)/(dy2+1). βˆ’d p, , , y. . , . u/v, vβ‰ 0. Ed25519 ( , p≑5(mod8)):



  • Ξ²=uv3(uv7)(pβˆ’5)/8.
  • vΞ²2=u, Β±Ξ².
  • , vΞ²2=βˆ’u, Β±βˆ’1Ξ².
  • , .


? , Ξ²8=u8v24(uv7)pβˆ’5=up+3v7pβˆ’11=(u/v)4, , Ξ²2=Β±u/v Ξ²2=Β±βˆ’1u/v. ( uβ‰ 0), u/v , βˆ’1 . Ξ²2=βˆ’u/v, (βˆ’1Ξ²)2=u/v. , , .



, : Ξ²=uv3(uv7)(pβˆ’5)/8 Ξ²=u(uv)(pβˆ’5)/8. Ξ²8=u8(uv)pβˆ’5=up+3vpβˆ’5=(u/v)4, . , v v2250βˆ’1 v11 p, p ( ).





, , sG=R+hA. , (R A), , , -: sGβˆ’hA, R. , , β€” sGβˆ’hA.



. sG hA, . β€” Β« Β» (double-and-add), :



result := 0
for bit_index in n-1 .. 0:
    result := double(result)
    if s & (1<<bit_index) != 0:
        result := add(result, G)
    if h & (1<<bit_index) != 0:
        result := subtract(result, A)


n β€” s h. s h, , G ( A). n n ( ) , , s h 0 1 . . , «» s h, , . , k A G 2k 2k+1βˆ’1, k+1 ! :



result := 0
for bit_index in n-1 .. k:
    result := double(result)
    if s & (1<<bit_index) != 0:
        result := add(result, Gmul[s >> (bit_index-k)])
        s := s & ((1 << (bit_index-k)) - 1)
    if h & (1<<bit_index) != 0:
        result := subtract(result, Amul[h >> (bit_index-k)])
        h := h & ((1 << (bit_index-k)) - 1)


, , , k . «» s h, . , : k . :



  • s G , G . s 2k, G β€” 2βˆ’kmodl. , 2k k s .
  • h A . h 2βˆ’kmodl 2k, , A l. A l, (h2βˆ’kmodl)β‹…2k h, l 8l ( ), 2βˆ’k. , : h h+8lβˆ’2k ( , hβˆ’2k 8l), : result := subtract(result, Amul[(1 << k) + h]), , k , 2k , A 2k 2k+1βˆ’1.


k=3, , .



: , . , p . EVM , . β€” Explicit-Formulas Database. , Curve25519. , . , EFD, , , , . : , . , , -2 -4 (. ), , ( ). Β«madd-2008-hwcd-3Β» Β«dbl-2008-hwcdΒ» ( ). , .



-, . (extended projective coordinates) β€” X, Y, Z T, x=X/Z, y=Y/Z xy=T/Z. , T , , β€” . , , X, U, Y V, x=X/U y=Y/V, , ( , T). X, U, Y, V, - T.



-, . madd (mixed addition) β€” , , . : ; , , . : ((y+x)/2,(yβˆ’x)/2,xyd). (, (y+x,yβˆ’x,xyβ‹…2d), libsodium) 2, EVM , . :



//  :
//  1: (x1, u1, y1, v1), x=x1/u1, y=y1/v1.
//  2: (s2, d2, t2), s2=(y+x)/2, d2=(y-x)/2, t2=x*y*d.
//  :
//  3: (x3, u3, y3, v3), x=x3/u3, y=y3/v3.

//  (x4, y4, z4, t4) -   ,    1,    .
x4 := x1 * v1
y4 := y1 * u1
z4 := u1 * v1
t4 := x1 * y1

//  .  madd-2008-hwcd-3.
s4 := y4 + x4
d4 := y4 - x4
a := d4 * d2 // (y4-x4)*(y2-x2)/2,  A/2.
b := s4 * s2 // (y4+x4)*(y2+x2)/2,  B/2.
c := t4 * t2 //  C/2.
             // D/2 -   z4,   .
x3 := b - a  // E/2.
u3 := z4 + c // G/2.
y3 := b + a  // H/2.
v3 := z4 - c // F/2.
//  x3, u3, y3, v3   E, G, H, F  1/2,    ,    x3/u3  y3/v3   .


:



//  :
//  1: (x1, u1, y1, v1), x=x1/u1, y=y1/v1.
//  :
//  2: (x2, u2, y2, v2), x=x2/u2, y=y2/v2.

//  (x3, y3, z3) -   ,    1,    .  t3  .
x3 := x1 * v1
y3 := y1 * u1
z3 := u1 * v1

//  .  dbl-2008-hwcd.
xx := x3 * x3 // A.
yy := y3 * y3 // B.
xy := x3 * y3 //      E  2xy,   ,  .
zz := z3 * z3
x2 := xy + xy // E.
u2 := yy - xx // G.
y2 := yy + xx // -H.
v2 := zz + zz - u2 // -F.
//  ,  -1   y2  v2     .


: addmod ( ). , 2255, ( ), 256- . , , , . , , .





, . : x=X/U y=Y/V, x y. β€” ( pβˆ’2), , : (UV)βˆ’1, Uβˆ’1=(UV)βˆ’1V Vβˆ’1=(UV)βˆ’1U. R, . , . .





, NEAR . - Rust AssemblyScript ( TypeScript) .



, NEAR, -IDE .



, .



!




All Articles