@eluvio/elv-client-js 4.2.21 → 4.2.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "4.2.21",
3
+ "version": "4.2.23",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/Crypto.js CHANGED
@@ -82,7 +82,19 @@ const Crypto = {
82
82
  return Utils.B64(cap);
83
83
  },
84
84
 
85
- async DecryptCap(encryptedCap, privateKey) {
85
+ // accepts either a raw private key string (legacy usage) or a signer
86
+ async DecryptCap(encryptedCap, signerOrPrivateKey) {
87
+ let privateKey;
88
+ if(typeof signerOrPrivateKey === "string") {
89
+ privateKey = signerOrPrivateKey;
90
+ } else if(signerOrPrivateKey && signerOrPrivateKey.remoteSigner) {
91
+ return await signerOrPrivateKey.DecryptCap(encryptedCap);
92
+ } else if(signerOrPrivateKey && typeof signerOrPrivateKey._signingKey === "function") {
93
+ privateKey = signerOrPrivateKey._signingKey().privateKey;
94
+ } else {
95
+ throw Error("Crypto.DecryptCap: second argument must be a signer or a private key string");
96
+ }
97
+
86
98
  const elvCrypto = await Crypto.ElvCrypto();
87
99
  privateKey = new Uint8Array(Buffer.from(privateKey.replace("0x", ""), "hex"));
88
100
 
package/src/ElvClient.js CHANGED
@@ -1348,7 +1348,7 @@ class ElvClient {
1348
1348
 
1349
1349
  ValidatePresence("message", message);
1350
1350
 
1351
- return await this.Crypto.DecryptCap(message, this.signer._signingKey().privateKey);
1351
+ return await this.Crypto.DecryptCap(message, this.signer);
1352
1352
  }
1353
1353
 
1354
1354
  /**
@@ -47,7 +47,7 @@ class RemoteSigner extends Ethers.Signer {
47
47
  body.code = this.userIdCode;
48
48
  }
49
49
 
50
- const {addr, eth, token} = await Utils.ResponseToJson(
50
+ const {addr, eth, token, pubkey} = await Utils.ResponseToJson(
51
51
  this.HttpClient.Request({
52
52
  path: UrlJoin("as", "wlt", "login", this.userIdCode ? "code" : "jwt"),
53
53
  method: "POST",
@@ -61,9 +61,10 @@ class RemoteSigner extends Ethers.Signer {
61
61
  this.authToken = token;
62
62
  this.address = Utils.FormatAddress(addr);
63
63
  this.id = eth;
64
+ this.publicKey = pubkey;
64
65
  }
65
66
 
66
- if(!this.address) {
67
+ if(!this.address || !this.publicKey) {
67
68
  const keys = await Utils.ResponseToJson(
68
69
  this.HttpClient.Request({
69
70
  method: "GET",
@@ -74,12 +75,18 @@ class RemoteSigner extends Ethers.Signer {
74
75
  })
75
76
  );
76
77
 
77
- const address = keys.eth[0];
78
+ if(!this.address) {
79
+ const address = keys.eth[0];
78
80
 
79
- if(address && address.startsWith("0x")) {
80
- this.address = address;
81
- } else {
82
- this.address = Utils.HashToAddress(keys.eth[0]);
81
+ if(address && address.startsWith("0x")) {
82
+ this.address = address;
83
+ } else {
84
+ this.address = Utils.HashToAddress(keys.eth[0]);
85
+ }
86
+ }
87
+
88
+ if(!this.publicKey) {
89
+ this.publicKey = keys.pubkey && keys.pubkey[0];
83
90
  }
84
91
  }
85
92
 
@@ -170,6 +177,63 @@ class RemoteSigner extends Ethers.Signer {
170
177
  return this.address;
171
178
  }
172
179
 
180
+ _normalizePublicKey(key) {
181
+ const with0x = key.startsWith("0x") ? key : `0x${key}`;
182
+ return with0x.length === 2 + 128 ? `0x04${with0x.slice(2)}` : with0x;
183
+ }
184
+
185
+ /**
186
+ * This signer's public key, as provided by the authd service
187
+ *
188
+ * @return {Promise<string>} - The public key, in uncompressed hex like SigningKey.publicKey
189
+ */
190
+ async PublicKey() {
191
+ if(!this.publicKey) {
192
+ throw Error("RemoteSigner: public key not available - call Initialize() first");
193
+ }
194
+
195
+ return this._normalizePublicKey(this.publicKey);
196
+ }
197
+
198
+ /** so remote signers can be used interchangeably with local signers */
199
+ _signingKey() {
200
+ if(!this.publicKey) {
201
+ throw Error("RemoteSigner: public key not available - call Initialize() first");
202
+ }
203
+
204
+ const publicKey = this._normalizePublicKey(this.publicKey);
205
+ return {
206
+ publicKey,
207
+ get privateKey() {
208
+ throw Error("RemoteSigner: remote signer does not have direct access to a private key");
209
+ }
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Decrypt a secp256k1 ECIES-encrypted blob (e.g. a fabric encryption conk) that was wrapped
215
+ * for this signer's public key, via the authd service's generic decrypt endpoint.
216
+ *
217
+ * @param {string} encryptedData - Base64-encoded ECIES-encrypted blob
218
+ * @return {Promise<Object>} - The decrypted, JSON-parsed contents
219
+ */
220
+ async DecryptCap(encryptedData) {
221
+ const {data} = await Utils.ResponseToJson(
222
+ this.HttpClient.Request({
223
+ method: "POST",
224
+ path: UrlJoin("as", "wlt", "decrypt", "eth", this.id),
225
+ headers: {
226
+ Authorization: `Bearer ${this.authToken}`
227
+ },
228
+ body: {
229
+ data: encryptedData
230
+ }
231
+ })
232
+ );
233
+
234
+ return JSON.parse(Buffer.from(data, "base64").toString());
235
+ }
236
+
173
237
  async signDigest(digest) {
174
238
  if(!this.signatureCache[digest]) {
175
239
  this.signatureCache[digest] = new Promise(async (resolve, reject) => {
@@ -2718,7 +2718,7 @@ exports.LinkData = async function({libraryId, objectId, versionHash, writeToken,
2718
2718
 
2719
2719
  exports.CreateEncryptionConk = async function({libraryId, objectId, versionHash, writeToken, createKMSConk=true}) {
2720
2720
  if(this.signer.remoteSigner) {
2721
- return;
2721
+ await this.signer.PublicKey();
2722
2722
  }
2723
2723
 
2724
2724
  ValidateParameters({libraryId, objectId, versionHash});
@@ -2743,7 +2743,7 @@ exports.CreateEncryptionConk = async function({libraryId, objectId, versionHash,
2743
2743
  });
2744
2744
 
2745
2745
  if(existingUserCap) {
2746
- this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2746
+ this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer);
2747
2747
  } else {
2748
2748
  this.encryptionConks[objectId] = await this.Crypto.GeneratePrimaryConk({
2749
2749
  spaceId: this.contentSpaceId,
@@ -2846,7 +2846,7 @@ exports.EncryptionConk = async function({libraryId, objectId, versionHash, write
2846
2846
  });
2847
2847
 
2848
2848
  if(existingUserCap) {
2849
- this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer._signingKey().privateKey);
2849
+ this.encryptionConks[objectId] = await this.Crypto.DecryptCap(existingUserCap, this.signer);
2850
2850
  } else if(writeToken) {
2851
2851
  await this.CreateEncryptionConk({libraryId, objectId, versionHash, writeToken, createKMSConk: false});
2852
2852
  } else {
@@ -680,7 +680,7 @@ exports.CopyContentObject = async function({libraryId, originalVersionHash, opti
680
680
  const userCapKey = `eluv.caps.iusr${this.utils.AddressToHash(this.signer.address)}`;
681
681
 
682
682
  if(metadata[userCapKey]) {
683
- const userConkKey = await this.Crypto.DecryptCap(metadata[userCapKey], this.signer._signingKey().privateKey);
683
+ const userConkKey = await this.Crypto.DecryptCap(metadata[userCapKey], this.signer);
684
684
  userConkKey.qid = objectId;
685
685
 
686
686
  await this.ReplaceMetadata({
@@ -733,7 +733,7 @@ exports.CreateNonOwnerCap = async function({objectId, libraryId, publicKey, writ
733
733
  throw Error("No user cap found for current user");
734
734
  }
735
735
 
736
- const userConk = await this.Crypto.DecryptCap(userCapValue, this.signer._signingKey().privateKey);
736
+ const userConk = await this.Crypto.DecryptCap(userCapValue, this.signer);
737
737
 
738
738
  const publicAddress = this.utils.PublicKeyToAddress(publicKey);
739
739