@tdxvolt/volt-client-grpc 0.16.0-beta.1 → 0.16.0-beta.12
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/README.md +1 -1
- package/lib/index.cjs +444 -407
- package/package.json +2 -4
- package/protobuf/tdx/volt_api/data/v1/sqlite_database_api.proto +49 -13
- package/protobuf/tdx/volt_api/data/v1/sqlite_server_api.proto +3 -0
- package/protobuf/tdx/volt_api/volt/v1/discovery_api.proto +0 -4
- package/protobuf/tdx/volt_api/volt/v1/ssi.proto +31 -5
- package/protobuf/tdx/volt_api/volt/v1/ssi_api.proto +119 -31
- package/protobuf/tdx/volt_api/volt/v1/terminal_api.proto +42 -0
- package/protobuf/tdx/volt_api/volt/v1/volt.proto +141 -134
- package/protobuf/tdx/volt_api/volt/v1/volt_api.proto +138 -234
- package/src/constants.js +3 -5
- package/src/grpc-call.js +142 -51
- package/src/grpc-utils.js +8 -4
- package/src/rpc-invocation.js +94 -46
- package/src/utils.js +4 -119
- package/src/volt-client-internal.js +123 -216
- package/src/volt-client.js +33 -13
- package/src/volt-connection.js +25 -16
- package/src/volt-credential.js +46 -125
package/src/volt-credential.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
|
2
2
|
import debug from "debug";
|
|
3
3
|
import fs from "fs";
|
|
4
|
-
import forge from "node-forge";
|
|
5
|
-
import jwt from "jsonwebtoken";
|
|
6
|
-
import crypto from "crypto";
|
|
7
|
-
import * as voltUtils from "./utils.js";
|
|
8
4
|
import { constants } from "./constants.js";
|
|
5
|
+
import {
|
|
6
|
+
createKey,
|
|
7
|
+
fingerprintFromPublicKey,
|
|
8
|
+
getIdentityToken,
|
|
9
|
+
keyFromPem,
|
|
10
|
+
privateKeyToPem,
|
|
11
|
+
publicKeyToPem
|
|
12
|
+
} from "@tdxvolt/volt-client-web";
|
|
9
13
|
|
|
10
|
-
const { pki } = forge;
|
|
11
14
|
const log = debug("volt-client-grpc:volt-credential");
|
|
12
|
-
const aesAlgorithm = "aes-256-cbc";
|
|
13
|
-
const rs256Algorithm = "RS256";
|
|
14
15
|
|
|
15
16
|
export class VoltCredential {
|
|
16
17
|
constructor(config, configPath) {
|
|
@@ -34,14 +35,13 @@ export class VoltCredential {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// Need to unencrypt the private key.
|
|
37
|
-
const decrypted =
|
|
38
|
-
|
|
39
|
-
config.p
|
|
40
|
-
);
|
|
38
|
+
const decrypted = keyFromPem(this._cryptoCache.key, config.p);
|
|
39
|
+
|
|
41
40
|
if (!decrypted) {
|
|
42
41
|
throw new Error("failed to decrypt key - check passphrase");
|
|
43
42
|
}
|
|
44
|
-
|
|
43
|
+
|
|
44
|
+
this._cryptoCache.key = privateKeyToPem(decrypted);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if (this._voltConfig.ca_pem) {
|
|
@@ -50,14 +50,11 @@ export class VoltCredential {
|
|
|
50
50
|
this._cryptoCache.ca = this._voltConfig.ca_pem;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
// Pre-cache the target Volt public key by extracting it from the signing certificate.
|
|
54
|
-
const voltCert = forge.pki.certificateFromPem(this._voltConfig.ca_pem);
|
|
55
|
-
|
|
56
53
|
// Extract Volt public key (used for encrypting Relay payloads).
|
|
57
|
-
this._voltPublicKey =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
);
|
|
54
|
+
this._voltPublicKey = this._voltConfig.public_key;
|
|
55
|
+
|
|
56
|
+
const voltKey = keyFromPem(this._voltPublicKey).publicKey;
|
|
57
|
+
this._voltFingerprint = fingerprintFromPublicKey(voltKey);
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
60
|
|
|
@@ -69,8 +66,16 @@ export class VoltCredential {
|
|
|
69
66
|
return this._cryptoCache;
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
get
|
|
73
|
-
return this._cryptoCache.
|
|
69
|
+
get certificate() {
|
|
70
|
+
return this._cryptoCache.cert;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get sessionId() {
|
|
74
|
+
return this._cryptoCache.session_id;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get identityId() {
|
|
78
|
+
return this._cryptoCache.identity_did;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
get voltPublicKey() {
|
|
@@ -78,7 +83,7 @@ export class VoltCredential {
|
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
get publicKey() {
|
|
81
|
-
return
|
|
86
|
+
return publicKeyToPem(this.getKey().publicKey);
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
get voltFingerprint() {
|
|
@@ -86,9 +91,8 @@ export class VoltCredential {
|
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
getKey() {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
return { privateKey, publicKey };
|
|
94
|
+
const key = keyFromPem(this._cryptoCache.key);
|
|
95
|
+
return key;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
/**
|
|
@@ -101,17 +105,10 @@ export class VoltCredential {
|
|
|
101
105
|
return Promise.resolve(this.getKey());
|
|
102
106
|
} else {
|
|
103
107
|
log("creating key");
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this._cryptoCache.key = keyInfo.pem;
|
|
109
|
-
return keyInfo.keypair;
|
|
110
|
-
})
|
|
111
|
-
.catch((err) => {
|
|
112
|
-
log("failure creating key [%s]", err.message);
|
|
113
|
-
return Promise.reject(err);
|
|
114
|
-
});
|
|
108
|
+
this._cryptoCache.key = createKey();
|
|
109
|
+
const key = keyFromPem(this._cryptoCache.key);
|
|
110
|
+
log("successfully created key");
|
|
111
|
+
return Promise.resolve(key);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
|
|
@@ -136,55 +133,6 @@ export class VoltCredential {
|
|
|
136
133
|
return !!this._cryptoCache.cert;
|
|
137
134
|
}
|
|
138
135
|
|
|
139
|
-
/**
|
|
140
|
-
* Signs the identity resource id using the private key.
|
|
141
|
-
* @param {*} audience the token audience (usually the target volt)
|
|
142
|
-
* @param {*} tunnelling flag indicating if the token is required for a tunnelled connection
|
|
143
|
-
* @param {*} ttl time to live in seconds (default to 1 minute)
|
|
144
|
-
*/
|
|
145
|
-
getIdentityToken(audience, publicKey, tunnelling = false, ttl = 60) {
|
|
146
|
-
if (!this._cryptoCache.key) {
|
|
147
|
-
throw new Error("crypto cache invalid");
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const keyPair = this.getKey();
|
|
151
|
-
const publicKeyPem = pki.publicKeyToPem(keyPair.publicKey);
|
|
152
|
-
const base58Key = voltUtils.createPublicKeyFingerprint(publicKeyPem);
|
|
153
|
-
|
|
154
|
-
log("base58 key is %s", base58Key);
|
|
155
|
-
|
|
156
|
-
// Allow TTL either side of the current time.
|
|
157
|
-
// @todo - fix with server time sync on volt connection.
|
|
158
|
-
const payload = {
|
|
159
|
-
aud: audience,
|
|
160
|
-
iat: Math.floor(Date.now() / 1000) - ttl,
|
|
161
|
-
exp: Math.floor(Date.now() / 1000) + ttl,
|
|
162
|
-
sub: this._cryptoCache.client_id
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
let sharedKey;
|
|
166
|
-
if (tunnelling) {
|
|
167
|
-
// Initialise the Relay encryption key.
|
|
168
|
-
sharedKey = VoltCredential.aesCreateKey();
|
|
169
|
-
|
|
170
|
-
// Encrypt the key details using the target Volt public key and include this in the JWT payload.
|
|
171
|
-
payload.sk = VoltCredential.rsaEncrypt(publicKey, sharedKey.key);
|
|
172
|
-
payload.iv = VoltCredential.rsaEncrypt(publicKey, sharedKey.iv);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Sign synchronously.
|
|
176
|
-
const token = jwt.sign(payload, this._cryptoCache.key, {
|
|
177
|
-
algorithm: rs256Algorithm,
|
|
178
|
-
keyid: base58Key
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Return the token along with any encryption key details.
|
|
182
|
-
return {
|
|
183
|
-
token,
|
|
184
|
-
sharedKey
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
136
|
/**
|
|
189
137
|
* Creates the metadata required for a grpc call, including the Volt authentication token
|
|
190
138
|
* and optionally tunnel encryption parameters.
|
|
@@ -195,9 +143,12 @@ export class VoltCredential {
|
|
|
195
143
|
* @returns
|
|
196
144
|
*/
|
|
197
145
|
getIdentityMetadata(grpc, audience, publicKey, tunnelling = false, ttl = 60) {
|
|
198
|
-
const
|
|
146
|
+
const key = keyFromPem(this._cryptoCache.key);
|
|
147
|
+
|
|
148
|
+
const identityToken = getIdentityToken(
|
|
149
|
+
this.sessionId,
|
|
150
|
+
key,
|
|
199
151
|
audience || this._voltConfig.id,
|
|
200
|
-
publicKey,
|
|
201
152
|
tunnelling,
|
|
202
153
|
ttl
|
|
203
154
|
);
|
|
@@ -207,47 +158,17 @@ export class VoltCredential {
|
|
|
207
158
|
}
|
|
208
159
|
|
|
209
160
|
saveCache() {
|
|
161
|
+
const clone = { ...this._config, credential: { ...this._cryptoCache } };
|
|
162
|
+
if (this._config.p) {
|
|
163
|
+
// A passphrase option exists => encrypt the key before writing the cache file.
|
|
164
|
+
const key = keyFromPem(this._cryptoCache.key);
|
|
165
|
+
clone.credential.key = privateKeyToPem(key.privateKey, this._config.p);
|
|
166
|
+
}
|
|
167
|
+
|
|
210
168
|
if (this._persistCache) {
|
|
211
|
-
const clone = { ...this._config, credential: { ...this._cryptoCache } };
|
|
212
|
-
if (this._config.p) {
|
|
213
|
-
// A passphrase option exists => encrypt the key before writing the cache file.
|
|
214
|
-
const privateKey = pki.privateKeyFromPem(this._cryptoCache.key);
|
|
215
|
-
clone.credential.key = pki.encryptRsaPrivateKey(
|
|
216
|
-
privateKey,
|
|
217
|
-
this._config.p
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
169
|
fs.writeFileSync(this._configPath, JSON.stringify(clone, null, 2));
|
|
221
170
|
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
static aesCreateKey() {
|
|
225
|
-
// Generate random key for the AES-256 algorithm (32 bytes = 256 bits).
|
|
226
|
-
const key = crypto.randomBytes(32);
|
|
227
|
-
const iv = crypto.randomBytes(16);
|
|
228
|
-
return { key, iv };
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
static aesEncrypt(buffer, key, iv) {
|
|
232
|
-
const cipher = crypto.createCipheriv(aesAlgorithm, key, iv);
|
|
233
|
-
const crypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
234
|
-
return crypted;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
static aesDecrypt(buffer, key, iv) {
|
|
238
|
-
const cipher = crypto.createDecipheriv(aesAlgorithm, key, iv);
|
|
239
|
-
const decrypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
|
|
240
|
-
return decrypted;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
static rsaEncrypt(key, buffer) {
|
|
244
|
-
const cipher = crypto.publicEncrypt(key, buffer);
|
|
245
|
-
return cipher.toString("base64url");
|
|
246
|
-
}
|
|
247
171
|
|
|
248
|
-
|
|
249
|
-
const keyObj = crypto.createPrivateKey(key);
|
|
250
|
-
const cipher = Buffer.from(buffer, "base64url");
|
|
251
|
-
return Buffer.from(crypto.privateDecrypt(keyObj, cipher));
|
|
172
|
+
return clone;
|
|
252
173
|
}
|
|
253
174
|
}
|