import nodeCrypto from 'crypto' ; const _0n = BigInt ( 0 ) ; const _1n = BigInt ( 1 ) ; const _2n = BigInt ( 2 ) ; const _255n = BigInt ( 255 ) ; /**
 * ed25519 is Twisted Edwards curve with equation of
 * ```
 * −x² + y² = 1 − (121665/121666) * x² * y²
 * ```
 */ const CURVE = { a : BigInt ( - 1 ) , d : BigInt ( '37095705934669439343138083508754565189542113879843219016388785533085940283555' ) , P : _2n ** _255n - BigInt ( 19 ) , n : _2n ** BigInt ( 252 ) + BigInt ( '27742317777372353535851937790883648493' ) , h : BigInt ( 8 ) , Gx : BigInt ( '15112221349535400772501151409588531511454012693041857206046113283949847762202' ) , Gy : BigInt ( '46316835694926478169428394003475163141307993866256225615783033603165251855960' ) , } ; export { CURVE } ; type Hex = Uint8Array | string ; type PrivKey = Hex | bigint | number ; type PubKey = Hex | Point ; type SigType = Hex | Signature ; const SQRT_M1 = BigInt ( '19681161376707505956807079304988542015446066515923890162744021073123829784752' ) ; const SQRT_D = BigInt ( '6853475219497561581579357271197624642482790079785650197046958215289687604742' ) ; const SQRT_AD_MINUS_ONE = BigInt ( '25063068953384623474111414158702152701244531502492656460079210482610430750235' ) ; const INVSQRT_A_MINUS_D = BigInt ( '54469307008909316920995813868745141605393597292927456921205312896311721017578' ) ; const ONE_MINUS_D_SQ = BigInt ( '1159843021668779879193775521855586647937357759715417654439879720876111806838' ) ; const D_MINUS_ONE_SQ = BigInt ( '40440834346308536858101042469323190826248399146238708352240133220865137265952' ) ; /**
 * Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy).
 * Default Point works in affine coordinates: (x, y)
 * https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates
 */ class ExtendedPoint { constructor ( readonly x , readonly y , readonly z , readonly t ) { } static BASE = new ExtendedPoint ( CURVE . Gx , CURVE . Gy , _1n , mod ( CURVE . Gx * CURVE . Gy ) ) ; static ZERO = new ExtendedPoint ( _0n , _1n , _1n , _0n ) ; static fromAffine ( p ) { if ( ! ( p instanceof Point ) ) { throw new TypeError ( 'ExtendedPoint#fromAffine: expected Point' ) ; } if ( p . equals ( Point . ZERO ) ) return ExtendedPoint . ZERO ; return new ExtendedPoint ( p . x , p . y , _1n , mod ( p . x * p . y ) ) ; } static toAffineBatch ( points ) { const toInv = invertBatch ( points . map ( ( p ) => p . z ) ) ; return points . map ( ( p , i ) => p . toAffine ( toInv [ i ] ) ) ; } static normalizeZ ( points ) { return this . toAffineBatch ( points ) . map ( this . fromAffine ) ; } static fromRistrettoHash ( hash ) { hash = ensureBytes ( hash ) ; assertLen ( 64 , hash ) ; const r1 = bytes255ToNumberLE ( hash . slice ( 0 , 32 ) ) ; const R1 = this . calcElligatorRistrettoMap ( r1 ) ; const r2 = bytes255ToNumberLE ( hash . slice ( 32 , 64 ) ) ; const R2 = this . calcElligatorRistrettoMap ( r2 ) ; return R1 . add ( R2 ) ; } private static calcElligatorRistrettoMap ( r0 ) { const { d } = CURVE ; const r = mod ( SQRT_M1 * r0 * r0 ) ; const Ns = mod ( ( r + _1n ) * ONE_MINUS_D_SQ ) ; let c = BigInt ( - 1 ) ; const D = mod ( ( c - d * r ) * mod ( r + d ) ) ; let { isValid : Ns_D_is_sq , value : s } = uvRatio ( Ns , D ) ; let s_ = mod ( s * r0 ) ; if ( ! edIsNegative ( s_ ) ) s_ = mod ( - s_ ) ; if ( ! Ns_D_is_sq ) s = s_ ; if ( ! Ns_D_is_sq ) c = r ; const Nt = mod ( c * ( r - _1n ) * D_MINUS_ONE_SQ - D ) ; const s2 = s * s ; const W0 = mod ( ( s + s ) * D ) ; const W1 = mod ( Nt * SQRT_AD_MINUS_ONE ) ; const W2 = mod ( _1n - s2 ) ; const W3 = mod ( _1n + s2 ) ; return new ExtendedPoint ( mod ( W0 * W3 ) , mod ( W2 * W1 ) , mod ( W1 * W3 ) , mod ( W0 * W2 ) ) ; } static fromRistrettoBytes ( bytes ) { bytes = ensureBytes ( bytes ) ; assertLen ( 32 , bytes ) ; const { a , d } = CURVE ; const emsg = 'ExtendedPoint.fromRistrettoBytes: Cannot convert bytes to Ristretto Point' ; const s = bytes255ToNumberLE ( bytes ) ; if ( ! equalBytes ( numberToBytesLEPadded ( s , 32 ) , bytes ) || edIsNegative ( s ) ) throw new Error ( emsg ) ; const s2 = mod ( s * s ) ; const u1 = mod ( _1n + a * s2 ) ; const u2 = mod ( _1n - a * s2 ) ; const u1_2 = mod ( u1 * u1 ) ; const u2_2 = mod ( u2 * u2 ) ; const v = mod ( a * d * u1_2 - u2_2 ) ; const { isValid , value : I } = invertSqrt ( mod ( v * u2_2 ) ) ; const Dx = mod ( I * u2 ) ; const Dy = mod ( I * Dx * v ) ; let x = mod ( ( s + s ) * Dx ) ; if ( edIsNegative ( x ) ) x = mod ( - x ) ; const y = mod ( u1 * Dy ) ; const t = mod ( x * y ) ; if ( ! isValid || edIsNegative ( t ) || y === _0n ) throw new Error ( emsg ) ; return new ExtendedPoint ( x , y , _1n , t ) ; } toRistrettoBytes ( ) { let { x , y , z , t } = this ; const u1 = mod ( mod ( z + y ) * mod ( z - y ) ) ; const u2 = mod ( x * y ) ; const { value : invsqrt } = invertSqrt ( mod ( u1 * u2 ** _2n ) ) ; const D1 = mod ( invsqrt * u1 ) ; const D2 = mod ( invsqrt * u2 ) ; const zInv = mod ( D1 * D2 * t ) ; let D ; if ( edIsNegative ( t * zInv ) ) { let _x = mod ( y * SQRT_M1 ) ; let _y = mod ( x * SQRT_M1 ) ; x = _x ; y = _y ; D = mod ( D1 * INVSQRT_A_MINUS_D ) ; } else { D = D2 ; } if ( edIsNegative ( x * zInv ) ) y = mod ( - y ) ; let s = mod ( ( z - y ) * D ) ; if ( edIsNegative ( s ) ) s = mod ( - s ) ; return numberToBytesLEPadded ( s , 32 ) ; } equals ( other ) { const a = this ; const b = other ; return mod ( a . t * b . z ) === mod ( b . t * a . z ) ; } negate ( ) { return new ExtendedPoint ( mod ( - this . x ) , this . y , this . z , mod ( - this . t ) ) ; } double ( ) { const X1 = this . x ; const Y1 = this . y ; const Z1 = this . z ; const { a } = CURVE ; const A = mod ( X1 ** _2n ) ; const B = mod ( Y1 ** _2n ) ; const C = mod ( _2n * Z1 ** _2n ) ; const D = mod ( a * A ) ; const E = mod ( ( X1 + Y1 ) ** _2n - A - B ) ; const G = mod ( D + B ) ; const F = mod ( G - C ) ; const H = mod ( D - B ) ; const X3 = mod ( E * F ) ; const Y3 = mod ( G * H ) ; const T3 = mod ( E * H ) ; const Z3 = mod ( F * G ) ; return new ExtendedPoint ( X3 , Y3 , Z3 , T3 ) ; } add ( other ) { const X1 = this . x ; const Y1 = this . y ; const Z1 = this . z ; const T1 = this . t ; const X2 = other . x ; const Y2 = other . y ; const Z2 = other . z ; const T2 = other . t ; const A = mod ( ( Y1 - X1 ) * ( Y2 + X2 ) ) ; const B = mod ( ( Y1 + X1 ) * ( Y2 - X2 ) ) ; const F = mod ( B - A ) ; if ( F === _0n ) { return this . double ( ) ; } const C = mod ( Z1 * _2n * T2 ) ; const D = mod ( T1 * _2n * Z2 ) ; const E = mod ( D + C ) ; const G = mod ( B + A ) ; const H = mod ( D - C ) ; const X3 = mod ( E * F ) ; const Y3 = mod ( G * H ) ; const T3 = mod ( E * H ) ; const Z3 = mod ( F * G ) ; return new ExtendedPoint ( X3 , Y3 , Z3 , T3 ) ; } subtract ( other ) { return this . add ( other . negate ( ) ) ; } multiplyUnsafe ( scalar ) { let n = normalizeScalar ( scalar ) ; const P0 = ExtendedPoint . ZERO ; if ( this . equals ( P0 ) || n === _1n ) return this ; let p = P0 ; let d = this ; while ( n > _0n ) { if ( n & _1n ) p = p . add ( d ) ; d = d . double ( ) ; n >>= _1n ; } return p ; } private precomputeWindow ( W ) { const windows = 256 / W + 1 ; let points = [ ] ; let p = this ; let base = p ; for ( let window = 0 ; window < windows ; window ++ ) { base = p ; points . push ( base ) ; for ( let i = 1 ; i < 2 ** ( W - 1 ) ; i ++ ) { base = base . add ( p ) ; points . push ( base ) ; } p = base . double ( ) ; } return points ; } private wNAF ( n , affinePoint ? ) { if ( ! affinePoint && this . equals ( ExtendedPoint . BASE ) ) affinePoint = Point . BASE ; const W = ( affinePoint && affinePoint . _WINDOW_SIZE ) || 1 ; if ( 256 % W ) { throw new Error ( 'Point#wNAF: Invalid precomputation window, must be power of 2' ) ; } let precomputes = affinePoint && pointPrecomputes . get ( affinePoint ) ; if ( ! precomputes ) { precomputes = this . precomputeWindow ( W ) ; if ( affinePoint && W !== 1 ) { precomputes = ExtendedPoint . normalizeZ ( precomputes ) ; pointPrecomputes . set ( affinePoint , precomputes ) ; } } let p = ExtendedPoint . ZERO ; let f = ExtendedPoint . ZERO ; const windows = 256 / W + 1 ; const windowSize = 2 ** ( W - 1 ) ; const mask = BigInt ( 2 ** W - 1 ) ; const maxNumber = 2 ** W ; const shiftBy = BigInt ( W ) ; for ( let window = 0 ; window < windows ; window ++ ) { const offset = window * windowSize ; let wbits = Number ( n & mask ) ; n >>= shiftBy ; if ( wbits > windowSize ) { wbits -= maxNumber ; n += _1n ; } if ( wbits === 0 ) { let pr = precomputes [ offset ] ; if ( window % 2 ) pr = pr . negate ( ) ; f = f . add ( pr ) ; } else { let cached = precomputes [ offset + Math . abs ( wbits ) - 1 ] ; if ( wbits < 0 ) cached = cached . negate ( ) ; p = p . add ( cached ) ; } } return [ p , f ] ; } multiply ( scalar , affinePoint ? ) { const n = normalizeScalar ( scalar ) ; return ExtendedPoint . normalizeZ ( this . wNAF ( n , affinePoint ) ) [ 0 ] ; } toAffine ( invZ = invert ( this . z ) ) { const x = mod ( this . x * invZ ) ; const y = mod ( this . y * invZ ) ; return new Point ( x , y ) ; } } const pointPrecomputes = new WeakMap < Point , ExtendedPoint [ ] > ( ) ; /**
 * Default Point works in affine coordinates: (x, y)
 */ class Point { static BASE : Point = new Point ( CURVE . Gx , CURVE . Gy ) ; static ZERO : Point = new Point ( _0n , _1n ) ; _WINDOW_SIZE ? : number ; constructor ( readonly x , readonly y ) { } _setWindowSize ( windowSize ) { this . _WINDOW_SIZE = windowSize ; pointPrecomputes . delete ( this ) ; } static fromHex ( hex ) { const { d , P } = CURVE ; const bytes = ensureBytes ( hex ) ; assertLen ( 32 , bytes ) ; const normed = bytes . slice ( ) ; normed [ 31 ] = bytes [ 31 ] & ~ 0x80 ; const y = bytesToNumberLE ( normed ) ; if ( y >= P ) throw new Error ( 'Point.fromHex expects hex <= Fp' ) ; const y2 = mod ( y * y ) ; const u = mod ( y2 - _1n ) ; const v = mod ( d * y2 + _1n ) ; let { isValid , value : x } = uvRatio ( u , v ) ; if ( ! isValid ) throw new Error ( 'Point.fromHex: invalid y coordinate' ) ; const isXOdd = ( x & _1n ) === _1n ; const isLastByteOdd = ( bytes [ 31 ] & 0x80 ) !== 0 ; if ( isLastByteOdd !== isXOdd ) { x = mod ( - x ) ; } return new Point ( x , y ) ; } static async fromPrivateKey ( privateKey ) { return ( await getExtendedPublicKey ( privateKey ) ) . point ; } toRawBytes ( ) { const bytes = numberToBytesLEPadded ( this . y , 32 ) ; bytes [ 31 ] |= this . x & _1n ? 0x80 : 0 ; return bytes ; } toHex ( ) { return bytesToHex ( this . toRawBytes ( ) ) ; } returns toX25519 ( ) { const { y } = this ; return mod ( ( _1n + y ) * invert ( _1n - y ) ) ; } equals ( other ) { return this . x === other . x && this . y === other . y ; } negate ( ) { return new Point ( mod ( - this . x ) , this . y ) ; } add ( other ) { return ExtendedPoint . fromAffine ( this ) . add ( ExtendedPoint . fromAffine ( other ) ) . toAffine ( ) ; } subtract ( other ) { return this . add ( other . negate ( ) ) ; } param scalar returns multiply ( scalar ) { return ExtendedPoint . fromAffine ( this ) . multiply ( scalar , this ) . toAffine ( ) ; } } /**
 * EDDSA signature.
 */ class Signature { readonly s : bigint ; constructor ( readonly r , s ) { if ( ! ( r instanceof Point ) ) throw new Error ( 'Expected Point instance' ) ; this . s = normalizeScalar ( s ) ; } static fromHex ( hex ) { const bytes = ensureBytes ( hex ) ; assertLen ( 64 , bytes ) ; const r = Point . fromHex ( bytes . slice ( 0 , 32 ) ) ; const s = bytesToNumberLE ( bytes . slice ( 32 , 64 ) ) ; return new Signature ( r , s ) ; } toRawBytes ( ) { const u8 = new Uint8Array ( 64 ) ; u8 . set ( this . r . toRawBytes ( ) ) ; u8 . set ( numberToBytesLEPadded ( this . s , 32 ) , 32 ) ; return u8 ; } toHex ( ) { return bytesToHex ( this . toRawBytes ( ) ) ; } } export { ExtendedPoint , Point , Signature } ; function concatBytes ( ... arrays ) { if ( ! arrays . every ( ( a ) => a instanceof Uint8Array ) ) throw new Error ( 'Expected Uint8Array list' ) ; if ( arrays . length === 1 ) return arrays [ 0 ] ; const length = arrays . reduce ( ( a , arr ) => a + arr . length , 0 ) ; const result = new Uint8Array ( length ) ; for ( let i = 0 , pad = 0 ; i < arrays . length ; i ++ ) { const arr = arrays [ i ] ; result . set ( arr , pad ) ; pad += arr . length ; } return result ; } const hexes = Array . from ( { length : 256 } , ( v , i ) => i . toString ( 16 ) . padStart ( 2 , '0' ) ) ; function bytesToHex ( uint8a ) { let hex = '' ; for ( let i = 0 ; i < uint8a . length ; i ++ ) { hex += hexes [ uint8a [ i ] ] ; } return hex ; } function hexToBytes ( hex ) { if ( typeof hex !== 'string' ) { throw new TypeError ( 'hexToBytes: expected string, got ' + typeof hex ) ; } if ( hex . length % 2 ) throw new Error ( 'hexToBytes: received invalid unpadded hex' ) ; const array = new Uint8Array ( hex . length / 2 ) ; for ( let i = 0 ; i < array . length ; i ++ ) { const j = i * 2 ; const hexByte = hex . slice ( j , j + 2 ) ; const byte = Number . parseInt ( hexByte , 16 ) ; if ( Number . isNaN ( byte ) ) throw new Error ( 'Invalid byte sequence' ) ; array [ i ] = byte ; } return array ; } function numberToBytesBEPadded ( num , length ) { const hex = num . toString ( 16 ) . padStart ( length * 2 , '0' ) ; return hexToBytes ( hex ) ; } function numberToBytesLEPadded ( num , length ) { return numberToBytesBEPadded ( num , length ) . reverse ( ) ; } function edIsNegative ( num ) { return ( mod ( num ) & _1n ) === _1n ; } function bytesToNumberLE ( uint8a ) { if ( ! ( uint8a instanceof Uint8Array ) ) throw new Error ( `bytesToNumberLE: expected Uint8Array, got ${ uint8a }` ) ; let value = _0n ; const _8n = BigInt ( 8 ) ; for ( let i = 0 ; i < uint8a . length ; i ++ ) { value += BigInt ( uint8a [ i ] ) << ( _8n * BigInt ( i ) ) ; } return value ; } function bytes255ToNumberLE ( bytes ) { return mod ( bytesToNumberLE ( bytes ) & ( _2n ** _255n - _1n ) ) ; } function mod ( a , b = CURVE . P ) { const res = a % b ; return res >= _0n ? res : b + res ; } function powMod ( a , power , modulo ) { let res = 1n ; while ( power > 0n ) { if ( power & 1n ) res = ( res * a ) % modulo ; a = ( a * a ) % modulo ; power >>= 1n ; } return res ; } function invert ( number , modulo = CURVE . P ) { if ( number === _0n || modulo <= _0n ) { throw new Error ( `invert: expected positive integers, got n=${ number } mod=${ modulo }` ) ; } let a = mod ( number , modulo ) ; let b = modulo ; let x = _0n , y = _1n , u = _1n , v = _0n ; while ( a !== _0n ) { const q = b / a ; const r = b % a ; const m = x - u * q ; const n = y - v * q ; b = a , a = r , x = u , y = v , u = m , v = n ; } const gcd = b ; if ( gcd !== _1n ) throw new Error ( 'invert: does not exist' ) ; return mod ( x , modulo ) ; } function invertBatch ( nums , modulo = CURVE . P ) { const len = nums . length ; const scratch = new Array ( len ) ; let acc = _1n ; for ( let i = 0 ; i < len ; i ++ ) { if ( nums [ i ] === _0n ) continue ; scratch [ i ] = acc ; acc = mod ( acc * nums [ i ] , modulo ) ; } acc = invert ( acc , modulo ) ; for ( let i = len - 1 ; i >= 0 ; i -- ) { if ( nums [ i ] === _0n ) continue ; let tmp = mod ( acc * nums [ i ] , modulo ) ; nums [ i ] = mod ( acc * scratch [ i ] , modulo ) ; acc = tmp ; } return nums ; } function pow2 ( x , power ) { const { P } = CURVE ; let res = x ; while ( power -- > _0n ) { res *= res ; res %= P ; } return res ; } function pow_2_252_3 ( x ) { const { P } = CURVE ; const _5n = BigInt ( 5 ) ; const _10n = BigInt ( 10 ) ; const _20n = BigInt ( 20 ) ; const _40n = BigInt ( 40 ) ; const _80n = BigInt ( 80 ) ; const x2 = ( x * x ) % P ; const b2 = ( x2 * x ) % P ; const b4 = ( pow2 ( b2 , _2n ) * b2 ) % P ; const b5 = ( pow2 ( b4 , _1n ) * x ) % P ; const b10 = ( pow2 ( b5 , _5n ) * b5 ) % P ; const b20 = ( pow2 ( b10 , _10n ) * b10 ) % P ; const b40 = ( pow2 ( b20 , _20n ) * b20 ) % P ; const b80 = ( pow2 ( b40 , _40n ) * b40 ) % P ; const b160 = ( pow2 ( b80 , _80n ) * b80 ) % P ; const b240 = ( pow2 ( b160 , _80n ) * b80 ) % P ; const b250 = ( pow2 ( b240 , _10n ) * b10 ) % P ; const pow_p_5_8 = ( pow2 ( b250 , _2n ) * x ) % P ; return { pow_p_5_8 , b2 } ; } function uvRatio ( u , v ) { const v3 = mod ( v * v * v ) ; const v7 = mod ( v3 * v3 * v ) ; const pow = pow_2_252_3 ( u * v7 ) . pow_p_5_8 ; let x = mod ( u * v3 * pow ) ; const vx2 = mod ( v * x * x ) ; const root1 = x ; const root2 = mod ( x * SQRT_M1 ) ; const useRoot1 = vx2 === u ; const useRoot2 = vx2 === mod ( - u ) ; const noRoot = vx2 === mod ( - u * SQRT_M1 ) ; if ( useRoot1 ) x = root1 ; if ( useRoot2 || noRoot ) x = root2 ; if ( edIsNegative ( x ) ) x = mod ( - x ) ; return { isValid : useRoot1 || useRoot2 , value : x } ; } function invertSqrt ( number ) { return uvRatio ( _1n , number ) ; } async function sha512ModnLE ( ... args ) { const messageArray = concatBytes ( ... args ) ; const hash = await utils . sha512 ( messageArray ) ; const value = bytesToNumberLE ( hash ) ; return mod ( value , CURVE . n ) ; } function equalBytes ( b1 , b2 ) { if ( b1 . length !== b2 . length ) { return false ; } for ( let i = 0 ; i < b1 . length ; i ++ ) { if ( b1 [ i ] !== b2 [ i ] ) { return false ; } } return true ; } function ensureBytes ( hash ) { return hash instanceof Uint8Array ? hash : hexToBytes ( hash ) ; } function assertLen ( len , bytes ) { if ( bytes . length !== len ) throw new Error ( `Expected ${ len } bytes` ) ; } function normalizeScalar ( num , max = CURVE . n ) { if ( typeof num === 'number' && num > 0 && Number . isSafeInteger ( num ) ) return BigInt ( num ) ; if ( typeof num === 'bigint' && _0n < num && num < max ) return num ; throw new TypeError ( 'Expected valid scalar: 0 < scalar < max' ) ; } function normalizePrivateKey ( key ) { const bytes = typeof key === 'bigint' || typeof key === 'number' ? numberToBytesBEPadded ( normalizeScalar ( key , _2n ** BigInt ( 256 ) ) , 32 ) : ensureBytes ( key ) ; assertLen ( 32 , bytes ) ; return bytes ; } function decodeScalar25519 ( n ) { n = ensureBytes ( n ) ; assertLen ( 32 , n ) ; const _n = n . slice ( ) ; _n [ 0 ] &= 248 ; _n [ 31 ] &= 127 ; _n [ 31 ] |= 64 ; return bytesToNumberLE ( _n ) ; } async function getExtendedPublicKey ( key ) { const hashed = await utils . sha512 ( normalizePrivateKey ( key ) ) ; const head = hashed . slice ( 0 , 32 ) ; const prefix = hashed . slice ( 32 , 64 ) ; const scalar = mod ( decodeScalar25519 ( head ) , CURVE . n ) ; const point = Point . BASE . multiply ( scalar ) ; const pubBytes = point . toRawBytes ( ) ; return { head , prefix , scalar , point , pubBytes } ; } /**
 * Calculates ed25519 public key.
 * 1. private key is hashed with sha512, then first 32 bytes are taken from the hash
 * 2. 3 least significant bits of the first byte are cleared
 * RFC8032 5.1.5
 */ export async function getPublicKey ( privateKey ) { return ( await getExtendedPublicKey ( privateKey ) ) . pubBytes ; } /**
 * Signs message with privateKey.
 * RFC8032 5.1.6
 */ export async function sign ( message , privateKey ) { const msg = ensureBytes ( message ) ; const { prefix , scalar : p , pubBytes } = await getExtendedPublicKey ( privateKey ) ; const r = await sha512ModnLE ( prefix , msg ) ; const R = Point . BASE . multiply ( r ) ; const k = await sha512ModnLE ( R . toRawBytes ( ) , pubBytes , msg ) ; const S = mod ( r + k * p , CURVE . n ) ; return new Signature ( R , S ) . toRawBytes ( ) ; } /**
 * Verifies ed25519 signature against message and public key.
 * An extended group equation is checked.
 * RFC8032 5.1.7
 */ export async function verify ( sig , message , publicKey ) { message = ensureBytes ( message ) ; if ( ! ( publicKey instanceof Point ) ) publicKey = Point . fromHex ( publicKey ) ; if ( ! ( sig instanceof Signature ) ) sig = Signature . fromHex ( sig ) ; const SB = ExtendedPoint . BASE . multiply ( sig . s ) ; const k = await sha512ModnLE ( sig . r . toRawBytes ( ) , publicKey . toRawBytes ( ) , message ) ; const kA = ExtendedPoint . fromAffine ( publicKey ) . multiplyUnsafe ( k ) ; const RkA = ExtendedPoint . fromAffine ( sig . r ) . add ( kA ) ; return RkA . subtract ( SB ) . multiplyUnsafe ( CURVE . h ) . equals ( ExtendedPoint . ZERO ) ; } param privateKey param publicKey returns export async function getSharedSecret ( privateKey , publicKey ) { const { scalar : p } = await getExtendedPublicKey ( privateKey ) ; const u = Point . fromHex ( publicKey ) . toX25519 ( ) ; return montgomeryLadderChecked ( p , u ) ; } Point . BASE . _setWindowSize ( 8 ) ; function cswap ( swap , x_2 , x_3 ) { const dummy = mod ( swap * ( x_2 - x_3 ) ) ; x_2 = mod ( x_2 - dummy ) ; x_3 = mod ( x_3 + dummy ) ; return [ x_2 , x_3 ] ; } param pointU param scalar returns function montgomeryLadder ( pointU , scalar ) { const { P , n } = CURVE ; const u = normalizeScalar ( pointU , P ) ; const k = normalizeScalar ( scalar , P ) ; const a24 = BigInt ( 121665 ) ; const x_1 = u ; let x_2 = _1n ; let z_2 = _0n ; let x_3 = u ; let z_3 = _1n ; let swap = _0n ; let sw ; for ( let t = BigInt ( 255 - 1 ) ; t >= _0n ; t -- ) { const k_t = ( k >> t ) & 1n ; swap ^= k_t ; sw = cswap ( swap , x_2 , x_3 ) ; x_2 = sw [ 0 ] ; x_3 = sw [ 1 ] ; sw = cswap ( swap , z_2 , z_3 ) ; z_2 = sw [ 0 ] ; z_3 = sw [ 1 ] ; swap = k_t ; const A = mod ( x_2 + z_2 ) ; const AA = mod ( A * A ) ; const B = mod ( x_2 - z_2 ) ; const BB = mod ( B * B ) ; const E = mod ( AA - BB ) ; const C = mod ( x_3 + z_3 ) ; const D = mod ( x_3 - z_3 ) ; const DA = mod ( D * A ) ; const CB = mod ( C * B ) ; x_3 = mod ( mod ( DA + CB ) ** 2n ) ; z_3 = mod ( x_1 * mod ( DA - CB ) ** 2n ) ; x_2 = mod ( AA * BB ) ; z_2 = mod ( E * ( AA + mod ( a24 * E ) ) ) ; } sw = cswap ( swap , x_2 , x_3 ) ; x_2 = sw [ 0 ] ; x_3 = sw [ 1 ] ; sw = cswap ( swap , z_2 , z_3 ) ; z_2 = sw [ 0 ] ; z_3 = sw [ 1 ] ; const { pow_p_5_8 , b2 } = pow_2_252_3 ( z_2 ) ; const xp2 = mod ( pow2 ( pow_p_5_8 , BigInt ( 3 ) ) * b2 ) ; return mod ( x_2 * xp2 ) ; } function encodeUCoordinate ( u ) { return numberToBytesLEPadded ( mod ( u , CURVE . P ) , 32 ) ; } function montgomeryLadderChecked ( u , p ) { const pu = montgomeryLadder ( u , p ) ; if ( pu === 0n ) throw new Error ( 'Invalid private or public key received' ) ; return encodeUCoordinate ( pu ) ; } function decodeUCoordinate ( uEnc ) { const _s = ensureBytes ( uEnc ) ; assertLen ( 32 , _s ) ; _s [ 31 ] &= 127 ; return bytesToNumberLE ( _s ) ; } export const curve25519 = { BASE_POINT_U : '0900000000000000000000000000000000000000000000000000000000000000' , scalarMult ( privateKey , publicKey ) { const u = decodeUCoordinate ( publicKey ) ; const p = decodeScalar25519 ( privateKey ) ; return montgomeryLadderChecked ( u , p ) ; } , scalarMultBase ( privateKey ) { return curve25519 . scalarMult ( privateKey , curve25519 . BASE_POINT_U ) ; } , } ; declare const self ; const crypto = { node : nodeCrypto , web : typeof self === 'object' && 'crypto' in self ? self . crypto : undefined , } ; export const utils = { TORSION_SUBGROUP : [ '0100000000000000000000000000000000000000000000000000000000000000' , 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a' , '0000000000000000000000000000000000000000000000000000000000000080' , '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05' , 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f' , '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85' , '0000000000000000000000000000000000000000000000000000000000000000' , 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa' , ] , bytesToHex , getExtendedPublicKey , randomBytes : ( bytesLength = 32 ) : Uint8Array => { if ( crypto . web ) { return crypto . web . getRandomValues ( new Uint8Array ( bytesLength ) ) ; } else if ( crypto . node ) { const { randomBytes } = crypto . node ; return new Uint8Array ( randomBytes ( bytesLength ) . buffer ) ; } else { throw new Error ( "The environment doesn't have randomBytes function" ) ; } } , randomPrivateKey : ( ) : Uint8Array => { return utils . randomBytes ( 32 ) ; } , sha512 : async ( message ) : Promise < Uint8Array > => { if ( crypto . web ) { const buffer = await crypto . web . subtle . digest ( 'SHA-512' , message . buffer ) ; return new Uint8Array ( buffer ) ; } else if ( crypto . node ) { return Uint8Array . from ( crypto . node . createHash ( 'sha512' ) . update ( message ) . digest ( ) ) ; } else { throw new Error ( "The environment doesn't have sha512 function" ) ; } } , precompute ( windowSize = 8 , point = Point . BASE ) { const cached = point . equals ( Point . BASE ) ? point : new Point ( point . x , point . y ) ; cached . _setWindowSize ( windowSize ) ; cached . multiply ( _1n ) ; return cached ; } , } ;