/**
 * Package x25519 implements X25519 key agreement.
 */ import { randomBytes , RandomSource } from "@stablelib/random" ; import { wipe } from "@stablelib/wipe" ; export const PUBLIC_KEY_LENGTH = 32 ; export const SECRET_KEY_LENGTH = 32 ; export const SHARED_KEY_LENGTH = 32 ; type GF = Float64Array ; function gf ( init ? ) { const r = new Float64Array ( 16 ) ; if ( init ) { for ( let i = 0 ; i < init . length ; i ++ ) { r [ i ] = init [ i ] ; } } return r ; } const _9 = new Uint8Array ( 32 ) ; _9 [ 0 ] = 9 ; const _121665 = gf ( [ 0xdb41 , 1 ] ) ; function car25519 ( o ) { let c = 1 ; for ( let i = 0 ; i < 16 ; i ++ ) { let v = o [ i ] + c + 65535 ; c = Math . floor ( v / 65536 ) ; o [ i ] = v - c * 65536 ; } o [ 0 ] += c - 1 + 37 * ( c - 1 ) ; } function sel25519 ( p , q , b ) { const c = ~ ( b - 1 ) ; for ( let i = 0 ; i < 16 ; i ++ ) { const t = c & ( p [ i ] ^ q [ i ] ) ; p [ i ] ^= t ; q [ i ] ^= t ; } } function pack25519 ( o , n ) { const m = gf ( ) ; const t = gf ( ) ; for ( let i = 0 ; i < 16 ; i ++ ) { t [ i ] = n [ i ] ; } car25519 ( t ) ; car25519 ( t ) ; car25519 ( t ) ; for ( let j = 0 ; j < 2 ; j ++ ) { m [ 0 ] = t [ 0 ] - 0xffed ; for ( let i = 1 ; i < 15 ; i ++ ) { m [ i ] = t [ i ] - 0xffff - ( ( m [ i - 1 ] >> 16 ) & 1 ) ; m [ i - 1 ] &= 0xffff ; } m [ 15 ] = t [ 15 ] - 0x7fff - ( ( m [ 14 ] >> 16 ) & 1 ) ; const b = ( m [ 15 ] >> 16 ) & 1 ; m [ 14 ] &= 0xffff ; sel25519 ( t , m , 1 - b ) ; } for ( let i = 0 ; i < 16 ; i ++ ) { o [ 2 * i ] = t [ i ] & 0xff ; o [ 2 * i + 1 ] = t [ i ] >> 8 ; } } function unpack25519 ( o , n ) { for ( let i = 0 ; i < 16 ; i ++ ) { o [ i ] = n [ 2 * i ] + ( n [ 2 * i + 1 ] << 8 ) ; } o [ 15 ] &= 0x7fff ; } function add ( o , a , b ) { for ( let i = 0 ; i < 16 ; i ++ ) { o [ i ] = a [ i ] + b [ i ] ; } } function sub ( o , a , b ) { for ( let i = 0 ; i < 16 ; i ++ ) { o [ i ] = a [ i ] - b [ i ] ; } } function mul ( o , a , b ) { let v , c , t0 = 0 , t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 , t6 = 0 , t7 = 0 , t8 = 0 , t9 = 0 , t10 = 0 , t11 = 0 , t12 = 0 , t13 = 0 , t14 = 0 , t15 = 0 , t16 = 0 , t17 = 0 , t18 = 0 , t19 = 0 , t20 = 0 , t21 = 0 , t22 = 0 , t23 = 0 , t24 = 0 , t25 = 0 , t26 = 0 , t27 = 0 , t28 = 0 , t29 = 0 , t30 = 0 , b0 = b [ 0 ] , b1 = b [ 1 ] , b2 = b [ 2 ] , b3 = b [ 3 ] , b4 = b [ 4 ] , b5 = b [ 5 ] , b6 = b [ 6 ] , b7 = b [ 7 ] , b8 = b [ 8 ] , b9 = b [ 9 ] , b10 = b [ 10 ] , b11 = b [ 11 ] , b12 = b [ 12 ] , b13 = b [ 13 ] , b14 = b [ 14 ] , b15 = b [ 15 ] ; v = a [ 0 ] ; t0 += v * b0 ; t1 += v * b1 ; t2 += v * b2 ; t3 += v * b3 ; t4 += v * b4 ; t5 += v * b5 ; t6 += v * b6 ; t7 += v * b7 ; t8 += v * b8 ; t9 += v * b9 ; t10 += v * b10 ; t11 += v * b11 ; t12 += v * b12 ; t13 += v * b13 ; t14 += v * b14 ; t15 += v * b15 ; v = a [ 1 ] ; t1 += v * b0 ; t2 += v * b1 ; t3 += v * b2 ; t4 += v * b3 ; t5 += v * b4 ; t6 += v * b5 ; t7 += v * b6 ; t8 += v * b7 ; t9 += v * b8 ; t10 += v * b9 ; t11 += v * b10 ; t12 += v * b11 ; t13 += v * b12 ; t14 += v * b13 ; t15 += v * b14 ; t16 += v * b15 ; v = a [ 2 ] ; t2 += v * b0 ; t3 += v * b1 ; t4 += v * b2 ; t5 += v * b3 ; t6 += v * b4 ; t7 += v * b5 ; t8 += v * b6 ; t9 += v * b7 ; t10 += v * b8 ; t11 += v * b9 ; t12 += v * b10 ; t13 += v * b11 ; t14 += v * b12 ; t15 += v * b13 ; t16 += v * b14 ; t17 += v * b15 ; v = a [ 3 ] ; t3 += v * b0 ; t4 += v * b1 ; t5 += v * b2 ; t6 += v * b3 ; t7 += v * b4 ; t8 += v * b5 ; t9 += v * b6 ; t10 += v * b7 ; t11 += v * b8 ; t12 += v * b9 ; t13 += v * b10 ; t14 += v * b11 ; t15 += v * b12 ; t16 += v * b13 ; t17 += v * b14 ; t18 += v * b15 ; v = a [ 4 ] ; t4 += v * b0 ; t5 += v * b1 ; t6 += v * b2 ; t7 += v * b3 ; t8 += v * b4 ; t9 += v * b5 ; t10 += v * b6 ; t11 += v * b7 ; t12 += v * b8 ; t13 += v * b9 ; t14 += v * b10 ; t15 += v * b11 ; t16 += v * b12 ; t17 += v * b13 ; t18 += v * b14 ; t19 += v * b15 ; v = a [ 5 ] ; t5 += v * b0 ; t6 += v * b1 ; t7 += v * b2 ; t8 += v * b3 ; t9 += v * b4 ; t10 += v * b5 ; t11 += v * b6 ; t12 += v * b7 ; t13 += v * b8 ; t14 += v * b9 ; t15 += v * b10 ; t16 += v * b11 ; t17 += v * b12 ; t18 += v * b13 ; t19 += v * b14 ; t20 += v * b15 ; v = a [ 6 ] ; t6 += v * b0 ; t7 += v * b1 ; t8 += v * b2 ; t9 += v * b3 ; t10 += v * b4 ; t11 += v * b5 ; t12 += v * b6 ; t13 += v * b7 ; t14 += v * b8 ; t15 += v * b9 ; t16 += v * b10 ; t17 += v * b11 ; t18 += v * b12 ; t19 += v * b13 ; t20 += v * b14 ; t21 += v * b15 ; v = a [ 7 ] ; t7 += v * b0 ; t8 += v * b1 ; t9 += v * b2 ; t10 += v * b3 ; t11 += v * b4 ; t12 += v * b5 ; t13 += v * b6 ; t14 += v * b7 ; t15 += v * b8 ; t16 += v * b9 ; t17 += v * b10 ; t18 += v * b11 ; t19 += v * b12 ; t20 += v * b13 ; t21 += v * b14 ; t22 += v * b15 ; v = a [ 8 ] ; t8 += v * b0 ; t9 += v * b1 ; t10 += v * b2 ; t11 += v * b3 ; t12 += v * b4 ; t13 += v * b5 ; t14 += v * b6 ; t15 += v * b7 ; t16 += v * b8 ; t17 += v * b9 ; t18 += v * b10 ; t19 += v * b11 ; t20 += v * b12 ; t21 += v * b13 ; t22 += v * b14 ; t23 += v * b15 ; v = a [ 9 ] ; t9 += v * b0 ; t10 += v * b1 ; t11 += v * b2 ; t12 += v * b3 ; t13 += v * b4 ; t14 += v * b5 ; t15 += v * b6 ; t16 += v * b7 ; t17 += v * b8 ; t18 += v * b9 ; t19 += v * b10 ; t20 += v * b11 ; t21 += v * b12 ; t22 += v * b13 ; t23 += v * b14 ; t24 += v * b15 ; v = a [ 10 ] ; t10 += v * b0 ; t11 += v * b1 ; t12 += v * b2 ; t13 += v * b3 ; t14 += v * b4 ; t15 += v * b5 ; t16 += v * b6 ; t17 += v * b7 ; t18 += v * b8 ; t19 += v * b9 ; t20 += v * b10 ; t21 += v * b11 ; t22 += v * b12 ; t23 += v * b13 ; t24 += v * b14 ; t25 += v * b15 ; v = a [ 11 ] ; t11 += v * b0 ; t12 += v * b1 ; t13 += v * b2 ; t14 += v * b3 ; t15 += v * b4 ; t16 += v * b5 ; t17 += v * b6 ; t18 += v * b7 ; t19 += v * b8 ; t20 += v * b9 ; t21 += v * b10 ; t22 += v * b11 ; t23 += v * b12 ; t24 += v * b13 ; t25 += v * b14 ; t26 += v * b15 ; v = a [ 12 ] ; t12 += v * b0 ; t13 += v * b1 ; t14 += v * b2 ; t15 += v * b3 ; t16 += v * b4 ; t17 += v * b5 ; t18 += v * b6 ; t19 += v * b7 ; t20 += v * b8 ; t21 += v * b9 ; t22 += v * b10 ; t23 += v * b11 ; t24 += v * b12 ; t25 += v * b13 ; t26 += v * b14 ; t27 += v * b15 ; v = a [ 13 ] ; t13 += v * b0 ; t14 += v * b1 ; t15 += v * b2 ; t16 += v * b3 ; t17 += v * b4 ; t18 += v * b5 ; t19 += v * b6 ; t20 += v * b7 ; t21 += v * b8 ; t22 += v * b9 ; t23 += v * b10 ; t24 += v * b11 ; t25 += v * b12 ; t26 += v * b13 ; t27 += v * b14 ; t28 += v * b15 ; v = a [ 14 ] ; t14 += v * b0 ; t15 += v * b1 ; t16 += v * b2 ; t17 += v * b3 ; t18 += v * b4 ; t19 += v * b5 ; t20 += v * b6 ; t21 += v * b7 ; t22 += v * b8 ; t23 += v * b9 ; t24 += v * b10 ; t25 += v * b11 ; t26 += v * b12 ; t27 += v * b13 ; t28 += v * b14 ; t29 += v * b15 ; v = a [ 15 ] ; t15 += v * b0 ; t16 += v * b1 ; t17 += v * b2 ; t18 += v * b3 ; t19 += v * b4 ; t20 += v * b5 ; t21 += v * b6 ; t22 += v * b7 ; t23 += v * b8 ; t24 += v * b9 ; t25 += v * b10 ; t26 += v * b11 ; t27 += v * b12 ; t28 += v * b13 ; t29 += v * b14 ; t30 += v * b15 ; t0 += 38 * t16 ; t1 += 38 * t17 ; t2 += 38 * t18 ; t3 += 38 * t19 ; t4 += 38 * t20 ; t5 += 38 * t21 ; t6 += 38 * t22 ; t7 += 38 * t23 ; t8 += 38 * t24 ; t9 += 38 * t25 ; t10 += 38 * t26 ; t11 += 38 * t27 ; t12 += 38 * t28 ; t13 += 38 * t29 ; t14 += 38 * t30 ; c = 1 ; v = t0 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t0 = v - c * 65536 ; v = t1 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t1 = v - c * 65536 ; v = t2 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t2 = v - c * 65536 ; v = t3 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t3 = v - c * 65536 ; v = t4 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t4 = v - c * 65536 ; v = t5 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t5 = v - c * 65536 ; v = t6 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t6 = v - c * 65536 ; v = t7 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t7 = v - c * 65536 ; v = t8 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t8 = v - c * 65536 ; v = t9 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t9 = v - c * 65536 ; v = t10 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t10 = v - c * 65536 ; v = t11 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t11 = v - c * 65536 ; v = t12 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t12 = v - c * 65536 ; v = t13 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t13 = v - c * 65536 ; v = t14 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t14 = v - c * 65536 ; v = t15 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t15 = v - c * 65536 ; t0 += c - 1 + 37 * ( c - 1 ) ; c = 1 ; v = t0 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t0 = v - c * 65536 ; v = t1 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t1 = v - c * 65536 ; v = t2 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t2 = v - c * 65536 ; v = t3 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t3 = v - c * 65536 ; v = t4 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t4 = v - c * 65536 ; v = t5 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t5 = v - c * 65536 ; v = t6 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t6 = v - c * 65536 ; v = t7 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t7 = v - c * 65536 ; v = t8 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t8 = v - c * 65536 ; v = t9 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t9 = v - c * 65536 ; v = t10 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t10 = v - c * 65536 ; v = t11 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t11 = v - c * 65536 ; v = t12 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t12 = v - c * 65536 ; v = t13 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t13 = v - c * 65536 ; v = t14 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t14 = v - c * 65536 ; v = t15 + c + 65535 ; c = Math . floor ( v / 65536 ) ; t15 = v - c * 65536 ; t0 += c - 1 + 37 * ( c - 1 ) ; o [ 0 ] = t0 ; o [ 1 ] = t1 ; o [ 2 ] = t2 ; o [ 3 ] = t3 ; o [ 4 ] = t4 ; o [ 5 ] = t5 ; o [ 6 ] = t6 ; o [ 7 ] = t7 ; o [ 8 ] = t8 ; o [ 9 ] = t9 ; o [ 10 ] = t10 ; o [ 11 ] = t11 ; o [ 12 ] = t12 ; o [ 13 ] = t13 ; o [ 14 ] = t14 ; o [ 15 ] = t15 ; } function square ( o , a ) { mul ( o , a , a ) ; } function inv25519 ( o , inp ) { const c = gf ( ) ; for ( let i = 0 ; i < 16 ; i ++ ) { c [ i ] = inp [ i ] ; } for ( let i = 253 ; i >= 0 ; i -- ) { square ( c , c ) ; if ( i !== 2 && i !== 4 ) { mul ( c , c , inp ) ; } } for ( let i = 0 ; i < 16 ; i ++ ) { o [ i ] = c [ i ] ; } } export function scalarMult ( n , p ) { const z = new Uint8Array ( 32 ) ; const x = new Float64Array ( 80 ) ; const a = gf ( ) , b = gf ( ) , c = gf ( ) , d = gf ( ) , e = gf ( ) , f = gf ( ) ; for ( let i = 0 ; i < 31 ; i ++ ) { z [ i ] = n [ i ] ; } z [ 31 ] = ( n [ 31 ] & 127 ) | 64 ; z [ 0 ] &= 248 ; unpack25519 ( x , p ) ; for ( let i = 0 ; i < 16 ; i ++ ) { b [ i ] = x [ i ] ; } a [ 0 ] = d [ 0 ] = 1 ; for ( let i = 254 ; i >= 0 ; -- i ) { const r = ( z [ i >>> 3 ] >>> ( i & 7 ) ) & 1 ; sel25519 ( a , b , r ) ; sel25519 ( c , d , r ) ; add ( e , a , c ) ; sub ( a , a , c ) ; add ( c , b , d ) ; sub ( b , b , d ) ; square ( d , e ) ; square ( f , a ) ; mul ( a , c , a ) ; mul ( c , b , e ) ; add ( e , a , c ) ; sub ( a , a , c ) ; square ( b , a ) ; sub ( c , d , f ) ; mul ( a , c , _121665 ) ; add ( a , a , d ) ; mul ( c , c , a ) ; mul ( a , d , f ) ; mul ( d , b , x ) ; square ( b , e ) ; sel25519 ( a , b , r ) ; sel25519 ( c , d , r ) ; } for ( let i = 0 ; i < 16 ; i ++ ) { x [ i + 16 ] = a [ i ] ; x [ i + 32 ] = c [ i ] ; x [ i + 48 ] = b [ i ] ; x [ i + 64 ] = d [ i ] ; } const x32 = x . subarray ( 32 ) ; const x16 = x . subarray ( 16 ) ; inv25519 ( x32 , x32 ) ; mul ( x16 , x16 , x32 ) ; const q = new Uint8Array ( 32 ) ; pack25519 ( q , x16 ) ; return q ; } export function scalarMultBase ( n ) { return scalarMult ( n , _9 ) ; } export interface KeyPair { publicKey : Uint8Array ; secretKey : Uint8Array ; } export function generateKeyPairFromSeed ( seed ) { if ( seed . length !== SECRET_KEY_LENGTH ) { throw new Error ( `x25519: seed must be ${ SECRET_KEY_LENGTH } bytes` ) ; } const secretKey = new Uint8Array ( seed ) ; const publicKey = scalarMultBase ( secretKey ) ; return { publicKey , secretKey } ; } export function generateKeyPair ( prng ? ) { const seed = randomBytes ( 32 , prng ) ; const result = generateKeyPairFromSeed ( seed ) ; wipe ( seed ) ; return result ; } /**
 * Returns a shared key between our secret key and a peer's public key.
 *
 * Throws an error if the given keys are of wrong length.
 *
 * If rejectZero is true throws if the calculated shared key is all-zero.
 * From RFC 7748:
 *
 * > Protocol designers using Diffie-Hellman over the curves defined in
 * > this document must not assume "contributory behavior".  Specially,
 * > contributory behavior means that both parties' private keys
 * > contribute to the resulting shared key.  Since curve25519 and
 * > curve448 have cofactors of 8 and 4 (respectively), an input point of
 * > small order will eliminate any contribution from the other party's
 * > private key.  This situation can be detected by checking for the all-
 * > zero output, which implementations MAY do, as specified in Section 6.
 * > However, a large number of existing implementations do not do this.
 *
 * IMPORTANT: the returned key is a raw result of scalar multiplication.
 * To use it as a key material, hash it with a cryptographic hash function.
 */ export function sharedKey ( mySecretKey , theirPublicKey , rejectZero = false ) { if ( mySecretKey . length !== PUBLIC_KEY_LENGTH ) { throw new Error ( "X25519: incorrect secret key length" ) ; } if ( theirPublicKey . length !== PUBLIC_KEY_LENGTH ) { throw new Error ( "X25519: incorrect public key length" ) ; } const result = scalarMult ( mySecretKey , theirPublicKey ) ; if ( rejectZero ) { let zeros = 0 ; for ( let i = 0 ; i < result . length ; i ++ ) { zeros |= result [ i ] ; } if ( zeros === 0 ) { throw new Error ( "X25519: invalid shared key" ) ; } } return result ; }