github.com/cloudflare/circl@v1.5.0/dh/x25519/curve.go (about) 1 package x25519 2 3 import ( 4 fp "github.com/cloudflare/circl/math/fp25519" 5 ) 6 7 // ladderJoye calculates a fixed-point multiplication with the generator point. 8 // The algorithm is the right-to-left Joye's ladder as described 9 // in "How to precompute a ladder" in SAC'2017. 10 func ladderJoye(k *Key) { 11 w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved. 12 fp.SetOne(&w[1]) // x1 = 1 13 fp.SetOne(&w[2]) // z1 = 1 14 w[3] = fp.Elt{ // x2 = G-S 15 0xbd, 0xaa, 0x2f, 0xc8, 0xfe, 0xe1, 0x94, 0x7e, 16 0xf8, 0xed, 0xb2, 0x14, 0xae, 0x95, 0xf0, 0xbb, 17 0xe2, 0x48, 0x5d, 0x23, 0xb9, 0xa0, 0xc7, 0xad, 18 0x34, 0xab, 0x7c, 0xe2, 0xee, 0xcd, 0xae, 0x1e, 19 } 20 fp.SetOne(&w[4]) // z2 = 1 21 22 const n = 255 23 const h = 3 24 swap := uint(1) 25 for s := 0; s < n-h; s++ { 26 i := (s + h) / 8 27 j := (s + h) % 8 28 bit := uint((k[i] >> uint(j)) & 1) 29 copy(w[0][:], tableGenerator[s*Size:(s+1)*Size]) 30 diffAdd(&w, swap^bit) 31 swap = bit 32 } 33 for s := 0; s < h; s++ { 34 double(&w[1], &w[2]) 35 } 36 toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) 37 } 38 39 // ladderMontgomery calculates a generic scalar point multiplication 40 // The algorithm implemented is the left-to-right Montgomery's ladder. 41 func ladderMontgomery(k, xP *Key) { 42 w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved. 43 w[0] = *(*fp.Elt)(xP) // x1 = xP 44 fp.SetOne(&w[1]) // x2 = 1 45 w[3] = *(*fp.Elt)(xP) // x3 = xP 46 fp.SetOne(&w[4]) // z3 = 1 47 48 move := uint(0) 49 for s := 255 - 1; s >= 0; s-- { 50 i := s / 8 51 j := s % 8 52 bit := uint((k[i] >> uint(j)) & 1) 53 ladderStep(&w, move^bit) 54 move = bit 55 } 56 toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) 57 } 58 59 func toAffine(k *[fp.Size]byte, x, z *fp.Elt) { 60 fp.Inv(z, z) 61 fp.Mul(x, x, z) 62 _ = fp.ToBytes(k[:], x) 63 } 64 65 var lowOrderPoints = [5]fp.Elt{ 66 { /* (0,_,1) point of order 2 on Curve25519 */ 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 }, 72 { /* (1,_,1) point of order 4 on Curve25519 */ 73 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 }, 78 { /* (x,_,1) first point of order 8 on Curve25519 */ 79 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 80 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 81 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 82 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00, 83 }, 84 { /* (x,_,1) second point of order 8 on Curve25519 */ 85 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 86 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 87 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 88 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57, 89 }, 90 { /* (-1,_,1) a point of order 4 on the twist of Curve25519 */ 91 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 95 }, 96 }