polynomial.go 1.3 KB

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