github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/sss/polynomial.go (about)

     1  package sss
     2  
     3  import "io"
     4  
     5  // the degree of the polynomial
     6  func degree(p []byte) int {
     7  	return len(p) - 1
     8  }
     9  
    10  // evaluate the polynomial at the given point
    11  func eval(p []byte, x byte) (result byte) {
    12  	// Horner's scheme
    13  	for i := 1; i <= len(p); i++ {
    14  		result = mul(result, x) ^ p[len(p)-i]
    15  	}
    16  	return
    17  }
    18  
    19  // generates a random n-degree polynomial w/ a given x-intercept
    20  func generate(degree byte, x byte, rand io.Reader) ([]byte, error) {
    21  	result := make([]byte, degree+1)
    22  	result[0] = x
    23  
    24  	buf := make([]byte, degree-1)
    25  	if _, err := io.ReadFull(rand, buf); err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	for i := byte(1); i < degree; i++ {
    30  		result[i] = buf[i-1]
    31  	}
    32  
    33  	// the Nth term can't be zero, or else it's a (N-1) degree polynomial
    34  	for {
    35  		buf = make([]byte, 1)
    36  		if _, err := io.ReadFull(rand, buf); err != nil {
    37  			return nil, err
    38  		}
    39  
    40  		if buf[0] != 0 {
    41  			result[degree] = buf[0]
    42  			return result, nil
    43  		}
    44  	}
    45  }
    46  
    47  // an input/output pair
    48  type pair struct {
    49  	x, y byte
    50  }
    51  
    52  // Lagrange interpolation
    53  func interpolate(points []pair, x byte) (value byte) {
    54  	for i, a := range points {
    55  		weight := byte(1)
    56  		for j, b := range points {
    57  			if i != j {
    58  				top := x ^ b.x
    59  				bottom := a.x ^ b.x
    60  				factor := div(top, bottom)
    61  				weight = mul(weight, factor)
    62  			}
    63  		}
    64  		value = value ^ mul(weight, a.y)
    65  	}
    66  	return
    67  }