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 }