Merge pull request #85 from sublimator/nd-impl-group-x-for-x-in-decafpoint-ristrettopoint-2023-09-20

feat: impl Group<X> for X in DecafPoint/RistrettoPoint
This commit is contained in:
Paul Miller 2023-09-20 21:06:36 +02:00 committed by GitHub
commit 2b41e387de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 4 deletions

@ -13,7 +13,7 @@ import {
numberToBytesLE, numberToBytesLE,
} from './abstract/utils.js'; } from './abstract/utils.js';
import { createHasher, htfBasicOpts, expand_message_xmd } from './abstract/hash-to-curve.js'; import { createHasher, htfBasicOpts, expand_message_xmd } from './abstract/hash-to-curve.js';
import { AffinePoint } from './abstract/curve.js'; import { AffinePoint, Group } from './abstract/curve.js';
/** /**
* ed25519 Twisted Edwards curve with following addons: * ed25519 Twisted Edwards curve with following addons:
@ -343,7 +343,7 @@ function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint {
* but it should work in its own namespace: do not combine those two. * but it should work in its own namespace: do not combine those two.
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
*/ */
class RistPoint { class RistPoint implements Group<RistPoint> {
static BASE: RistPoint; static BASE: RistPoint;
static ZERO: RistPoint; static ZERO: RistPoint;
// Private property to discourage combining ExtendedPoint + RistrettoPoint // Private property to discourage combining ExtendedPoint + RistrettoPoint
@ -471,6 +471,14 @@ class RistPoint {
multiplyUnsafe(scalar: bigint): RistPoint { multiplyUnsafe(scalar: bigint): RistPoint {
return new RistPoint(this.ep.multiplyUnsafe(scalar)); return new RistPoint(this.ep.multiplyUnsafe(scalar));
} }
double(): RistPoint {
return new RistPoint(this.ep.double());
}
negate(): RistPoint {
return new RistPoint(this.ep.negate());
}
} }
export const RistrettoPoint = /* @__PURE__ */ (() => { export const RistrettoPoint = /* @__PURE__ */ (() => {
if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE); if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE);

@ -13,7 +13,7 @@ import {
Hex, Hex,
numberToBytesLE, numberToBytesLE,
} from './abstract/utils.js'; } from './abstract/utils.js';
import { AffinePoint } from './abstract/curve.js'; import { AffinePoint, Group } from './abstract/curve.js';
/** /**
* Edwards448 (not Ed448-Goldilocks) curve with following addons: * Edwards448 (not Ed448-Goldilocks) curve with following addons:
@ -166,12 +166,14 @@ export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Ar
const _1n = BigInt(1); const _1n = BigInt(1);
return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))); return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
} }
export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated export const edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version // TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
// Hash To Curve Elligator2 Map // Hash To Curve Elligator2 Map
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
const ELL2_J = BigInt(156326); const ELL2_J = BigInt(156326);
function map_to_curve_elligator2_curve448(u: bigint) { function map_to_curve_elligator2_curve448(u: bigint) {
let tv1 = Fp.sqr(u); // 1. tv1 = u^2 let tv1 = Fp.sqr(u); // 1. tv1 = u^2
let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1 let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
@ -201,6 +203,7 @@ function map_to_curve_elligator2_curve448(u: bigint) {
y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3) y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1) return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
} }
function map_to_curve_elligator2_edwards448(u: bigint) { function map_to_curve_elligator2_edwards448(u: bigint) {
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2 let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
@ -326,7 +329,7 @@ function calcElligatorDecafMap(r0: bigint): ExtendedPoint {
* but it should work in its own namespace: do not combine those two. * but it should work in its own namespace: do not combine those two.
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
*/ */
class DcfPoint { class DcfPoint implements Group<DcfPoint> {
static BASE: DcfPoint; static BASE: DcfPoint;
static ZERO: DcfPoint; static ZERO: DcfPoint;
// Private property to discourage combining ExtendedPoint + DecafPoint // Private property to discourage combining ExtendedPoint + DecafPoint
@ -448,7 +451,16 @@ class DcfPoint {
multiplyUnsafe(scalar: bigint): DcfPoint { multiplyUnsafe(scalar: bigint): DcfPoint {
return new DcfPoint(this.ep.multiplyUnsafe(scalar)); return new DcfPoint(this.ep.multiplyUnsafe(scalar));
} }
double(): DcfPoint {
return new DcfPoint(this.ep.double());
} }
negate(): DcfPoint {
return new DcfPoint(this.ep.negate());
}
}
export const DecafPoint = /* @__PURE__ */ (() => { export const DecafPoint = /* @__PURE__ */ (() => {
// decaf448 base point is ed448 base x 2 // decaf448 base point is ed448 base x 2
// https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699