x25519 function
Core X25519 function: computes X25519(k, u) per RFC 7748 sec. 5.
scalar32 is the 32-byte scalar (clamped internally); uCoordinate32 is
the 32-byte little-endian u-coordinate. Returns 32 bytes little-endian.
Implementation
Uint8List x25519(Uint8List scalar32, Uint8List uCoordinate32) {
if (scalar32.length != 32) {
throw ArgumentError('scalar must be 32 bytes, got ${scalar32.length}');
}
if (uCoordinate32.length != 32) {
throw ArgumentError(
'u-coordinate must be 32 bytes, got ${uCoordinate32.length}',
);
}
final BigInt k = _decodeScalar(scalar32);
final BigInt u = _decodeUCoordinate(uCoordinate32);
final BigInt x1 = u;
BigInt x2 = BigInt.one;
BigInt z2 = BigInt.zero;
BigInt x3 = u;
BigInt z3 = BigInt.one;
int swap = 0;
for (int t = _bits - 1; t >= 0; t--) {
final int kT = ((k >> t) & BigInt.one).toInt();
swap ^= kT;
List<BigInt> s;
s = _cswap(swap, x2, x3);
x2 = s[0];
x3 = s[1];
s = _cswap(swap, z2, z3);
z2 = s[0];
z3 = s[1];
swap = kT;
final BigInt a = (x2 + z2) % _p;
final BigInt aa = (a * a) % _p;
final BigInt b = (x2 - z2) % _p;
final BigInt bb = (b * b) % _p;
final BigInt e = (aa - bb) % _p;
final BigInt c = (x3 + z3) % _p;
final BigInt d = (x3 - z3) % _p;
final BigInt da = (d * a) % _p;
final BigInt cb = (c * b) % _p;
final BigInt x3New = (da + cb) % _p;
x3 = (x3New * x3New) % _p;
final BigInt z3Diff = (da - cb) % _p;
z3 = (x1 * ((z3Diff * z3Diff) % _p)) % _p;
x2 = (aa * bb) % _p;
z2 = (e * ((aa + (_a24 * e) % _p) % _p)) % _p;
}
// Final conditional swap.
List<BigInt> s;
s = _cswap(swap, x2, x3);
x2 = s[0];
x3 = s[1];
s = _cswap(swap, z2, z3);
z2 = s[0];
z3 = s[1];
// Normalize results modulo p (subtraction above can yield negatives).
final BigInt resultNum = (x2 % _p + _p) % _p;
final BigInt resultDen = (z2 % _p + _p) % _p;
final BigInt result = (resultNum * _inv(resultDen)) % _p;
return _encodeUCoordinate(result);
}