|  | // Copyright (c) 2019 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package edwards25519 | 
|  |  | 
|  | import "sync" | 
|  |  | 
|  | // basepointTable is a set of 32 affineLookupTables, where table i is generated | 
|  | // from 256i * basepoint. It is precomputed the first time it's used. | 
|  | func basepointTable() *[32]affineLookupTable { | 
|  | basepointTablePrecomp.initOnce.Do(func() { | 
|  | p := NewGeneratorPoint() | 
|  | for i := 0; i < 32; i++ { | 
|  | basepointTablePrecomp.table[i].FromP3(p) | 
|  | for j := 0; j < 8; j++ { | 
|  | p.Add(p, p) | 
|  | } | 
|  | } | 
|  | }) | 
|  | return &basepointTablePrecomp.table | 
|  | } | 
|  |  | 
|  | var basepointTablePrecomp struct { | 
|  | table    [32]affineLookupTable | 
|  | initOnce sync.Once | 
|  | } | 
|  |  | 
|  | // ScalarBaseMult sets v = x * B, where B is the canonical generator, and | 
|  | // returns v. | 
|  | // | 
|  | // The scalar multiplication is done in constant time. | 
|  | func (v *Point) ScalarBaseMult(x *Scalar) *Point { | 
|  | basepointTable := basepointTable() | 
|  |  | 
|  | // Write x = sum(x_i * 16^i) so  x*B = sum( B*x_i*16^i ) | 
|  | // as described in the Ed25519 paper | 
|  | // | 
|  | // Group even and odd coefficients | 
|  | // x*B     = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B | 
|  | //         + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B | 
|  | // x*B     = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B | 
|  | //    + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) | 
|  | // | 
|  | // We use a lookup table for each i to get x_i*16^(2*i)*B | 
|  | // and do four doublings to multiply by 16. | 
|  | digits := x.signedRadix16() | 
|  |  | 
|  | multiple := &affineCached{} | 
|  | tmp1 := &projP1xP1{} | 
|  | tmp2 := &projP2{} | 
|  |  | 
|  | // Accumulate the odd components first | 
|  | v.Set(NewIdentityPoint()) | 
|  | for i := 1; i < 64; i += 2 { | 
|  | basepointTable[i/2].SelectInto(multiple, digits[i]) | 
|  | tmp1.AddAffine(v, multiple) | 
|  | v.fromP1xP1(tmp1) | 
|  | } | 
|  |  | 
|  | // Multiply by 16 | 
|  | tmp2.FromP3(v)       // tmp2 =    v in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  2*v in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  2*v in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  4*v in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  4*v in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  8*v in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  8*v in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 = 16*v in P1xP1 coords | 
|  | v.fromP1xP1(tmp1)    // now v = 16*(odd components) | 
|  |  | 
|  | // Accumulate the even components | 
|  | for i := 0; i < 64; i += 2 { | 
|  | basepointTable[i/2].SelectInto(multiple, digits[i]) | 
|  | tmp1.AddAffine(v, multiple) | 
|  | v.fromP1xP1(tmp1) | 
|  | } | 
|  |  | 
|  | return v | 
|  | } | 
|  |  | 
|  | // ScalarMult sets v = x * q, and returns v. | 
|  | // | 
|  | // The scalar multiplication is done in constant time. | 
|  | func (v *Point) ScalarMult(x *Scalar, q *Point) *Point { | 
|  | checkInitialized(q) | 
|  |  | 
|  | var table projLookupTable | 
|  | table.FromP3(q) | 
|  |  | 
|  | // Write x = sum(x_i * 16^i) | 
|  | // so  x*Q = sum( Q*x_i*16^i ) | 
|  | //         = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) | 
|  | //           <------compute inside out--------- | 
|  | // | 
|  | // We use the lookup table to get the x_i*Q values | 
|  | // and do four doublings to compute 16*Q | 
|  | digits := x.signedRadix16() | 
|  |  | 
|  | // Unwrap first loop iteration to save computing 16*identity | 
|  | multiple := &projCached{} | 
|  | tmp1 := &projP1xP1{} | 
|  | tmp2 := &projP2{} | 
|  | table.SelectInto(multiple, digits[63]) | 
|  |  | 
|  | v.Set(NewIdentityPoint()) | 
|  | tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords | 
|  | for i := 62; i >= 0; i-- { | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =    (prev) in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  2*(prev) in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  2*(prev) in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  4*(prev) in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  4*(prev) in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 =  8*(prev) in P1xP1 coords | 
|  | tmp2.FromP1xP1(tmp1) // tmp2 =  8*(prev) in P2 coords | 
|  | tmp1.Double(tmp2)    // tmp1 = 16*(prev) in P1xP1 coords | 
|  | v.fromP1xP1(tmp1)    //    v = 16*(prev) in P3 coords | 
|  | table.SelectInto(multiple, digits[i]) | 
|  | tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords | 
|  | } | 
|  | v.fromP1xP1(tmp1) | 
|  | return v | 
|  | } | 
|  |  | 
|  | // basepointNafTable is the nafLookupTable8 for the basepoint. | 
|  | // It is precomputed the first time it's used. | 
|  | func basepointNafTable() *nafLookupTable8 { | 
|  | basepointNafTablePrecomp.initOnce.Do(func() { | 
|  | basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint()) | 
|  | }) | 
|  | return &basepointNafTablePrecomp.table | 
|  | } | 
|  |  | 
|  | var basepointNafTablePrecomp struct { | 
|  | table    nafLookupTable8 | 
|  | initOnce sync.Once | 
|  | } | 
|  |  | 
|  | // VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical | 
|  | // generator, and returns v. | 
|  | // | 
|  | // Execution time depends on the inputs. | 
|  | func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point { | 
|  | checkInitialized(A) | 
|  |  | 
|  | // Similarly to the single variable-base approach, we compute | 
|  | // digits and use them with a lookup table.  However, because | 
|  | // we are allowed to do variable-time operations, we don't | 
|  | // need constant-time lookups or constant-time digit | 
|  | // computations. | 
|  | // | 
|  | // So we use a non-adjacent form of some width w instead of | 
|  | // radix 16.  This is like a binary representation (one digit | 
|  | // for each binary place) but we allow the digits to grow in | 
|  | // magnitude up to 2^{w-1} so that the nonzero digits are as | 
|  | // sparse as possible.  Intuitively, this "condenses" the | 
|  | // "mass" of the scalar onto sparse coefficients (meaning | 
|  | // fewer additions). | 
|  |  | 
|  | basepointNafTable := basepointNafTable() | 
|  | var aTable nafLookupTable5 | 
|  | aTable.FromP3(A) | 
|  | // Because the basepoint is fixed, we can use a wider NAF | 
|  | // corresponding to a bigger table. | 
|  | aNaf := a.nonAdjacentForm(5) | 
|  | bNaf := b.nonAdjacentForm(8) | 
|  |  | 
|  | // Find the first nonzero coefficient. | 
|  | i := 255 | 
|  | for j := i; j >= 0; j-- { | 
|  | if aNaf[j] != 0 || bNaf[j] != 0 { | 
|  | break | 
|  | } | 
|  | } | 
|  |  | 
|  | multA := &projCached{} | 
|  | multB := &affineCached{} | 
|  | tmp1 := &projP1xP1{} | 
|  | tmp2 := &projP2{} | 
|  | tmp2.Zero() | 
|  |  | 
|  | // Move from high to low bits, doubling the accumulator | 
|  | // at each iteration and checking whether there is a nonzero | 
|  | // coefficient to look up a multiple of. | 
|  | for ; i >= 0; i-- { | 
|  | tmp1.Double(tmp2) | 
|  |  | 
|  | // Only update v if we have a nonzero coeff to add in. | 
|  | if aNaf[i] > 0 { | 
|  | v.fromP1xP1(tmp1) | 
|  | aTable.SelectInto(multA, aNaf[i]) | 
|  | tmp1.Add(v, multA) | 
|  | } else if aNaf[i] < 0 { | 
|  | v.fromP1xP1(tmp1) | 
|  | aTable.SelectInto(multA, -aNaf[i]) | 
|  | tmp1.Sub(v, multA) | 
|  | } | 
|  |  | 
|  | if bNaf[i] > 0 { | 
|  | v.fromP1xP1(tmp1) | 
|  | basepointNafTable.SelectInto(multB, bNaf[i]) | 
|  | tmp1.AddAffine(v, multB) | 
|  | } else if bNaf[i] < 0 { | 
|  | v.fromP1xP1(tmp1) | 
|  | basepointNafTable.SelectInto(multB, -bNaf[i]) | 
|  | tmp1.SubAffine(v, multB) | 
|  | } | 
|  |  | 
|  | tmp2.FromP1xP1(tmp1) | 
|  | } | 
|  |  | 
|  | v.fromP2(tmp2) | 
|  | return v | 
|  | } |