mirror of https://github.com/bsnes-emu/bsnes.git
80 lines
1.9 KiB
C++
80 lines
1.9 KiB
C++
#pragma once
|
|
|
|
#include <nall/arithmetic/barrett.hpp>
|
|
|
|
namespace nall { namespace EllipticCurve {
|
|
|
|
static const uint256_t P = (1_u256 << 255) - 19;
|
|
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
|
|
|
|
static BarrettReduction modP{P};
|
|
static BarrettReduction modL{L};
|
|
|
|
struct Modulo25519 : uint256_t {
|
|
using type = Modulo25519;
|
|
using uint256_t::uint256_t;
|
|
|
|
alwaysinline auto operator()() const -> uint256_t {
|
|
return *this;
|
|
}
|
|
|
|
alwaysinline auto operator-() const -> type {
|
|
return P.operator-(*this);
|
|
}
|
|
|
|
template<typename T> alwaysinline auto operator+(const T& rhs) const -> type {
|
|
auto lhs = (uint512_t)*this + rhs;
|
|
if(lhs >= P) lhs -= P;
|
|
return lhs;
|
|
}
|
|
|
|
template<typename T> alwaysinline auto operator-(const T& rhs) const -> type {
|
|
auto lhs = (uint512_t)*this;
|
|
if(lhs < rhs) lhs += P;
|
|
return lhs - rhs;
|
|
}
|
|
|
|
template<typename T> alwaysinline auto operator*(const T& rhs) const -> type {
|
|
uint256_t hi, lo;
|
|
nall::mul(*this, rhs, hi, lo);
|
|
return modP(uint512_t{hi, lo});
|
|
}
|
|
|
|
alwaysinline auto square() const -> type {
|
|
uint256_t hi, lo;
|
|
nall::square(*this, hi, lo);
|
|
return modP(uint512_t{hi, lo});
|
|
}
|
|
|
|
inline auto expmod(uint256_t e) const -> type {
|
|
type x = 1;
|
|
for(auto n : rrange(256)) {
|
|
x = x.square();
|
|
if(e >> n & 1) x = operator*(x);
|
|
}
|
|
return x;
|
|
}
|
|
|
|
inline auto reciprocal() const -> type {
|
|
return expmod(P - 2);
|
|
}
|
|
|
|
inline auto squareRoot() const -> type {
|
|
static const type i = type(2).expmod((P - 1) >> 2); //i = sqrt(-1)
|
|
type x = expmod((P + 3) >> 3);
|
|
if(operator!=(x.square())) x = x * i;
|
|
if(x & 1) x = -x;
|
|
return x;
|
|
}
|
|
};
|
|
|
|
inline auto cmove(bool bit, Modulo25519& lhs, const Modulo25519& rhs) -> void {
|
|
if(bit) lhs = rhs;
|
|
}
|
|
|
|
inline auto cswap(bool bit, Modulo25519& lhs, Modulo25519& rhs) -> void {
|
|
if(bit) swap(lhs, rhs);
|
|
}
|
|
|
|
}}
|