Skip to content

Commit be728ab

Browse files
feat(abstract-lightning): make encrypted prv key optional in get key
wallet shared users control prv key of user auth key alone, not node auth and user keys. Ticket: BTC-1934
1 parent 4a66143 commit be728ab

File tree

5 files changed

+62
-29
lines changed

5 files changed

+62
-29
lines changed

modules/abstract-lightning/src/codecs/api/wallet.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,34 @@ export type KeyPurpose = t.TypeOf<typeof KeyPurpose>;
1010

1111
export const LightningAuthKeychainCoinSpecific = getCodecPair(t.type({ purpose: KeyPurpose }));
1212

13-
export const LightningKeychain = t.strict(
14-
{
15-
id: NonEmptyString,
16-
pub: NonEmptyString,
17-
encryptedPrv: NonEmptyString,
18-
source: t.literal('user'),
19-
},
13+
export const LightningKeychain = t.intersection(
14+
[
15+
t.type({
16+
id: NonEmptyString,
17+
pub: NonEmptyString,
18+
source: t.literal('user'),
19+
}),
20+
t.partial({
21+
encryptedPrv: NonEmptyString,
22+
}),
23+
],
2024
'LightningKeychain'
2125
);
2226

2327
export type LightningKeychain = t.TypeOf<typeof LightningKeychain>;
2428

25-
export const LightningAuthKeychain = t.strict(
26-
{
27-
id: NonEmptyString,
28-
pub: NonEmptyString,
29-
encryptedPrv: NonEmptyString,
30-
coinSpecific: LightningAuthKeychainCoinSpecific,
31-
source: t.literal('user'),
32-
},
29+
export const LightningAuthKeychain = t.intersection(
30+
[
31+
t.type({
32+
id: NonEmptyString,
33+
pub: NonEmptyString,
34+
coinSpecific: LightningAuthKeychainCoinSpecific,
35+
source: t.literal('user'),
36+
}),
37+
t.partial({
38+
encryptedPrv: NonEmptyString,
39+
}),
40+
],
3341
'LightningAuthKeychain'
3442
);
3543

modules/abstract-lightning/src/wallet/lightning.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,13 @@ export class LightningWallet implements ILightningWallet {
239239
this.wallet.bitgo.setRequestTracer(reqId);
240240

241241
const { userAuthKey } = await getLightningAuthKeychains(this.wallet);
242+
const userAuthKeyEncryptedPrv = userAuthKey.encryptedPrv;
243+
if (!userAuthKeyEncryptedPrv) {
244+
throw new Error(`user auth key is missing encrypted private key`);
245+
}
242246
const signature = createMessageSignature(
243247
t.exact(LightningPaymentRequest).encode(params),
244-
this.wallet.bitgo.decrypt({ password: params.passphrase, input: userAuthKey.encryptedPrv })
248+
this.wallet.bitgo.decrypt({ password: params.passphrase, input: userAuthKeyEncryptedPrv })
245249
);
246250

247251
const paymentIntent: { intent: LightningPaymentIntent } = {

modules/abstract-lightning/src/wallet/selfCustodialLightning.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import * as sdkcore from '@bitgo/sdk-core';
2-
import {
3-
BackupResponse,
4-
LightningAuthKeychain,
5-
UpdateLightningWalletClientRequest,
6-
UpdateLightningWalletEncryptedRequest,
7-
} from '../codecs';
2+
import { BackupResponse, UpdateLightningWalletClientRequest, UpdateLightningWalletEncryptedRequest } from '../codecs';
83
import { getLightningAuthKeychains, ILightningWallet, LightningWallet } from './lightning';
94
import { createMessageSignature, deriveLightningServiceSharedSecret, isLightningCoinName } from '../lightning';
105
import * as t from 'io-ts';
116

127
function encryptWalletUpdateRequest(
138
wallet: sdkcore.IWallet,
149
params: UpdateLightningWalletClientRequest,
15-
userAuthKey: LightningAuthKeychain
10+
userAuthKeyEncryptedPrv: string
1611
): UpdateLightningWalletEncryptedRequest {
1712
const coinName = wallet.coin() as 'tlnbtc' | 'lnbtc';
1813

@@ -22,7 +17,7 @@ function encryptWalletUpdateRequest(
2217

2318
const userAuthXprv = wallet.bitgo.decrypt({
2419
password: params.passphrase,
25-
input: userAuthKey.encryptedPrv,
20+
input: userAuthKeyEncryptedPrv,
2621
});
2722

2823
if (params.signerTlsKey) {
@@ -87,10 +82,14 @@ export async function updateWalletCoinSpecific(
8782
);
8883

8984
const { userAuthKey } = await getLightningAuthKeychains(wallet);
90-
const updateRequestWithEncryption = encryptWalletUpdateRequest(wallet, params, userAuthKey);
85+
const userAuthKeyEncryptedPrv = userAuthKey.encryptedPrv;
86+
if (!userAuthKeyEncryptedPrv) {
87+
throw new Error(`user auth key is missing encrypted private key`);
88+
}
89+
const updateRequestWithEncryption = encryptWalletUpdateRequest(wallet, params, userAuthKeyEncryptedPrv);
9190
const signature = createMessageSignature(
9291
updateRequestWithEncryption,
93-
wallet.bitgo.decrypt({ password: params.passphrase, input: userAuthKey.encryptedPrv })
92+
wallet.bitgo.decrypt({ password: params.passphrase, input: userAuthKeyEncryptedPrv })
9493
);
9594
const coinSpecific = {
9695
[wallet.coin()]: {

modules/abstract-lightning/test/unit/lightning/codecs.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ describe('Codecs', function () {
3737
encryptedPrv: 'encryptedPrv',
3838
source: 'user',
3939
},
40+
{
41+
id: 'id',
42+
pub: 'xpub',
43+
source: 'user',
44+
},
4045
],
4146
[
4247
null,
@@ -65,6 +70,16 @@ describe('Codecs', function () {
6570
},
6671
},
6772
},
73+
{
74+
id: 'id',
75+
pub: 'xpub',
76+
source: 'user',
77+
coinSpecific: {
78+
lnbtc: {
79+
purpose: 'userAuth',
80+
},
81+
},
82+
},
6883
],
6984
[
7085
null,

modules/express/src/lightning/lightningSignerRoutes.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,18 @@ export async function handleInitLightningWallet(req: express.Request): Promise<u
9191
const lndSignerClient = await LndSignerClient.create(walletId, req.config);
9292

9393
const userKey = await getLightningKeychain(wallet);
94+
const userKeyEncryptedPrv = userKey.encryptedPrv;
95+
if (!userKeyEncryptedPrv) {
96+
throw new ApiResponseError('Missing encryptedPrv in user keychain', 400);
97+
}
9498
const { nodeAuthKey } = await getLightningAuthKeychains(wallet);
95-
99+
const nodeAuthKeyEncryptedPrv = nodeAuthKey.encryptedPrv;
100+
if (!nodeAuthKeyEncryptedPrv) {
101+
throw new ApiResponseError('Missing encryptedPrv in node auth keychain', 400);
102+
}
96103
const network = getUtxolibNetwork(coin.getChain());
97-
const signerRootKey = getSignerRootKey(passphrase, userKey.encryptedPrv, network, bitgo.decrypt);
98-
const macaroonRootKey = getMacaroonRootKey(passphrase, nodeAuthKey.encryptedPrv, bitgo.decrypt);
104+
const signerRootKey = getSignerRootKey(passphrase, userKeyEncryptedPrv, network, bitgo.decrypt);
105+
const macaroonRootKey = getMacaroonRootKey(passphrase, nodeAuthKeyEncryptedPrv, bitgo.decrypt);
99106

100107
const { admin_macaroon: adminMacaroon } = await lndSignerClient.initWallet({
101108
// The passphrase at LND can only accommodate a base64 character set

0 commit comments

Comments
 (0)