@bsv/sdk 1.6.15 → 1.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/certificates/__tests/CompletedProtoWallet.js +1 -1
- package/dist/cjs/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
- package/dist/cjs/src/primitives/Point.js +123 -6
- package/dist/cjs/src/primitives/Point.js.map +1 -1
- package/dist/cjs/src/primitives/PrivateKey.js +19 -2
- package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
- package/dist/cjs/src/primitives/PublicKey.js +19 -2
- package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js +12 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/KeyDeriver.js +8 -5
- package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/ProtoWallet.js +5 -2
- package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/certificates/__tests/CompletedProtoWallet.js +2 -2
- package/dist/esm/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
- package/dist/esm/src/primitives/Point.js +123 -6
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/primitives/PrivateKey.js +19 -2
- package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
- package/dist/esm/src/primitives/PublicKey.js +19 -2
- package/dist/esm/src/primitives/PublicKey.js.map +1 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js +20 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/KeyDeriver.js +11 -5
- package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/ProtoWallet.js +2 -2
- package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/certificates/__tests/CompletedProtoWallet.d.ts.map +1 -1
- package/dist/types/src/primitives/Point.d.ts.map +1 -1
- package/dist/types/src/primitives/PrivateKey.d.ts +3 -1
- package/dist/types/src/primitives/PrivateKey.d.ts.map +1 -1
- package/dist/types/src/primitives/PublicKey.d.ts +3 -1
- package/dist/types/src/primitives/PublicKey.d.ts.map +1 -1
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts +10 -2
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/KeyDeriver.d.ts +5 -2
- package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/reference/primitives.md +14 -6
- package/docs/reference/wallet.md +25 -6
- package/package.json +1 -1
- package/src/auth/certificates/__tests/CompletedProtoWallet.ts +3 -2
- package/src/primitives/Point.ts +152 -5
- package/src/primitives/PrivateKey.ts +22 -2
- package/src/primitives/PublicKey.ts +22 -2
- package/src/wallet/CachedKeyDeriver.ts +32 -8
- package/src/wallet/KeyDeriver.ts +22 -6
- package/src/wallet/ProtoWallet.ts +3 -2
|
@@ -2396,7 +2396,7 @@ export default class PrivateKey extends BigNumber {
|
|
|
2396
2396
|
toHex(): string
|
|
2397
2397
|
toString(base: number | "hex" = "hex", padding: number = 64): string
|
|
2398
2398
|
deriveSharedSecret(key: PublicKey): Point
|
|
2399
|
-
deriveChild(publicKey: PublicKey, invoiceNumber: string): PrivateKey
|
|
2399
|
+
deriveChild(publicKey: PublicKey, invoiceNumber: string, cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))): PrivateKey
|
|
2400
2400
|
toKeyShares(threshold: number, totalShares: number): KeyShares
|
|
2401
2401
|
toBackupShares(threshold: number, totalShares: number): string[]
|
|
2402
2402
|
static fromBackupShares(shares: string[]): PrivateKey
|
|
@@ -2453,9 +2453,9 @@ Returns
|
|
|
2453
2453
|
Derives a child key with BRC-42.
|
|
2454
2454
|
|
|
2455
2455
|
```ts
|
|
2456
|
-
deriveChild(publicKey: PublicKey, invoiceNumber: string): PrivateKey
|
|
2456
|
+
deriveChild(publicKey: PublicKey, invoiceNumber: string, cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))): PrivateKey
|
|
2457
2457
|
```
|
|
2458
|
-
See also: [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey)
|
|
2458
|
+
See also: [Point](./primitives.md#class-point), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey)
|
|
2459
2459
|
|
|
2460
2460
|
Returns
|
|
2461
2461
|
|
|
@@ -2467,6 +2467,10 @@ Argument Details
|
|
|
2467
2467
|
+ The public key of the other party
|
|
2468
2468
|
+ **invoiceNumber**
|
|
2469
2469
|
+ The invoice number used to derive the child key
|
|
2470
|
+
+ **cacheSharedSecret**
|
|
2471
|
+
+ Optional function to cache shared secrets
|
|
2472
|
+
+ **retrieveCachedSharedSecret**
|
|
2473
|
+
+ Optional function to retrieve shared secrets from the cache
|
|
2470
2474
|
|
|
2471
2475
|
#### Method deriveSharedSecret
|
|
2472
2476
|
|
|
@@ -2885,7 +2889,7 @@ export default class PublicKey extends Point {
|
|
|
2885
2889
|
toDER(enc?: "hex" | undefined): number[] | string
|
|
2886
2890
|
toHash(enc?: "hex"): number[] | string
|
|
2887
2891
|
toAddress(prefix: number[] | string = [0]): string
|
|
2888
|
-
deriveChild(privateKey: PrivateKey, invoiceNumber: string): PublicKey
|
|
2892
|
+
deriveChild(privateKey: PrivateKey, invoiceNumber: string, cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))): PublicKey
|
|
2889
2893
|
static fromMsgHashAndCompactSignature(msgHash: BigNumber, signature: number[] | string, enc?: "hex" | "base64"): PublicKey
|
|
2890
2894
|
}
|
|
2891
2895
|
```
|
|
@@ -2920,9 +2924,9 @@ new PublicKey('abc123', 'def456');
|
|
|
2920
2924
|
Derives a child key with BRC-42.
|
|
2921
2925
|
|
|
2922
2926
|
```ts
|
|
2923
|
-
deriveChild(privateKey: PrivateKey, invoiceNumber: string): PublicKey
|
|
2927
|
+
deriveChild(privateKey: PrivateKey, invoiceNumber: string, cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))): PublicKey
|
|
2924
2928
|
```
|
|
2925
|
-
See also: [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey)
|
|
2929
|
+
See also: [Point](./primitives.md#class-point), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey)
|
|
2926
2930
|
|
|
2927
2931
|
Returns
|
|
2928
2932
|
|
|
@@ -2934,6 +2938,10 @@ Argument Details
|
|
|
2934
2938
|
+ The private key of the other party
|
|
2935
2939
|
+ **invoiceNumber**
|
|
2936
2940
|
+ The invoice number used to derive the child key
|
|
2941
|
+
+ **cacheSharedSecret**
|
|
2942
|
+
+ Optional function to cache shared secrets
|
|
2943
|
+
+ **retrieveCachedSharedSecret**
|
|
2944
|
+
+ Optional function to retrieve shared secrets from the cache
|
|
2937
2945
|
|
|
2938
2946
|
#### Method deriveSharedSecret
|
|
2939
2947
|
|
package/docs/reference/wallet.md
CHANGED
|
@@ -1549,7 +1549,9 @@ This is useful for optimizing performance when the same keys are derived multipl
|
|
|
1549
1549
|
It supports configurable cache size with sane defaults and maintains cache entries using LRU (Least Recently Used) eviction policy.
|
|
1550
1550
|
|
|
1551
1551
|
```ts
|
|
1552
|
-
export default class CachedKeyDeriver {
|
|
1552
|
+
export default class CachedKeyDeriver implements KeyDeriverApi {
|
|
1553
|
+
rootKey: PrivateKey;
|
|
1554
|
+
identityKey: string;
|
|
1553
1555
|
constructor(rootKey: PrivateKey | "anyone", options?: {
|
|
1554
1556
|
maxCacheSize?: number;
|
|
1555
1557
|
})
|
|
@@ -1561,7 +1563,7 @@ export default class CachedKeyDeriver {
|
|
|
1561
1563
|
}
|
|
1562
1564
|
```
|
|
1563
1565
|
|
|
1564
|
-
See also: [Counterparty](./wallet.md#type-counterparty), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey), [SymmetricKey](./primitives.md#class-symmetrickey), [WalletProtocol](./wallet.md#type-walletprotocol)
|
|
1566
|
+
See also: [Counterparty](./wallet.md#type-counterparty), [KeyDeriverApi](./wallet.md#interface-keyderiverapi), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey), [SymmetricKey](./primitives.md#class-symmetrickey), [WalletProtocol](./wallet.md#type-walletprotocol)
|
|
1565
1567
|
|
|
1566
1568
|
#### Constructor
|
|
1567
1569
|
|
|
@@ -1581,6 +1583,23 @@ Argument Details
|
|
|
1581
1583
|
+ **options**
|
|
1582
1584
|
+ Optional settings for the cache.
|
|
1583
1585
|
|
|
1586
|
+
#### Property identityKey
|
|
1587
|
+
|
|
1588
|
+
The identity of this key deriver which is normally the public key associated with the `rootKey`
|
|
1589
|
+
|
|
1590
|
+
```ts
|
|
1591
|
+
identityKey: string
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
#### Property rootKey
|
|
1595
|
+
|
|
1596
|
+
The root key from which all other keys are derived.
|
|
1597
|
+
|
|
1598
|
+
```ts
|
|
1599
|
+
rootKey: PrivateKey
|
|
1600
|
+
```
|
|
1601
|
+
See also: [PrivateKey](./primitives.md#class-privatekey)
|
|
1602
|
+
|
|
1584
1603
|
#### Method derivePrivateKey
|
|
1585
1604
|
|
|
1586
1605
|
Derives a private key based on protocol ID, key ID, and counterparty.
|
|
@@ -1955,7 +1974,7 @@ It supports deriving public and private keys, symmetric keys, and revealing key
|
|
|
1955
1974
|
export class KeyDeriver implements KeyDeriverApi {
|
|
1956
1975
|
rootKey: PrivateKey;
|
|
1957
1976
|
identityKey: string;
|
|
1958
|
-
constructor(rootKey: PrivateKey | "anyone")
|
|
1977
|
+
constructor(rootKey: PrivateKey | "anyone", private readonly cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), private readonly retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined)))
|
|
1959
1978
|
derivePublicKey(protocolID: WalletProtocol, keyID: string, counterparty: Counterparty, forSelf: boolean = false): PublicKey
|
|
1960
1979
|
derivePrivateKey(protocolID: WalletProtocol, keyID: string, counterparty: Counterparty): PrivateKey
|
|
1961
1980
|
deriveSymmetricKey(protocolID: WalletProtocol, keyID: string, counterparty: Counterparty): SymmetricKey
|
|
@@ -1964,16 +1983,16 @@ export class KeyDeriver implements KeyDeriverApi {
|
|
|
1964
1983
|
}
|
|
1965
1984
|
```
|
|
1966
1985
|
|
|
1967
|
-
See also: [Counterparty](./wallet.md#type-counterparty), [KeyDeriverApi](./wallet.md#interface-keyderiverapi), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey), [SymmetricKey](./primitives.md#class-symmetrickey), [WalletProtocol](./wallet.md#type-walletprotocol)
|
|
1986
|
+
See also: [Counterparty](./wallet.md#type-counterparty), [KeyDeriverApi](./wallet.md#interface-keyderiverapi), [Point](./primitives.md#class-point), [PrivateKey](./primitives.md#class-privatekey), [PublicKey](./primitives.md#class-publickey), [SymmetricKey](./primitives.md#class-symmetrickey), [WalletProtocol](./wallet.md#type-walletprotocol)
|
|
1968
1987
|
|
|
1969
1988
|
#### Constructor
|
|
1970
1989
|
|
|
1971
1990
|
Initializes the KeyDeriver instance with a root private key.
|
|
1972
1991
|
|
|
1973
1992
|
```ts
|
|
1974
|
-
constructor(rootKey: PrivateKey | "anyone")
|
|
1993
|
+
constructor(rootKey: PrivateKey | "anyone", private readonly cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void), private readonly retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined)))
|
|
1975
1994
|
```
|
|
1976
|
-
See also: [PrivateKey](./primitives.md#class-privatekey)
|
|
1995
|
+
See also: [Point](./primitives.md#class-point), [PrivateKey](./primitives.md#class-privatekey)
|
|
1977
1996
|
|
|
1978
1997
|
Argument Details
|
|
1979
1998
|
|
package/package.json
CHANGED
|
@@ -23,7 +23,8 @@ import {
|
|
|
23
23
|
PubKeyHex,
|
|
24
24
|
AuthenticatedResult,
|
|
25
25
|
GetNetworkResult,
|
|
26
|
-
GetVersionResult
|
|
26
|
+
GetVersionResult,
|
|
27
|
+
CachedKeyDeriver
|
|
27
28
|
} from '../../../wallet/index.js'
|
|
28
29
|
|
|
29
30
|
// Test Mock wallet which extends ProtoWallet but still implements Wallet interface
|
|
@@ -41,7 +42,7 @@ export class CompletedProtoWallet
|
|
|
41
42
|
typeof rootKeyOrKeyDeriver === 'string' ||
|
|
42
43
|
rootKeyOrKeyDeriver instanceof PrivateKey
|
|
43
44
|
) {
|
|
44
|
-
this.keyDeriver = new
|
|
45
|
+
this.keyDeriver = new CachedKeyDeriver(rootKeyOrKeyDeriver)
|
|
45
46
|
} else {
|
|
46
47
|
throw new Error('Invalid key deriver provided')
|
|
47
48
|
}
|
package/src/primitives/Point.ts
CHANGED
|
@@ -576,12 +576,159 @@ export default class Point extends BasePoint {
|
|
|
576
576
|
k = new BigNumber(k as number, 16)
|
|
577
577
|
}
|
|
578
578
|
k = k as BigNumber
|
|
579
|
-
if (
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
579
|
+
if (typeof BigInt === 'function') {
|
|
580
|
+
if (this.inf) {
|
|
581
|
+
return this
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const zero = BigInt(0)
|
|
585
|
+
const one = BigInt(1)
|
|
586
|
+
const two = BigInt(2)
|
|
587
|
+
const three = BigInt(3)
|
|
588
|
+
const four = BigInt(4)
|
|
589
|
+
const eight = BigInt(8)
|
|
590
|
+
|
|
591
|
+
const p = BigInt(
|
|
592
|
+
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'
|
|
593
|
+
)
|
|
594
|
+
const n = BigInt(
|
|
595
|
+
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
let kBig = BigInt('0x' + k.toString(16))
|
|
599
|
+
const isNeg = kBig < zero
|
|
600
|
+
if (isNeg) kBig = -kBig
|
|
601
|
+
kBig = ((kBig % n) + n) % n
|
|
602
|
+
if (kBig === zero) {
|
|
603
|
+
return new Point(null, null)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (this.x === null || this.y === null) {
|
|
607
|
+
throw new Error('Point coordinates cannot be null')
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const Px = BigInt('0x' + this.x.fromRed().toString(16))
|
|
611
|
+
const Py = BigInt('0x' + this.y.fromRed().toString(16))
|
|
612
|
+
|
|
613
|
+
const mod = (a: bigint, m: bigint): bigint => ((a % m) + m) % m
|
|
614
|
+
const modMul = (a: bigint, b: bigint, m: bigint): bigint => mod(a * b, m)
|
|
615
|
+
const modSub = (a: bigint, b: bigint, m: bigint): bigint => mod(a - b, m)
|
|
616
|
+
const modInv = (a: bigint, m: bigint): bigint => {
|
|
617
|
+
let lm = one
|
|
618
|
+
let hm = zero
|
|
619
|
+
let low = mod(a, m)
|
|
620
|
+
let high = m
|
|
621
|
+
while (low > one) {
|
|
622
|
+
const r = high / low
|
|
623
|
+
const nm = hm - lm * r
|
|
624
|
+
const neww = high - low * r
|
|
625
|
+
hm = lm
|
|
626
|
+
lm = nm
|
|
627
|
+
high = low
|
|
628
|
+
low = neww
|
|
629
|
+
}
|
|
630
|
+
return mod(lm, m)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
interface JacobianPoint {
|
|
634
|
+
X: bigint
|
|
635
|
+
Y: bigint
|
|
636
|
+
Z: bigint
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const pointDouble = (P: JacobianPoint): JacobianPoint => {
|
|
640
|
+
const { X: X1, Y: Y1, Z: Z1 } = P
|
|
641
|
+
if (Y1 === zero) {
|
|
642
|
+
return { X: zero, Y: one, Z: zero }
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const Y1sq = modMul(Y1, Y1, p)
|
|
646
|
+
const S = modMul(four, modMul(X1, Y1sq, p), p)
|
|
647
|
+
const M = modMul(three, modMul(X1, X1, p), p)
|
|
648
|
+
const X3 = modSub(modMul(M, M, p), modMul(two, S, p), p)
|
|
649
|
+
const Y3 = modSub(
|
|
650
|
+
modMul(M, modSub(S, X3, p), p),
|
|
651
|
+
modMul(eight, modMul(Y1sq, Y1sq, p), p),
|
|
652
|
+
p
|
|
653
|
+
)
|
|
654
|
+
const Z3 = modMul(two, modMul(Y1, Z1, p), p)
|
|
655
|
+
return { X: X3, Y: Y3, Z: Z3 }
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const pointAdd = (P: JacobianPoint, Q: JacobianPoint): JacobianPoint => {
|
|
659
|
+
if (P.Z === zero) return Q
|
|
660
|
+
if (Q.Z === zero) return P
|
|
661
|
+
|
|
662
|
+
const Z1Z1 = modMul(P.Z, P.Z, p)
|
|
663
|
+
const Z2Z2 = modMul(Q.Z, Q.Z, p)
|
|
664
|
+
const U1 = modMul(P.X, Z2Z2, p)
|
|
665
|
+
const U2 = modMul(Q.X, Z1Z1, p)
|
|
666
|
+
const S1 = modMul(P.Y, modMul(Z2Z2, Q.Z, p), p)
|
|
667
|
+
const S2 = modMul(Q.Y, modMul(Z1Z1, P.Z, p), p)
|
|
668
|
+
|
|
669
|
+
const H = modSub(U2, U1, p)
|
|
670
|
+
const r = modSub(S2, S1, p)
|
|
671
|
+
|
|
672
|
+
if (H === zero) {
|
|
673
|
+
if (r === zero) {
|
|
674
|
+
return pointDouble(P)
|
|
675
|
+
} else {
|
|
676
|
+
return { X: zero, Y: one, Z: zero }
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
const HH = modMul(H, H, p)
|
|
681
|
+
const HHH = modMul(H, HH, p)
|
|
682
|
+
const V = modMul(U1, HH, p)
|
|
683
|
+
|
|
684
|
+
const X3 = modSub(modSub(modMul(r, r, p), HHH, p), modMul(two, V, p), p)
|
|
685
|
+
const Y3 = modSub(modMul(r, modSub(V, X3, p), p), modMul(S1, HHH, p), p)
|
|
686
|
+
const Z3 = modMul(H, modMul(P.Z, Q.Z, p), p)
|
|
687
|
+
|
|
688
|
+
return { X: X3, Y: Y3, Z: Z3 }
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const scalarMultiply = (
|
|
692
|
+
kVal: bigint,
|
|
693
|
+
P0: { x: bigint, y: bigint }
|
|
694
|
+
): JacobianPoint => {
|
|
695
|
+
let N: JacobianPoint = { X: P0.x, Y: P0.y, Z: one }
|
|
696
|
+
let Q: JacobianPoint = { X: zero, Y: one, Z: zero }
|
|
697
|
+
let kk = kVal
|
|
698
|
+
while (kk > zero) {
|
|
699
|
+
if ((kk & one) === one) {
|
|
700
|
+
Q = pointAdd(Q, N)
|
|
701
|
+
}
|
|
702
|
+
N = pointDouble(N)
|
|
703
|
+
kk >>= one
|
|
704
|
+
}
|
|
705
|
+
return Q
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const R = scalarMultiply(kBig, { x: Px, y: Py })
|
|
709
|
+
if (R.Z === zero) {
|
|
710
|
+
return new Point(null, null)
|
|
711
|
+
}
|
|
712
|
+
const zInv = modInv(R.Z, p)
|
|
713
|
+
const zInv2 = modMul(zInv, zInv, p)
|
|
714
|
+
const xRes = modMul(R.X, zInv2, p)
|
|
715
|
+
const yRes = modMul(R.Y, modMul(zInv2, zInv, p), p)
|
|
716
|
+
|
|
717
|
+
const xBN = new BigNumber(xRes.toString(16), 16)
|
|
718
|
+
const yBN = new BigNumber(yRes.toString(16), 16)
|
|
719
|
+
const result = new Point(xBN, yBN)
|
|
720
|
+
if (isNeg) {
|
|
721
|
+
return result.neg()
|
|
722
|
+
}
|
|
723
|
+
return result
|
|
583
724
|
} else {
|
|
584
|
-
|
|
725
|
+
if (this.isInfinity()) {
|
|
726
|
+
return this
|
|
727
|
+
} else if (this._hasDoubles(k)) {
|
|
728
|
+
return this._fixedNafMul(k)
|
|
729
|
+
} else {
|
|
730
|
+
return this._endoWnafMulAdd([this], [k]) as Point
|
|
731
|
+
}
|
|
585
732
|
}
|
|
586
733
|
}
|
|
587
734
|
|
|
@@ -359,10 +359,30 @@ export default class PrivateKey extends BigNumber {
|
|
|
359
359
|
* Derives a child key with BRC-42.
|
|
360
360
|
* @param publicKey The public key of the other party
|
|
361
361
|
* @param invoiceNumber The invoice number used to derive the child key
|
|
362
|
+
* @param cacheSharedSecret Optional function to cache shared secrets
|
|
363
|
+
* @param retrieveCachedSharedSecret Optional function to retrieve shared secrets from the cache
|
|
362
364
|
* @returns The derived child key.
|
|
363
365
|
*/
|
|
364
|
-
deriveChild (
|
|
365
|
-
|
|
366
|
+
deriveChild (
|
|
367
|
+
publicKey: PublicKey,
|
|
368
|
+
invoiceNumber: string,
|
|
369
|
+
cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void),
|
|
370
|
+
retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))
|
|
371
|
+
): PrivateKey {
|
|
372
|
+
let sharedSecret: Point
|
|
373
|
+
if (typeof retrieveCachedSharedSecret === 'function') {
|
|
374
|
+
const retrieved = retrieveCachedSharedSecret(this, publicKey)
|
|
375
|
+
if (typeof retrieved !== 'undefined') {
|
|
376
|
+
sharedSecret = retrieved
|
|
377
|
+
} else {
|
|
378
|
+
sharedSecret = this.deriveSharedSecret(publicKey)
|
|
379
|
+
if (typeof cacheSharedSecret === 'function') {
|
|
380
|
+
cacheSharedSecret(this, publicKey, sharedSecret)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
sharedSecret = this.deriveSharedSecret(publicKey)
|
|
385
|
+
}
|
|
366
386
|
const invoiceNumberBin = toArray(invoiceNumber, 'utf8')
|
|
367
387
|
const hmac = sha256hmac(sharedSecret.encode(true), invoiceNumberBin)
|
|
368
388
|
const curve = new Curve()
|
|
@@ -202,10 +202,30 @@ export default class PublicKey extends Point {
|
|
|
202
202
|
* Derives a child key with BRC-42.
|
|
203
203
|
* @param privateKey The private key of the other party
|
|
204
204
|
* @param invoiceNumber The invoice number used to derive the child key
|
|
205
|
+
* @param cacheSharedSecret Optional function to cache shared secrets
|
|
206
|
+
* @param retrieveCachedSharedSecret Optional function to retrieve shared secrets from the cache
|
|
205
207
|
* @returns The derived child key.
|
|
206
208
|
*/
|
|
207
|
-
deriveChild (
|
|
208
|
-
|
|
209
|
+
deriveChild (
|
|
210
|
+
privateKey: PrivateKey,
|
|
211
|
+
invoiceNumber: string,
|
|
212
|
+
cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void),
|
|
213
|
+
retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))
|
|
214
|
+
): PublicKey {
|
|
215
|
+
let sharedSecret: Point
|
|
216
|
+
if (typeof retrieveCachedSharedSecret === 'function') {
|
|
217
|
+
const retrieved = retrieveCachedSharedSecret(privateKey, this)
|
|
218
|
+
if (typeof retrieved !== 'undefined') {
|
|
219
|
+
sharedSecret = retrieved
|
|
220
|
+
} else {
|
|
221
|
+
sharedSecret = this.deriveSharedSecret(privateKey)
|
|
222
|
+
if (typeof cacheSharedSecret === 'function') {
|
|
223
|
+
cacheSharedSecret(privateKey, this, sharedSecret)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
sharedSecret = this.deriveSharedSecret(privateKey)
|
|
228
|
+
}
|
|
209
229
|
const invoiceNumberBin = toArray(invoiceNumber, 'utf8')
|
|
210
230
|
const hmac = sha256hmac(sharedSecret.encode(true), invoiceNumberBin)
|
|
211
231
|
const curve = new Curve()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PrivateKey, PublicKey, SymmetricKey } from '../primitives/index.js'
|
|
2
|
-
import { Counterparty, KeyDeriver } from './KeyDeriver.js'
|
|
1
|
+
import { Point, PrivateKey, PublicKey, SymmetricKey } from '../primitives/index.js'
|
|
2
|
+
import { Counterparty, KeyDeriver, KeyDeriverApi } from './KeyDeriver.js'
|
|
3
3
|
import { WalletProtocol } from './Wallet.interfaces.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -7,11 +7,21 @@ import { WalletProtocol } from './Wallet.interfaces.js'
|
|
|
7
7
|
* This is useful for optimizing performance when the same keys are derived multiple times.
|
|
8
8
|
* It supports configurable cache size with sane defaults and maintains cache entries using LRU (Least Recently Used) eviction policy.
|
|
9
9
|
*/
|
|
10
|
-
export default class CachedKeyDeriver {
|
|
10
|
+
export default class CachedKeyDeriver implements KeyDeriverApi {
|
|
11
11
|
private readonly keyDeriver: KeyDeriver
|
|
12
|
-
private readonly cache: Map<string, PublicKey | PrivateKey | SymmetricKey | number[]>
|
|
12
|
+
private readonly cache: Map<string, PublicKey | PrivateKey | SymmetricKey | Point | number[]>
|
|
13
13
|
private readonly maxCacheSize: number
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* The root key from which all other keys are derived.
|
|
17
|
+
*/
|
|
18
|
+
rootKey: PrivateKey
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The identity of this key deriver which is normally the public key associated with the `rootKey`
|
|
22
|
+
*/
|
|
23
|
+
identityKey: string
|
|
24
|
+
|
|
15
25
|
/**
|
|
16
26
|
* Initializes the CachedKeyDeriver instance with a root private key and optional cache settings.
|
|
17
27
|
* @param {PrivateKey | 'anyone'} rootKey - The root private key or the string 'anyone'.
|
|
@@ -22,8 +32,22 @@ export default class CachedKeyDeriver {
|
|
|
22
32
|
rootKey: PrivateKey | 'anyone',
|
|
23
33
|
options?: { maxCacheSize?: number }
|
|
24
34
|
) {
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
if (rootKey === 'anyone') {
|
|
36
|
+
this.rootKey = new PrivateKey(1)
|
|
37
|
+
} else {
|
|
38
|
+
this.rootKey = rootKey
|
|
39
|
+
}
|
|
40
|
+
this.keyDeriver = new KeyDeriver(
|
|
41
|
+
this.rootKey,
|
|
42
|
+
(priv, pub, point) => {
|
|
43
|
+
this.cacheSet(`${priv.toString()}-${pub.toString()}`, point)
|
|
44
|
+
},
|
|
45
|
+
(priv, pub) => {
|
|
46
|
+
return this.cacheGet(`${priv.toString()}-${pub.toString()}`) as Point | undefined
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
this.identityKey = this.rootKey.toPublicKey().toString()
|
|
50
|
+
this.cache = new Map<string, PublicKey | PrivateKey | SymmetricKey | Point | number[]>()
|
|
27
51
|
const maxCacheSize = options?.maxCacheSize
|
|
28
52
|
this.maxCacheSize = (maxCacheSize != null && !isNaN(maxCacheSize) && maxCacheSize > 0) ? maxCacheSize : 1000
|
|
29
53
|
}
|
|
@@ -237,7 +261,7 @@ export default class CachedKeyDeriver {
|
|
|
237
261
|
* @param {string} cacheKey - The key of the cached item.
|
|
238
262
|
* @returns {any} - The cached value.
|
|
239
263
|
*/
|
|
240
|
-
private cacheGet (cacheKey: string): PublicKey | PrivateKey | SymmetricKey | number[] | undefined {
|
|
264
|
+
private cacheGet (cacheKey: string): PublicKey | PrivateKey | SymmetricKey | Point | number[] | undefined {
|
|
241
265
|
const value = this.cache.get(cacheKey)
|
|
242
266
|
// Update the entry to reflect recent use
|
|
243
267
|
this.cache.delete(cacheKey)
|
|
@@ -252,7 +276,7 @@ export default class CachedKeyDeriver {
|
|
|
252
276
|
* @param {string} cacheKey - The key of the item to cache.
|
|
253
277
|
* @param {any} value - The value to cache.
|
|
254
278
|
*/
|
|
255
|
-
private cacheSet (cacheKey: string, value: PublicKey | PrivateKey | SymmetricKey | number[]): void {
|
|
279
|
+
private cacheSet (cacheKey: string, value: PublicKey | PrivateKey | SymmetricKey | Point | number[]): void {
|
|
256
280
|
if (this.cache.size >= this.maxCacheSize) {
|
|
257
281
|
// Evict the least recently used item (first item in Map)
|
|
258
282
|
const firstKey = this.cache.keys().next().value
|
package/src/wallet/KeyDeriver.ts
CHANGED
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
PublicKey,
|
|
4
4
|
SymmetricKey,
|
|
5
5
|
Hash,
|
|
6
|
-
Utils
|
|
6
|
+
Utils,
|
|
7
|
+
Point
|
|
7
8
|
} from '../primitives/index.js'
|
|
8
9
|
import { WalletProtocol, PubKeyHex } from './Wallet.interfaces.js'
|
|
9
10
|
|
|
@@ -92,12 +93,18 @@ export interface KeyDeriverApi {
|
|
|
92
93
|
export class KeyDeriver implements KeyDeriverApi {
|
|
93
94
|
rootKey: PrivateKey
|
|
94
95
|
identityKey: string
|
|
96
|
+
private readonly anyone: PublicKey
|
|
95
97
|
|
|
96
98
|
/**
|
|
97
99
|
* Initializes the KeyDeriver instance with a root private key.
|
|
98
100
|
* @param {PrivateKey | 'anyone'} rootKey - The root private key or the string 'anyone'.
|
|
99
101
|
*/
|
|
100
|
-
constructor (
|
|
102
|
+
constructor (
|
|
103
|
+
rootKey: PrivateKey | 'anyone',
|
|
104
|
+
private readonly cacheSharedSecret?: ((priv: PrivateKey, pub: Point, point: Point) => void),
|
|
105
|
+
private readonly retrieveCachedSharedSecret?: ((priv: PrivateKey, pub: Point) => (Point | undefined))
|
|
106
|
+
) {
|
|
107
|
+
this.anyone = new PrivateKey(1).toPublicKey()
|
|
101
108
|
if (rootKey === 'anyone') {
|
|
102
109
|
this.rootKey = new PrivateKey(1)
|
|
103
110
|
} else {
|
|
@@ -123,12 +130,19 @@ export class KeyDeriver implements KeyDeriverApi {
|
|
|
123
130
|
counterparty = this.normalizeCounterparty(counterparty)
|
|
124
131
|
if (forSelf) {
|
|
125
132
|
return this.rootKey
|
|
126
|
-
.deriveChild(
|
|
133
|
+
.deriveChild(
|
|
134
|
+
counterparty,
|
|
135
|
+
this.computeInvoiceNumber(protocolID, keyID),
|
|
136
|
+
this.cacheSharedSecret,
|
|
137
|
+
this.retrieveCachedSharedSecret
|
|
138
|
+
)
|
|
127
139
|
.toPublicKey()
|
|
128
140
|
} else {
|
|
129
141
|
return counterparty.deriveChild(
|
|
130
142
|
this.rootKey,
|
|
131
|
-
this.computeInvoiceNumber(protocolID, keyID)
|
|
143
|
+
this.computeInvoiceNumber(protocolID, keyID),
|
|
144
|
+
this.cacheSharedSecret,
|
|
145
|
+
this.retrieveCachedSharedSecret
|
|
132
146
|
)
|
|
133
147
|
}
|
|
134
148
|
}
|
|
@@ -148,7 +162,9 @@ export class KeyDeriver implements KeyDeriverApi {
|
|
|
148
162
|
counterparty = this.normalizeCounterparty(counterparty)
|
|
149
163
|
return this.rootKey.deriveChild(
|
|
150
164
|
counterparty,
|
|
151
|
-
this.computeInvoiceNumber(protocolID, keyID)
|
|
165
|
+
this.computeInvoiceNumber(protocolID, keyID),
|
|
166
|
+
this.cacheSharedSecret,
|
|
167
|
+
this.retrieveCachedSharedSecret
|
|
152
168
|
)
|
|
153
169
|
}
|
|
154
170
|
|
|
@@ -168,7 +184,7 @@ export class KeyDeriver implements KeyDeriverApi {
|
|
|
168
184
|
// If counterparty is 'anyone', we use 1*G as the public key.
|
|
169
185
|
// This is a publicly derivable key and should only be used in scenarios where public disclosure is intended.
|
|
170
186
|
if (counterparty === 'anyone') {
|
|
171
|
-
counterparty =
|
|
187
|
+
counterparty = this.anyone
|
|
172
188
|
}
|
|
173
189
|
counterparty = this.normalizeCounterparty(counterparty)
|
|
174
190
|
const derivedPublicKey = this.derivePublicKey(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KeyDeriver, KeyDeriverApi } from './KeyDeriver.js'
|
|
2
|
+
import CachedKeyDeriver from './CachedKeyDeriver.js'
|
|
2
3
|
import {
|
|
3
4
|
Hash,
|
|
4
5
|
ECDSA,
|
|
@@ -42,11 +43,11 @@ export class ProtoWallet {
|
|
|
42
43
|
|
|
43
44
|
constructor (rootKeyOrKeyDeriver?: PrivateKey | 'anyone' | KeyDeriverApi) {
|
|
44
45
|
if (typeof (rootKeyOrKeyDeriver as KeyDeriver).identityKey !== 'string') {
|
|
45
|
-
rootKeyOrKeyDeriver = new
|
|
46
|
+
rootKeyOrKeyDeriver = new CachedKeyDeriver(
|
|
46
47
|
rootKeyOrKeyDeriver as PrivateKey | 'anyone'
|
|
47
48
|
)
|
|
48
49
|
}
|
|
49
|
-
this.keyDeriver = rootKeyOrKeyDeriver as
|
|
50
|
+
this.keyDeriver = rootKeyOrKeyDeriver as KeyDeriverApi
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
async getPublicKey (
|