]> git.codecow.com Git - libnemo.git/commitdiff
Public key derivation always multiplies secret key scalar by base point G, so elimina...
authorChris Duncan <chris@zoso.dev>
Fri, 5 Dec 2025 17:08:22 +0000 (09:08 -0800)
committerChris Duncan <chris@zoso.dev>
Fri, 5 Dec 2025 17:08:22 +0000 (09:08 -0800)
src/lib/crypto/secp256k1.ts

index 0d56660970ba50063db48daca0d64b0e07b64781..7d9198c1d42b9aaf78a64cb8c40d39a6964c9982 100644 (file)
@@ -19,7 +19,6 @@ type Point = {
        negate: () => Point
        double: () => Point
        add: (other: Point) => Point
-       multiply: (n: bigint) => Point
        toAffine: () => AffinePoint
        assertValidity: () => Point
        toBytes: (isCompressed?: boolean) => Bytes
@@ -217,27 +216,6 @@ export class Secp256k1 {
                                Z3 = M(Z3 + t0) // step 40
                                return secp256k1.Point(X3, Y3, Z3)
                        },
-                       /**
-                        * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
-                        * Uses {@link wNAF} for base point.
-                        * Uses fake point to mitigate side-channel leakage.
-                        * @param n scalar by which point is multiplied
-                        * @param safe safe mode guards against timing attacks; unsafe mode is faster
-                        */
-                       multiply (n: bigint): Point {
-                               if (secp256k1.bigintInRange(n, 1n, secp256k1.N) === 1n) return this
-                               if (this.equals(secp256k1.G)) return secp256k1.wNAF(n).p
-                               // init result point & fake point
-                               let p = secp256k1.I
-                               let f = secp256k1.G
-                               for (let d: Point = this; n > 0n; d = d.double(), n >>= 1n) {
-                                       // if bit is present, add to point
-                                       // if not present, add to fake, for timing safety
-                                       if (n & 1n) p = p.add(d)
-                                       else f = f.add(d)
-                               }
-                               return p
-                       },
                        /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
                        toAffine (): AffinePoint {
                                const { X: x, Y: y, Z: z } = this
@@ -325,7 +303,7 @@ export class Secp256k1 {
 
        /** Creates 33/65-byte public key from 32-byte private key. */
        static getPublicKey (sk: Bytes, isCompressed = true): Bytes {
-               return this.G.multiply(this.secretKeyToScalar(sk)).toBytes(isCompressed)
+               return this.wNAF(this.secretKeyToScalar(sk)).p.toBytes(isCompressed)
        }
 
        static isValidPublicKey (pk: Bytes, isCompressed?: boolean): boolean {
@@ -375,6 +353,7 @@ export class Secp256k1 {
                return cnd ? n : p
        }
        static wNAF (n: bigint): { p: Point; f: Point } {
+               console.log('mult', n)
                const comp = this.Gpows || (this.Gpows = this.precompute())
                let p = this.I
                let f = this.G // f must be G, or could become I in the end