@ironcorelabs/ironweb 4.2.49 → 4.4.1

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/es/lib/Utils.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import * as UTF8 from "@stablelib/utf8";
2
2
  import { fromByteArray, toByteArray } from "base64-js";
3
+ import Future from "futurejs";
4
+ import { CryptoConstants, ErrorCodes, VERSION_HEADER_LENGTH, HEADER_META_LENGTH_LENGTH } from "../Constants";
5
+ import SDKError from "./SDKError";
3
6
  /**
4
7
  * Convert a string into a ArrayBuffer, specifically a Uint8Array
5
8
  */
@@ -59,6 +62,13 @@ export function concatArrayBuffers() {
59
62
  return newBuffer;
60
63
  }, new Uint8Array(length));
61
64
  }
65
+ /**
66
+ * Convert a transfer list of Uint8Arrays and Transferables into a Transferable[].
67
+ * Uint8Arrays are unwrapped to their underlying ArrayBuffer; other items pass through.
68
+ */
69
+ export function toTransferables(items) {
70
+ return items.map(function (item) { return (item instanceof Uint8Array ? item.buffer : item); });
71
+ }
62
72
  /**
63
73
  * Polyfill since some environments (notably Phantom) don't support ArrayBuffer.slice
64
74
  */
@@ -68,3 +78,30 @@ export function sliceArrayBuffer(buffer, start, end) {
68
78
  }
69
79
  return new Uint8Array(Array.prototype.slice.call(buffer, start, end));
70
80
  }
81
+ /**
82
+ * Parse the IronCore document header from encrypted document bytes.
83
+ * Extracts the document ID (if v2), IV, and the byte offset where ciphertext begins.
84
+ */
85
+ export function parseDocumentHeader(data) {
86
+ return Future.tryF(function () {
87
+ var version = data[0];
88
+ var documentID = null;
89
+ var headerTotalLength;
90
+ if (version === 1) {
91
+ headerTotalLength = VERSION_HEADER_LENGTH;
92
+ }
93
+ else if (version === 2) {
94
+ var headerJsonLength = new DataView(data.buffer, data.byteOffset).getUint16(VERSION_HEADER_LENGTH, false);
95
+ headerTotalLength = VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH + headerJsonLength;
96
+ var headerContent = data.slice(VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH, headerTotalLength);
97
+ var headerObject = JSON.parse(UTF8.decode(headerContent));
98
+ documentID = headerObject._did_;
99
+ }
100
+ else {
101
+ throw new Error("Provided encrypted document doesn't appear to be valid. Invalid version.");
102
+ }
103
+ var contentOffset = headerTotalLength + CryptoConstants.IV_LENGTH;
104
+ var iv = data.slice(headerTotalLength, contentOffset);
105
+ return { documentID: documentID, iv: iv, contentOffset: contentOffset };
106
+ }).errorMap(function (error) { return new SDKError(error, ErrorCodes.DOCUMENT_HEADER_PARSE_FAILURE); });
107
+ }
@@ -1,6 +1,7 @@
1
1
  import Future from "futurejs";
2
2
  import { ErrorCodes, Frame, Versions } from "../Constants";
3
3
  import SDKError from "../lib/SDKError";
