fe_extra.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. // Copyright (c) 2021 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package field
  5. import "errors"
  6. // This file contains additional functionality that is not included in the
  7. // upstream crypto/ed25519/edwards25519/field package.
  8. // SetWideBytes sets v to x, where x is a 64-byte little-endian encoding, which
  9. // is reduced modulo the field order. If x is not of the right length,
  10. // SetWideBytes returns nil and an error, and the receiver is unchanged.
  11. //
  12. // SetWideBytes is not necessary to select a uniformly distributed value, and is
  13. // only provided for compatibility: SetBytes can be used instead as the chance
  14. // of bias is less than 2⁻²⁵⁰.
  15. func (v *Element) SetWideBytes(x []byte) (*Element, error) {
  16. if len(x) != 64 {
  17. return nil, errors.New("edwards25519: invalid SetWideBytes input size")
  18. }
  19. // Split the 64 bytes into two elements, and extract the most significant
  20. // bit of each, which is ignored by SetBytes.
  21. lo, _ := new(Element).SetBytes(x[:32])
  22. loMSB := uint64(x[31] >> 7)
  23. hi, _ := new(Element).SetBytes(x[32:])
  24. hiMSB := uint64(x[63] >> 7)
  25. // The output we want is
  26. //
  27. // v = lo + loMSB * 2²⁵⁵ + hi * 2²⁵⁶ + hiMSB * 2⁵¹¹
  28. //
  29. // which applying the reduction identity comes out to
  30. //
  31. // v = lo + loMSB * 19 + hi * 2 * 19 + hiMSB * 2 * 19²
  32. //
  33. // l0 will be the sum of a 52 bits value (lo.l0), plus a 5 bits value
  34. // (loMSB * 19), a 6 bits value (hi.l0 * 2 * 19), and a 10 bits value
  35. // (hiMSB * 2 * 19²), so it fits in a uint64.
  36. v.l0 = lo.l0 + loMSB*19 + hi.l0*2*19 + hiMSB*2*19*19
  37. v.l1 = lo.l1 + hi.l1*2*19
  38. v.l2 = lo.l2 + hi.l2*2*19
  39. v.l3 = lo.l3 + hi.l3*2*19
  40. v.l4 = lo.l4 + hi.l4*2*19
  41. return v.carryPropagate(), nil
  42. }