@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/commonjs/Constants.js +13 -2
- package/commonjs/lib/Utils.js +40 -1
- package/commonjs/shim/FrameMediator.js +11 -7
- package/commonjs/shim/Initialize.js +28 -2
- package/commonjs/shim/index.js +6 -3
- package/commonjs/shim/sdk/DocumentSDK.js +283 -19
- package/commonjs/shim/sdk/UserSDK.js +33 -1
- package/es/Constants.js +12 -1
- package/es/lib/Utils.js +37 -0
- package/es/shim/FrameMediator.js +11 -7
- package/es/shim/Initialize.js +26 -1
- package/es/shim/index.js +2 -1
- package/es/shim/sdk/DocumentSDK.js +280 -18
- package/es/shim/sdk/UserSDK.js +31 -0
- package/ironweb.d.ts +40 -0
- package/ironweb.min.js +1 -1
- package/ironweb.min.js.map +1 -1
- package/package.json +1 -1
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
|
+
}
|
package/es/shim/FrameMediator.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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;
|
package/es/shim/Initialize.js
CHANGED
|
@@ -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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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.
|
package/es/shim/sdk/UserSDK.js
CHANGED
|
@@ -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>;
|