4
+ import { toTransferables } from "../lib/Utils";
4
5
  /**
5
6
  * Class which handles messaging from the shim into the frame. Holds callback messages so that users can interact with this
6
7
  * class via Futures. Also handles the creation of all the ChannelMessage ports to pass down to the frame.
@@ -33,7 +34,7 @@ var ShimMessenger = /** @class */ (function () {
33
34
  /**
34
35
  * Post request message to child iFrame
35
36
  * @param {RequestMessage} data RequestMessage to post to child iFrame
36
- * @param {Uint8Array[]} transferList List of byte arrays to transfer to frame
37
+ * @param {Uint8Array[]} transferList List of byte arrays or transferables to transfer to frame
37
38
  */
38
39
  ShimMessenger.prototype.postMessageToFrame = function (data, transferList) {
39
40
  var _this = this;
@@ -43,16 +44,19 @@ var ShimMessenger = /** @class */ (function () {
43
44
  data: data,
44
45
  };
45
46
  try {
46
- this.messagePort.postMessage(message, transferList.map(function (_a) {
47
- var buffer = _a.buffer;
48
- return buffer;
49
- }));
47
+ this.messagePort.postMessage(message, toTransferables(transferList));
50
48
  return new Future(function (_, resolve) {
51
49
  _this.callbacks[message.replyID] = resolve;
52
50
  });
53
51
  }
54
- catch (_) {
55
- return Future.reject(new SDKError(new Error("Failure occurred when passing message due to the lack of browser support."), ErrorCodes.BROWSER_FRAME_MESSAGE_FAILURE));
52
+ catch (_e) {
53
+ var hasStreams = transferList.some(function (item) { return item instanceof ReadableStream || item instanceof WritableStream; });
54
+ // Safari is the notable holdout here (https://github.com/WebKit/standards-positions/issues/643). For now,
55
+ // give an informative message about support.
56
+ var message_1 = hasStreams
57
+ ? "Streaming encrypt/decrypt requires transferable streams, which is not supported by this browser. It is known to be supported by Chrome, Firefox, and Edge."
58
+ : "Failure occurred when passing message due to the lack of browser support.";
59
+ return Future.reject(new SDKError(new Error(message_1), ErrorCodes.BROWSER_FRAME_MESSAGE_FAILURE));
56
60
  }
57
61
  };
58
62
  return ShimMessenger;
@@ -74,7 +74,6 @@ export var createNewUser = function (jwtCallback, passcode, needsRotation) {
74
74
  return FrameMediator.sendMessage(payload);
75
75
  })
76
76
  //Rename a few fields and strip out the users private key and currentKeyId since they'll probably be confusing that they're getting back an encrypted private key
77
- //eslint-disable-next-line @typescript-eslint/no-unused-vars
78
77
  .map(function (_a) {
79
78
  var _b = _a.message, id = _b.id, segmentId = _b.segmentId, needsRotation = _b.needsRotation, status = _b.status, userMasterPublicKey = _b.userMasterPublicKey;
80
79
  return ({
@@ -157,3 +156,29 @@ export var deleteDeviceByPublicSigningKey = function (jwtCallback, publicSigning
157
156
  })
158
157
  .toPromise();
159
158
  };
159
+ /**
160
+ * Update the status (enabled or disabled) of the user identified by the provided JWT.
161
+ * Authenticates with a JWT and does not require an initialized SDK. The user id is taken
162
+ * from the `sub` claim of the JWT.
163
+ */
164
+ export var updateUserStatus = function (jwtCallback, status) {
165
+ return getJWT(jwtCallback)
166
+ .flatMap(function (jwtToken) {
167
+ var payload = {
168
+ type: "UPDATE_USER_STATUS_JWT",
169
+ message: { jwtToken: jwtToken, status: status },
170
+ };
171
+ return FrameMediator.sendMessage(payload);
172
+ })
173
+ .map(function (_a) {
174
+ var _b = _a.message, id = _b.id, segmentId = _b.segmentId, needsRotation = _b.needsRotation, status = _b.status, userMasterPublicKey = _b.userMasterPublicKey;
175
+ return ({
176
+ accountID: id,
177
+ segmentID: segmentId,
178
+ needsRotation: needsRotation,
179
+ status: status,
180
+ userMasterPublicKey: userMasterPublicKey,
181
+ });
182
+ })
183
+ .toPromise();
184
+ };
package/es/shim/index.js CHANGED
@@ -2,7 +2,8 @@ import { ErrorCodes } from "../Constants";
2
2
  import SDKError from "../lib/SDKError";
3
3
  import * as Init from "./Initialize";
4
4
  import { checkSDKInitialized } from "./ShimUtils";
5
- export { deleteDeviceByPublicSigningKey } from "./Initialize";
5
+ export { deleteDeviceByPublicSigningKey, updateUserStatus } from "./Initialize";
6
+ export { UserStatus } from "../Constants";
6
7
  /**
7
8
  * Checks bowser functionality to ensure random number generation is supported.
8
9
  */
@@ -1,3 +1,39 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (_) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
1
37
  var __read = (this && this.__read) || function (o, n) {
2
38
  var m = typeof Symbol === "function" && o[Symbol.iterator];
3
39
  if (!m) return o;
@@ -14,12 +50,21 @@ var __read = (this && this.__read) || function (o, n) {
14
50
  }
15
51
  return ar;
16
52
  };
53
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
54
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
55
+ if (ar || !(i in from)) {
56
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
57
+ ar[i] = from[i];
58
+ }
59
+ }
60
+ return to.concat(ar || Array.prototype.slice.call(from));
61
+ };
17
62
  import Future from "futurejs";
18
63
  import { ErrorCodes, HEADER_META_LENGTH_LENGTH, VERSION_HEADER_LENGTH } from "../../Constants";
19
64
  import SDKError from "../../lib/SDKError";
65
+ import { concatArrayBuffers, parseDocumentHeader } from "../../lib/Utils";
20
66
  import * as FrameMediator from "../FrameMediator";
21
67
  import * as ShimUtils from "../ShimUtils";
22
- import { utf8 } from "./CodecSDK";
23
68
  var MAX_DOCUMENT_SIZE = 1024 * 2 * 1000; //2MB
24
69
  /**
25
70
  * Takes the document encrypt options object and normalizes it to a complete object with proper default values.
@@ -83,23 +128,12 @@ export function getMetadata(documentID) {
83
128
  export function getDocumentIDFromBytes(documentData) {
84
129
  ShimUtils.checkSDKInitialized();
85
130
  ShimUtils.validateEncryptedDocument(documentData);
86
- //Version 1 document, we don't have the document ID as it's not encoded in the header
87
- if (documentData[0] === 1) {
88
- return Promise.resolve(null);
89
- }
90
- //Check to see if the document is a version we don't support and reject if so
91
- if (documentData[0] !== 2) {
92
- return Promise.reject(new SDKError(new Error("Provided encrypted document doesn't appear to be valid. Invalid version."), ErrorCodes.DOCUMENT_HEADER_PARSE_FAILURE));
93
- }
94
- var headerLength = new DataView(documentData.buffer).getUint16(documentData.byteOffset + VERSION_HEADER_LENGTH, false);
95
- var headerContent = documentData.slice(VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH, VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH + headerLength);
96
- try {
97
- var headerObject = JSON.parse(utf8.fromBytes(headerContent));
98
- return Promise.resolve(headerObject._did_);
99
- }
100
- catch (_a) {
101
- return Promise.reject(new SDKError(new Error("Unable to parse document header. Header value is corrupted."), ErrorCodes.DOCUMENT_HEADER_PARSE_FAILURE));
102
- }
131
+ return parseDocumentHeader(documentData)
132
+ .map(function (_a) {
133
+ var documentID = _a.documentID;
134
+ return documentID;
135
+ })
136
+ .toPromise();
103
137
  }
104
138
  /**
105
139
  * @deprecated Use `decrypt` instead.
@@ -354,6 +388,174 @@ export function revokeAccess(documentID, revokeList) {
354
388
  })
355
389
  .toPromise();
356
390
  }
391
+ /**
392
+ * Parse the version header, header JSON, and IV from the beginning of an encrypted ReadableStream.
393
+ * Returns the document ID, IV, and a new ReadableStream starting after the header+IV (ciphertext only).
394
+ */
395
+ function parseStreamHeader(encryptedStream) {
396
+ var _this = this;
397
+ return Future.tryP(function () { return __awaiter(_this, void 0, void 0, function () {
398
+ var reader, chunks_1, totalLen_1, readAtLeastIntoChunks, initialHeaderBytes, headerJsonLength, e_1;
399
+ var _this = this;
400
+ return __generator(this, function (_a) {
401
+ switch (_a.label) {
402
+ case 0:
403
+ reader = encryptedStream.getReader();
404
+ _a.label = 1;
405
+ case 1:
406
+ _a.trys.push([1, 7, , 8]);
407
+ chunks_1 = [];
408
+ totalLen_1 = 0;
409
+ readAtLeastIntoChunks = function (n) { return __awaiter(_this, void 0, void 0, function () {
410
+ var _a, done, value;
411
+ return __generator(this, function (_b) {
412
+ switch (_b.label) {
413
+ case 0:
414
+ if (!(totalLen_1 < n)) return [3 /*break*/, 2];
415
+ return [4 /*yield*/, reader.read()];
416
+ case 1:
417
+ _a = _b.sent(), done = _a.done, value = _a.value;
418
+ if (done)
419
+ throw new SDKError(new Error("Encrypted stream ended before header could be parsed"), ErrorCodes.DOCUMENT_HEADER_PARSE_FAILURE);
420
+ chunks_1.push(value);
421
+ totalLen_1 += value.length;
422
+ return [3 /*break*/, 0];
423
+ case 2: return [2 /*return*/];
424
+ }
425
+ });
426
+ }); };
427
+ // Need to read the header length prefix to know total size.
428
+ return [4 /*yield*/, readAtLeastIntoChunks(VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH)];
429
+ case 2:
430
+ // Need to read the header length prefix to know total size.
431
+ _a.sent();
432
+ initialHeaderBytes = concatArrayBuffers.apply(void 0, __spreadArray([], __read(chunks_1), false));
433
+ if (!(initialHeaderBytes[0] === 2)) return [3 /*break*/, 4];
434
+ headerJsonLength = new DataView(initialHeaderBytes.buffer, initialHeaderBytes.byteOffset).getUint16(VERSION_HEADER_LENGTH, false);
435
+ return [4 /*yield*/, readAtLeastIntoChunks(VERSION_HEADER_LENGTH + HEADER_META_LENGTH_LENGTH + headerJsonLength + 12)];
436
+ case 3:
437
+ _a.sent();
438
+ return [3 /*break*/, 6];
439
+ case 4: return [4 /*yield*/, readAtLeastIntoChunks(VERSION_HEADER_LENGTH + 12)];
440
+ case 5:
441
+ _a.sent();
442
+ _a.label = 6;
443
+ case 6: return [2 /*return*/, { reader: reader, buffer: concatArrayBuffers.apply(void 0, __spreadArray([], __read(chunks_1), false)) }];
444
+ case 7:
445
+ e_1 = _a.sent();
446
+ // On any error in reading header chunks we need to release the reader
447
+ reader.releaseLock();
448
+ throw e_1;
449
+ case 8: return [2 /*return*/];
450
+ }
451
+ });
452
+ }); }).flatMap(function (_a) {
453
+ var reader = _a.reader, buffer = _a.buffer;
454
+ return parseDocumentHeader(buffer)
455
+ .map(function (parsed) {
456
+ var remainder = buffer.slice(parsed.contentOffset);
457
+ // Once we've parsed the header we might have remaining bytes. If
458
+ // we do we start out the ciphertextStream by writing them and then pull
459
+ // can just pull from the reader we had previously read from.
460
+ var ciphertextStream = new ReadableStream({
461
+ start: function (controller) {
462
+ if (remainder.length > 0) {
463
+ controller.enqueue(remainder);
464
+ }
465
+ },
466
+ pull: function (controller) {
467
+ return reader.read().then(function (_a) {
468
+ var done = _a.done, value = _a.value;
469
+ done ? controller.close() : controller.enqueue(value);
470
+ });
471
+ },
472
+ cancel: function () {
473
+ return reader.cancel();
474
+ },
475
+ });
476
+ return { documentID: parsed.documentID, iv: parsed.iv, ciphertextStream: ciphertextStream };
477
+ })
478
+ .errorMap(function (e) {
479
+ // On any error in preparing the new stream we need to release the reader lock
480
+ // This is purely defensive.
481
+ reader.releaseLock();
482
+ return e;
483
+ });
484
+ });
485
+ }
486
+ /**
487
+ * Encrypt a plaintext stream. Returns a Promise which resolves with the encrypted stream and document metadata.
488
+ * The output stream produces bytes in the same format as encrypt(): [header][IV][ciphertext][auth_tag].
489
+ *
490
+ * @param {ReadableStream<Uint8Array>} plaintextStream Plaintext data as a ReadableStream
491
+ * @param {DocumentCreateOptions} options Document create options
492
+ */
493
+ export function encryptStream(plaintextStream, options) {
494
+ ShimUtils.checkSDKInitialized();
495
+ var encryptOptions = calculateDocumentCreateOptionsDefault(options);
496
+ if (encryptOptions.documentID) {
497
+ ShimUtils.validateID(encryptOptions.documentID);
498
+ }
499
+ var _a = __read(ShimUtils.dedupeAccessLists(encryptOptions.accessList), 2), userGrants = _a[0], groupGrants = _a[1];
500
+ var payload = {
501
+ type: "DOCUMENT_STREAM_ENCRYPT",
502
+ message: {
503
+ documentID: encryptOptions.documentID,
504
+ documentName: encryptOptions.documentName,
505
+ plaintextStream: plaintextStream,
506
+ userGrants: userGrants,
507
+ groupGrants: groupGrants,
508
+ grantToAuthor: encryptOptions.accessList.grantToAuthor,
509
+ policy: encryptOptions.policy,
510
+ },
511
+ };
512
+ // Cast needed because TS's Transferable type doesn't yet include ReadableStream/WritableStream
513
+ return FrameMediator.sendMessage(payload, [plaintextStream])
514
+ .map(function (_a) {
515
+ var message = _a.message;
516
+ return ({
517
+ documentID: message.documentID,
518
+ documentName: message.documentName,
519
+ encryptedStream: message.encryptedStream,
520
+ created: message.created,
521
+ updated: message.updated,
522
+ });
523
+ })
524
+ .toPromise();
525
+ }
526
+ /**
527
+ * Decrypt an encrypted document stream. Parses the header and IV from the stream, then streams decrypted
528
+ * plaintext back via the returned ReadableStream. If the auth tag fails at the end of the stream, the
529
+ * readable side errors — which propagates through pipeTo() to abort any destination WritableStream.
530
+ *
531
+ * @param {string} documentID ID of the document to decrypt
532
+ * @param {ReadableStream<Uint8Array>} encryptedStream Encrypted document as a ReadableStream (from fetch().body, file.stream(), etc.)
533
+ */
534
+ export function decryptStream(documentID, encryptedStream) {
535
+ ShimUtils.checkSDKInitialized();
536
+ ShimUtils.validateID(documentID);
537
+ return parseStreamHeader(encryptedStream)
538
+ .flatMap(function (_a) {
539
+ var iv = _a.iv, ciphertextStream = _a.ciphertextStream;
540
+ var payload = {
541
+ type: "DOCUMENT_STREAM_DECRYPT",
542
+ message: { documentID: documentID, iv: iv, encryptedStream: ciphertextStream },
543
+ };
544
+ return FrameMediator.sendMessage(payload, [ciphertextStream]).map(function (_a) {
545
+ var message = _a.message;
546
+ return ({
547
+ documentID: documentID,
548
+ documentName: message.documentName,
549
+ visibleTo: message.visibleTo,
550
+ association: message.association,
551
+ created: message.created,
552
+ updated: message.updated,
553
+ plaintextStream: message.plaintextStream,
554
+ });
555
+ });
556
+ })
557
+ .toPromise();
558
+ }
357
559
  /**
358
560
  * A collection of methods for advanced encryption/decryption use cases. Currently focused on methods which require the caller to manage the encrypted
359
561
  * DEKs.
@@ -389,6 +591,66 @@ export var advanced = {
389
591
  })
390
592
  .toPromise();
391
593
  },
594
+ /**
595
+ * Streaming decrypt with caller-provided EDEKs. Parses the header/IV from the stream, then decrypts.
596
+ * If the auth tag fails, the returned plaintextStream errors.
597
+ */
598
+ decryptStreamUnmanaged: function (encryptedStream, edeks) {
599
+ ShimUtils.checkSDKInitialized();
600
+ ShimUtils.validateEncryptedDeks(edeks);
601
+ return parseStreamHeader(encryptedStream)
602
+ .flatMap(function (_a) {
603
+ var documentID = _a.documentID, iv = _a.iv, ciphertextStream = _a.ciphertextStream;
604
+ var payload = {
605
+ type: "DOCUMENT_UNMANAGED_STREAM_DECRYPT",
606
+ message: { edeks: edeks, iv: iv, encryptedStream: ciphertextStream },
607
+ };
608
+ return FrameMediator.sendMessage(payload, [
609
+ ciphertextStream,
610
+ ]).map(function (_a) {
611
+ var message = _a.message;
612
+ return ({
613
+ documentID: documentID,
614
+ plaintextStream: message.plaintextStream,
615
+ accessVia: message.accessVia,
616
+ });
617
+ });
618
+ })
619
+ .toPromise();
620
+ },
621
+ /**
622
+ * Streaming encrypt with caller-managed EDEKs. Returns the encrypted stream and EDEKs to the caller.
623
+ * The output stream produces bytes in the same format as encrypt(): [header][IV][ciphertext][auth_tag].
624
+ */
625
+ encryptStreamUnmanaged: function (plaintextStream, options) {
626
+ ShimUtils.checkSDKInitialized();
627
+ var encryptOptions = calculateDocumentCreateOptionsDefault(options);
628
+ if (encryptOptions.documentID) {
629
+ ShimUtils.validateID(encryptOptions.documentID);
630
+ }
631
+ var _a = __read(ShimUtils.dedupeAccessLists(encryptOptions.accessList), 2), userGrants = _a[0], groupGrants = _a[1];
632
+ var payload = {
633
+ type: "DOCUMENT_UNMANAGED_STREAM_ENCRYPT",
634
+ message: {
635
+ documentID: encryptOptions.documentID,
636
+ plaintextStream: plaintextStream,
637
+ userGrants: userGrants,
638
+ groupGrants: groupGrants,
639
+ grantToAuthor: encryptOptions.accessList.grantToAuthor,
640
+ policy: encryptOptions.policy,
641
+ },
642
+ };
643
+ return FrameMediator.sendMessage(payload, [plaintextStream])
644
+ .map(function (_a) {
645
+ var message = _a.message;
646
+ return ({
647
+ documentID: message.documentID,
648
+ encryptedStream: message.encryptedStream,
649
+ edeks: message.edeks,
650
+ });
651
+ })
652
+ .toPromise();
653
+ },
392
654
  /**
393
655
  * Encrypt the provided document with various document create options. Does not store any part of the document within IronCore and instead returns
394
656
  * the encrypted DEKs to the caller. These encrypted DEKs must be then be provided as input in order to decrypt the document.
@@ -96,3 +96,34 @@ export var listDevices = function () {
96
96
  })
97
97
  .toPromise();
98
98
  };
99
+ /**
100
+ * Disables the currently authenticated user. Disabled users are unable to call any
101
+ * other authorized SDK functions but remain in any groups they belonged to. Users
102
+ * cannot re-enable themselves; an admin must call `updateUserStatus` with a JWT for
103
+ * the user to re-enable them.
104
+ */
105
+ export var disableSelf = function () {
106
+ checkSDKInitialized();
107
+ var payload = {
108
+ type: "DISABLE_USER_SELF",
109
+ message: null,
110
+ };
111
+ // The frame wipes its ApiState and device keys on a successful disable, so mirror the
112
+ // current-device path of `deleteDevice` here: drop the parent-window symmetric key now
113
+ // and clear the init flag on success. Otherwise `isInitialized()` keeps returning true
114
+ // while the frame is empty, and the next SDK call fails confusingly in the frame.
115
+ clearParentWindowSymmetricKey();
116
+ return FrameMediator.sendMessage(payload)
117
+ .map(function (_a) {
118
+ var _b = _a.message, id = _b.id, segmentId = _b.segmentId, needsRotation = _b.needsRotation, status = _b.status, userMasterPublicKey = _b.userMasterPublicKey;
119
+ clearSDKInitialized();
120
+ return {
121
+ accountID: id,
122
+ segmentID: segmentId,
123
+ needsRotation: needsRotation,
124
+ status: status,
125
+ userMasterPublicKey: userMasterPublicKey,
126
+ };
127
+ })
128
+ .toPromise();
129
+ };
package/ironweb.d.ts CHANGED
@@ -96,6 +96,22 @@ export interface DocumentAccessResponse {
96
96
  succeeded: UserOrGroup[];
97
97
  failed: (UserOrGroup & {error: string})[];
98
98
  }
99
+ export interface StreamEncryptResponse extends DocumentIDNameResponse {
100
+ encryptedStream: ReadableStream<Uint8Array>;
101
+ }
102
+ export interface StreamEncryptUnmanagedResponse {
103
+ documentID: string;
104
+ encryptedStream: ReadableStream<Uint8Array>;
105
+ edeks: Uint8Array;
106
+ }
107
+ export interface StreamDecryptResponse extends DocumentMetaResponse {
108
+ plaintextStream: ReadableStream<Uint8Array>;
109
+ }
110
+ export interface StreamDecryptUnmanagedResponse {
111
+ documentID: string;
112
+ plaintextStream: ReadableStream<Uint8Array>;
113
+ accessVia: UserOrGroup;
114
+ }
99
115
 
100
116
  /**
101
117
  * Group SDK response types
@@ -139,6 +155,18 @@ export interface UserCreateResponse {
139
155
  userMasterPublicKey: PublicKey<Base64String>;
140
156
  needsRotation: boolean;
141
157
  }
158
+ export interface UserUpdateResponse {
159
+ accountID: string;
160
+ segmentID: number;
161
+ status: UserStatus;
162
+ userMasterPublicKey: PublicKey<Base64String>;
163
+ needsRotation: boolean;
164
+ }
165
+ export const UserStatus: {
166
+ DISABLED: 0;
167
+ ENABLED: 1;
168
+ };
169
+ export type UserStatus = 0 | 1;
142
170
  export interface DeviceKeys {
143
171
  accountId: string;
144
172
  segmentId: number;
@@ -184,6 +212,7 @@ export interface User {
184
212
  listDevices(): Promise<UserDeviceListResponse>;
185
213
  changePasscode(currentPasscode: string, newPasscode: string): Promise<void>;
186
214
  rotateMasterKey(passcode: string): Promise<void>;
215
+ disableSelf(): Promise<UserUpdateResponse>;
187
216
  }
188
217
 
189
218
  export interface Document {
@@ -191,8 +220,10 @@ export interface Document {
191
220
  getMetadata(documentID: string): Promise<DocumentMetaResponse>;
192
221
  getDocumentIDFromBytes(encryptedDocument: Uint8Array): Promise<string | null>;
193
222
  decrypt(documentID: string, encryptedDocument: Uint8Array): Promise<DecryptedDocumentResponse>;
223
+ decryptStream(documentID: string, encryptedStream: ReadableStream<Uint8Array>): Promise<StreamDecryptResponse>;
194
224
  decryptFromStore(documentID: string): Promise<DecryptedDocumentResponse>;
195
225
  encrypt(documentData: Uint8Array, options?: DocumentCreateOptions): Promise<EncryptedDocumentResponse>;
226
+ encryptStream(plaintextStream: ReadableStream<Uint8Array>, options?: DocumentCreateOptions): Promise<StreamEncryptResponse>;
196
227
  encryptToStore(documentData: Uint8Array, options?: DocumentCreateOptions): Promise<DocumentIDNameResponse>;
197
228
  updateEncryptedData(documentID: string, newDocumentData: Uint8Array): Promise<EncryptedDocumentResponse>;
198
229
  updateEncryptedDataInStore(documentID: string, newDocumentData: Uint8Array): Promise<DocumentIDNameResponse>;
@@ -201,7 +232,12 @@ export interface Document {
201
232
  revokeAccess(documentID: string, revokeList: DocumentAccessList): Promise<DocumentAccessResponse>;
202
233
  advanced: {
203
234
  decryptUnmanaged(data: Uint8Array, edeks: Uint8Array): Promise<DecryptedUnmanagedDocumentResponse>;
235
+ decryptStreamUnmanaged(encryptedStream: ReadableStream<Uint8Array>, edeks: Uint8Array): Promise<StreamDecryptUnmanagedResponse>;
204
236
  encryptUnmanaged(documentData: Uint8Array, options?: Omit<DocumentCreateOptions, "documentName">): Promise<EncryptedUnmanagedDocumentResponse>;
237
+ encryptStreamUnmanaged(
238
+ plaintextStream: ReadableStream<Uint8Array>,
239
+ options?: Omit<DocumentCreateOptions, "documentName">
240
+ ): Promise<StreamEncryptUnmanagedResponse>;
205
241
  };
206
242
  }
207
243
 
@@ -283,6 +319,7 @@ export interface ErrorCodes {
283
319
  USER_DEVICE_DELETE_REQUEST_FAILURE: 210;
284
320
  USER_UPDATE_KEY_REQUEST_FAILURE: 211;
285
321
  USER_PRIVATE_KEY_ROTATION_FAILURE: 212;
322
+ USER_UPDATE_STATUS_REQUEST_FAILURE: 214;
286
323
  DOCUMENT_LIST_REQUEST_FAILURE: 300;
287
324
  DOCUMENT_GET_REQUEST_FAILURE: 301;
288
325
  DOCUMENT_CREATE_REQUEST_FAILURE: 302;
@@ -297,6 +334,8 @@ export interface ErrorCodes {
297
334
  DOCUMENT_CREATE_WITH_ACCESS_FAILURE: 311;
298
335
  DOCUMENT_HEADER_PARSE_FAILURE: 312;
299
336
  DOCUMENT_TRANSFORM_REQUEST_FAILURE: 313;
337
+ DOCUMENT_STREAM_DECRYPT_FAILURE: 314;
338
+ DOCUMENT_STREAM_ENCRYPT_FAILURE: 315;
300
339
  GROUP_LIST_REQUEST_FAILURE: 400;
301
340
  GROUP_GET_REQUEST_FAILURE: 401;
302
341
  GROUP_CREATE_REQUEST_FAILURE: 402;
@@ -335,3 +374,4 @@ export function createNewUser(jwtCallback: JWTCallback, passcode: string, option
335
374
  export function createNewDeviceKeys(jwtCallback: JWTCallback, passcode: string): Promise<DeviceKeys>;
336
375
  export function isInitialized(): boolean;
337
376
  export function deleteDeviceByPublicSigningKey(jwtCallback: JWTCallback, publicSigningKey: Base64String): Promise<number>;
377
+ export function updateUserStatus(jwtCallback: JWTCallback, status: UserStatus): Promise<UserUpdateResponse>;