2016-10-27 21:16:58 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#if defined(EC_REFERENCE)
|
|
|
|
#include <nall/elliptic-curve/modulo25519-reference.hpp>
|
|
|
|
#else
|
2018-10-04 10:11:23 +00:00
|
|
|
#include <nall/elliptic-curve/modulo25519-optimized.hpp>
|
2016-10-27 21:16:58 +00:00
|
|
|
#endif
|
|
|
|
|
2019-01-16 00:46:42 +00:00
|
|
|
namespace nall::EllipticCurve {
|
2016-10-27 21:16:58 +00:00
|
|
|
|
|
|
|
struct Curve25519 {
|
|
|
|
auto sharedKey(uint256_t secretKey, uint256_t basepoint = 9) const -> uint256_t {
|
2018-10-04 10:11:23 +00:00
|
|
|
secretKey &= (1_u256 << 254) - 8;
|
|
|
|
secretKey |= (1_u256 << 254);
|
|
|
|
basepoint &= ~0_u256 >> 1;
|
2016-10-27 21:16:58 +00:00
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
point p = scalarMultiply(basepoint % P, secretKey);
|
|
|
|
field k = p.x * reciprocal(p.z);
|
|
|
|
return k();
|
2016-10-27 21:16:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
using field = Modulo25519;
|
|
|
|
struct point { field x, z; };
|
2018-10-04 10:11:23 +00:00
|
|
|
const BarrettReduction<256> P = BarrettReduction<256>{EllipticCurve::P};
|
2016-10-27 21:16:58 +00:00
|
|
|
|
|
|
|
inline auto montgomeryDouble(point p) const -> point {
|
2018-10-04 10:11:23 +00:00
|
|
|
field a = square(p.x + p.z);
|
|
|
|
field b = square(p.x - p.z);
|
2016-10-27 21:16:58 +00:00
|
|
|
field c = a - b;
|
|
|
|
field d = a + c * 121665;
|
|
|
|
return {a * b, c * d};
|
|
|
|
}
|
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
inline auto montgomeryAdd(point p, point q, field b) const -> point {
|
|
|
|
return {
|
|
|
|
square(p.x * q.x - p.z * q.z),
|
|
|
|
square(p.x * q.z - p.z * q.x) * b
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
inline auto scalarMultiply(field b, uint256_t exponent) const -> point {
|
2016-10-27 21:16:58 +00:00
|
|
|
point p{1, 0}, q{b, 1};
|
2018-10-04 10:11:23 +00:00
|
|
|
for(uint bit : reverse(range(255))) {
|
|
|
|
bool condition = exponent >> bit & 1;
|
|
|
|
cswap(condition, p.x, q.x);
|
|
|
|
cswap(condition, p.z, q.z);
|
2016-10-27 21:16:58 +00:00
|
|
|
q = montgomeryAdd(p, q, b);
|
|
|
|
p = montgomeryDouble(p);
|
2018-10-04 10:11:23 +00:00
|
|
|
cswap(condition, p.x, q.x);
|
|
|
|
cswap(condition, p.z, q.z);
|
2016-10-27 21:16:58 +00:00
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-16 00:46:42 +00:00
|
|
|
}
|