modulo25519-reference.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #pragma once
  2. //warning: this implementation leaks side-channel information
  3. //use modulo25519-optimized.hpp in production
  4. #include <nall/arithmetic/barrett.hpp>
  5. namespace nall::EllipticCurve {
  6. static const uint256_t P = (1_u256 << 255) - 19;
  7. struct Modulo25519 {
  8. Modulo25519() = default;
  9. Modulo25519(const Modulo25519& source) : value(source.value) {}
  10. template<typename T> Modulo25519(const T& value) : value(value) {}
  11. explicit operator bool() const { return (bool)value; }
  12. auto operator()() const -> uint256_t { return value; }
  13. private:
  14. uint256_t value;
  15. };
  16. inline auto operator-(const Modulo25519& lhs) -> Modulo25519 {
  17. return P - lhs();
  18. }
  19. inline auto operator+(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
  20. uint512_t value = (uint512_t)lhs() + rhs();
  21. if(value >= P) value -= P;
  22. return value;
  23. }
  24. inline auto operator-(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
  25. uint512_t value = (uint512_t)lhs();
  26. if(value < rhs()) value += P;
  27. return uint256_t(value - rhs());
  28. }
  29. inline auto operator*(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
  30. static const BarrettReduction<256> P{EllipticCurve::P};
  31. uint256_t hi, lo;
  32. mul(lhs(), rhs(), hi, lo);
  33. return uint512_t{hi, lo} % P;
  34. }
  35. inline auto operator&(const Modulo25519& lhs, uint256_t rhs) -> uint256_t {
  36. return lhs() & rhs;
  37. }
  38. inline auto square(const Modulo25519& lhs) -> Modulo25519 {
  39. static const BarrettReduction<256> P{EllipticCurve::P};
  40. uint256_t hi, lo;
  41. square(lhs(), hi, lo);
  42. return uint512_t{hi, lo} % P;
  43. }
  44. inline auto exponentiate(const Modulo25519& lhs, uint256_t exponent) -> Modulo25519 {
  45. if(exponent == 0) return 1;
  46. Modulo25519 value = square(exponentiate(lhs, exponent >> 1));
  47. if(exponent & 1) value = value * lhs;
  48. return value;
  49. }
  50. inline auto reciprocal(const Modulo25519& lhs) -> Modulo25519 {
  51. return exponentiate(lhs, P - 2);
  52. }
  53. inline auto squareRoot(const Modulo25519& lhs) -> Modulo25519 {
  54. static const Modulo25519 I = exponentiate(Modulo25519(2), P - 1 >> 2); //I = sqrt(-1)
  55. Modulo25519 value = exponentiate(lhs, P + 3 >> 3);
  56. if(square(value) - lhs) value = value * I;
  57. if(value & 1) value = -value;
  58. return value;
  59. }
  60. inline auto cmove(bool condition, Modulo25519& lhs, const Modulo25519& rhs) -> void {
  61. if(condition) lhs = rhs;
  62. }
  63. inline auto cswap(bool condition, Modulo25519& lhs, Modulo25519& rhs) -> void {
  64. if(condition) swap(lhs, rhs);
  65. }
  66. }