@lifeready/core 6.1.3 → 6.1.5

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.
Files changed (77) hide show
  1. package/bundles/lifeready-core.umd.js +303 -295
  2. package/bundles/lifeready-core.umd.js.map +1 -1
  3. package/bundles/lifeready-core.umd.min.js +1 -1
  4. package/bundles/lifeready-core.umd.min.js.map +1 -1
  5. package/esm2015/lib/auth/auth.config.js +57 -0
  6. package/esm2015/lib/auth/auth.gql.private.js +85 -0
  7. package/esm2015/lib/auth/auth.service.js +602 -0
  8. package/esm2015/lib/auth/auth.types.js +21 -0
  9. package/esm2015/lib/idle/idle.service.js +3 -3
  10. package/esm2015/lib/item/item.gql.js +164 -0
  11. package/esm2015/lib/item/item.gql.private.js +23 -0
  12. package/esm2015/lib/item/item.service.js +592 -0
  13. package/esm2015/lib/item/item.types.js +2 -0
  14. package/esm2015/lib/key-exchange/key-exchange.gql.js +174 -0
  15. package/esm2015/lib/key-exchange/key-exchange.service.js +480 -0
  16. package/esm2015/lib/lbop/lbop.service.js +7 -15
  17. package/esm2015/lib/life-ready.module.js +2 -2
  18. package/esm2015/lib/password/password.service.js +1 -1
  19. package/esm2015/lib/plan/plan.gql.js +91 -0
  20. package/esm2015/lib/plan/plan.service.js +191 -0
  21. package/esm2015/lib/plan/plan.types.js +2 -0
  22. package/esm2015/lib/profile/profile.gql.js +2 -2
  23. package/esm2015/lib/profile/profile.service.js +1 -8
  24. package/esm2015/lib/profile/profile.types.js +1 -8
  25. package/esm2015/lib/scenario/scenario.service.js +8 -8
  26. package/esm2015/lib/shared-contact-card/shared-contact-card2.service.js +1 -1
  27. package/esm2015/lib/trusted-party/trusted-party.gql.js +64 -0
  28. package/esm2015/lib/trusted-party/trusted-party.gql.private.js +25 -0
  29. package/esm2015/lib/trusted-party/trusted-party.service.js +240 -0
  30. package/esm2015/lib/trusted-party/trusted-party.types.js +2 -0
  31. package/esm2015/public-api.js +17 -12
  32. package/fesm2015/lifeready-core.js +191 -213
  33. package/fesm2015/lifeready-core.js.map +1 -1
  34. package/lib/{auth2/auth2.service.d.ts → auth/auth.service.d.ts} +2 -2
  35. package/lib/idle/idle.service.d.ts +9 -2
  36. package/lib/{item2/item2.service.d.ts → item/item.service.d.ts} +39 -39
  37. package/lib/key-exchange/{key-exchange2.service.d.ts → key-exchange.service.d.ts} +2 -2
  38. package/lib/lbop/lbop.service.d.ts +1 -5
  39. package/lib/password/password.service.d.ts +1 -1
  40. package/lib/{plan2/plan2.service.d.ts → plan/plan.service.d.ts} +20 -20
  41. package/lib/profile/profile.service.d.ts +1 -2
  42. package/lib/profile/profile.types.d.ts +2 -15
  43. package/lib/scenario/scenario.service.d.ts +3 -3
  44. package/lib/shared-contact-card/shared-contact-card2.service.d.ts +1 -1
  45. package/lib/trusted-party/{trusted-party2.service.d.ts → trusted-party.service.d.ts} +6 -6
  46. package/lifeready-core.metadata.json +1 -1
  47. package/package.json +1 -1
  48. package/public-api.d.ts +16 -11
  49. package/esm2015/lib/auth2/auth.config.js +0 -57
  50. package/esm2015/lib/auth2/auth2.gql.private.js +0 -85
  51. package/esm2015/lib/auth2/auth2.service.js +0 -602
  52. package/esm2015/lib/auth2/auth2.types.js +0 -21
  53. package/esm2015/lib/item2/item2.gql.js +0 -164
  54. package/esm2015/lib/item2/item2.gql.private.js +0 -23
  55. package/esm2015/lib/item2/item2.service.js +0 -592
  56. package/esm2015/lib/item2/item2.types.js +0 -2
  57. package/esm2015/lib/key-exchange/key-exchange2.gql.js +0 -174
  58. package/esm2015/lib/key-exchange/key-exchange2.service.js +0 -480
  59. package/esm2015/lib/plan2/plan2.gql.js +0 -91
  60. package/esm2015/lib/plan2/plan2.service.js +0 -191
  61. package/esm2015/lib/plan2/plan2.types.js +0 -2
  62. package/esm2015/lib/trusted-party/trusted-party2.gql.js +0 -64
  63. package/esm2015/lib/trusted-party/trusted-party2.gql.private.js +0 -25
  64. package/esm2015/lib/trusted-party/trusted-party2.service.js +0 -240
  65. package/esm2015/lib/trusted-party/trusted-party2.types.js +0 -2
  66. /package/lib/{auth2 → auth}/auth.config.d.ts +0 -0
  67. /package/lib/{auth2/auth2.gql.private.d.ts → auth/auth.gql.private.d.ts} +0 -0
  68. /package/lib/{auth2/auth2.types.d.ts → auth/auth.types.d.ts} +0 -0
  69. /package/lib/{item2/item2.gql.d.ts → item/item.gql.d.ts} +0 -0
  70. /package/lib/{item2/item2.gql.private.d.ts → item/item.gql.private.d.ts} +0 -0
  71. /package/lib/{item2/item2.types.d.ts → item/item.types.d.ts} +0 -0
  72. /package/lib/key-exchange/{key-exchange2.gql.d.ts → key-exchange.gql.d.ts} +0 -0
  73. /package/lib/{plan2/plan2.gql.d.ts → plan/plan.gql.d.ts} +0 -0
  74. /package/lib/{plan2/plan2.types.d.ts → plan/plan.types.d.ts} +0 -0
  75. /package/lib/trusted-party/{trusted-party2.gql.d.ts → trusted-party.gql.d.ts} +0 -0
  76. /package/lib/trusted-party/{trusted-party2.gql.private.d.ts → trusted-party.gql.private.d.ts} +0 -0
  77. /package/lib/trusted-party/{trusted-party2.types.d.ts → trusted-party.types.d.ts} +0 -0
@@ -0,0 +1,480 @@
1
+ import { __awaiter, __decorate } from "tslib";
2
+ import { Injectable, Injector, NgZone } from '@angular/core';
3
+ import { LrMutation, LrService } from '../api/lr-graphql';
4
+ import { EncryptionService, JoseSerialization, } from '../encryption/encryption.service';
5
+ import { KeyFactoryService } from '../key/key-factory.service';
6
+ import { KeyGraphService } from '../key/key-graph.service';
7
+ import { KeyService } from '../key/key.service';
8
+ import { KcCodeMismatchException } from '../_common/exceptions';
9
+ import { RunOutsideAngular } from '../_common/run-outside-angular';
10
+ import { CancelKeyExchangeMutation, CompleteKeyExchangeOtkMutation, CurrentUserSharedKeyQuery2, DeclineKeyExchangeMutation, InitiateKeyExchangeOtkMutation, KeyExchangeQuery2, KeyExchangesQuery2, KeyExchangeTokenQuery2, RespondKeyExchangeOtkMutation, } from './key-exchange.gql';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "../key/key-factory.service";
13
+ import * as i2 from "../key/key.service";
14
+ import * as i3 from "../encryption/encryption.service";
15
+ import * as i4 from "../key/key-graph.service";
16
+ let KeyExchangeService = class KeyExchangeService extends LrService {
17
+ constructor(ngZone, injector, keyFactory, keyService, encryptionService, keyGraph) {
18
+ super(injector);
19
+ this.ngZone = ngZone;
20
+ this.injector = injector;
21
+ this.keyFactory = keyFactory;
22
+ this.keyService = keyService;
23
+ this.encryptionService = encryptionService;
24
+ this.keyGraph = keyGraph;
25
+ this.CLIENT_NONCE_LENGTH = 32;
26
+ }
27
+ getOtKey(keyExchange, otKeyK) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ if (otKeyK) {
30
+ return yield KeyFactoryService.asKey(Object.assign(Object.assign({}, JSON.parse(keyExchange.otk.otKeyParams)), { k: otKeyK }));
31
+ }
32
+ else if (keyExchange.otk.state === 'OTK_INITIATED' &&
33
+ !keyExchange.isInitiator &&
34
+ keyExchange.otk.responderPbkCipher) {
35
+ // Assuming existing user getting invited where OTK is wrapped in responder's public key.
36
+ const prk = this.keyService.currentPxk;
37
+ const decryptedCipher = yield this.encryptionService.decrypt(prk.jwk, JSON.parse(keyExchange.otk.responderPbkCipher), {
38
+ serializations: [JoseSerialization.COMPACT],
39
+ });
40
+ if (decryptedCipher.otKey) {
41
+ return yield KeyFactoryService.asKey(decryptedCipher.otKey);
42
+ }
43
+ }
44
+ return null;
45
+ });
46
+ }
47
+ decryptOtk(keyExchange, otKeyK) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ const otKey = yield this.getOtKey(keyExchange, otKeyK);
50
+ let otk = keyExchange.otk;
51
+ if (otKey && otk.otKeyCipher) {
52
+ otk = Object.assign(Object.assign({}, otk), { otKey, otKeyCipherClearJson: yield this.encryptionService.decrypt(otKey, keyExchange.otk.otKeyCipher) });
53
+ }
54
+ return Object.assign(Object.assign({}, keyExchange), { otk });
55
+ });
56
+ }
57
+ decryptResponseCipher(otKey, otPrk, content) {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ // The response could be wrapped by the OtK in addition to the OtPbk
60
+ try {
61
+ content = yield this.encryptionService.decrypt(otKey, content);
62
+ }
63
+ catch (error) {
64
+ if (error.message !== 'no key found') {
65
+ throw error;
66
+ }
67
+ // Do nothing to support older versions where message is not wrapped with otk.
68
+ }
69
+ // The Prk is single-use and only used to send information from the responder back to the initiator.
70
+ return yield this.encryptionService.decrypt(otPrk, content);
71
+ });
72
+ }
73
+ decryptKeyExchangeAsInitiator(keyExchange) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const rootKey = this.keyService.currentRootKey;
76
+ // Decrypt using the root key to get the Prk
77
+ const initiatorRootKeyCipherClearJson = (yield this.encryptionService.decrypt(rootKey.jwk, keyExchange.initiatorRootKeyCipher));
78
+ const otKey = yield KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.otKey);
79
+ keyExchange = Object.assign(Object.assign({}, keyExchange), { initiatorRootKeyCipherClearJson });
80
+ let otk = keyExchange.otk;
81
+ if (otk.initiatorOneTimePbkCipher) {
82
+ otk = Object.assign(Object.assign({}, otk), { initiatorOneTimePbkCipherClearJson: yield this.decryptResponseCipher(otKey, yield KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.oneTimePrk), otk.initiatorOneTimePbkCipher) });
83
+ }
84
+ if (otk.otKeyCipher) {
85
+ otk.otKeyCipherClearJson = yield this.encryptionService.decrypt(otKey, otk.otKeyCipher);
86
+ }
87
+ return Object.assign(Object.assign({}, keyExchange), { otk });
88
+ });
89
+ }
90
+ decryptKeyExchangeAsResponder(keyExchange, otKeyK) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ return this.decryptOtk(keyExchange, otKeyK);
93
+ });
94
+ }
95
+ decryptKeyExchange(keyExchange, otKeyK) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ if (keyExchange.isInitiator) {
98
+ return this.decryptKeyExchangeAsInitiator(keyExchange);
99
+ }
100
+ else {
101
+ return this.decryptKeyExchangeAsResponder(keyExchange, otKeyK);
102
+ }
103
+ });
104
+ }
105
+ getKeyExchanges({ state } = {}) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ const { keyExchanges } = yield this.query({
108
+ query: KeyExchangesQuery2,
109
+ variables: {
110
+ state,
111
+ },
112
+ });
113
+ return Promise.all(keyExchanges.edges.map((edge) => this.decryptKeyExchange(edge.node)));
114
+ });
115
+ }
116
+ /**
117
+ * @param id If the current user can responder the key exchange if they are either the initiator or the receiver.
118
+ * @param token If not signed in, or not the initiator or responder, 'token' must be given.
119
+ * @param otKeyK Is the raw one-time key (string). If the responder is explicitly specified at time of initiation, then
120
+ * it's possible to have the otKey wrapped by the public key of the responder. In which case, the otKeyK is not needed.
121
+ */
122
+ getKeyExchange(id, { otKeyK, token } = {}) {
123
+ return __awaiter(this, void 0, void 0, function* () {
124
+ const res = yield this.query({
125
+ query: token ? KeyExchangeTokenQuery2 : KeyExchangeQuery2,
126
+ variables: {
127
+ id,
128
+ token,
129
+ },
130
+ includeKeyGraph: !token,
131
+ });
132
+ return this.decryptKeyExchange(res.keyExchange, otKeyK);
133
+ });
134
+ }
135
+ getCurrentUserSharedKey(input) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ return this.query({
138
+ query: CurrentUserSharedKeyQuery2,
139
+ variables: {
140
+ username: input.username,
141
+ userId: input.userId,
142
+ },
143
+ });
144
+ });
145
+ }
146
+ cancelKeyExchange(id) {
147
+ return this.mutate(this.cancelKeyExchangeMutation(id));
148
+ }
149
+ cancelKeyExchangeMutation(id) {
150
+ return new LrMutation({
151
+ mutation: CancelKeyExchangeMutation,
152
+ variables: {
153
+ input: {
154
+ id,
155
+ },
156
+ },
157
+ });
158
+ }
159
+ declineKeyExchange(id, token) {
160
+ return this.mutate(this.declineKeyExchangeMutation(id, token));
161
+ }
162
+ declineKeyExchangeMutation(id, token) {
163
+ return new LrMutation({
164
+ mutation: DeclineKeyExchangeMutation,
165
+ variables: {
166
+ input: {
167
+ id,
168
+ token,
169
+ },
170
+ },
171
+ });
172
+ }
173
+ initiateOtk(input = {}) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ return this.mutate((yield this.initiateOtkMutation(input)).lrMutation);
176
+ });
177
+ }
178
+ initiateOtkMutation({ message, email, contactCard, upgrade, } = {}) {
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ const otKey = yield this.keyFactory.createKey();
181
+ const nonce = this.keyFactory.randomString(this.CLIENT_NONCE_LENGTH);
182
+ // New PKC key for encryption. This key is used only once when the responder sends
183
+ // back their signing public key.
184
+ const initiatorOneTimePrk = yield this.keyFactory.createPkcKey();
185
+ // Option 1: New PKC key for signing
186
+ // const initiatorSigPrk = await this.keyService.createPkcSignKey();
187
+ // Option 2: Use the user's global signing key.
188
+ // This key is used to prove the initiator's identity.
189
+ const initiatorPrk = this.keyService.currentPxk;
190
+ const initiatorSigPrk = this.keyService.currentSigPxk;
191
+ let initiatorPlainDataSig = null;
192
+ if (contactCard && contactCard.ownerPlainDataJson) {
193
+ initiatorPlainDataSig = yield this.encryptionService.signToString(initiatorSigPrk.jwk, contactCard.ownerPlainDataJson);
194
+ }
195
+ const initiator = {
196
+ message,
197
+ contactCard: contactCard && {
198
+ sharedCipherDataClearJson: contactCard.sharedCipherDataClearJson,
199
+ },
200
+ };
201
+ // Content to be encrypted using the OTK.
202
+ const plainOtKeyCipher = {
203
+ // TODO Make sure we also put the OOB code in here as well since the OOB code is the
204
+ // _only_ information the KC server does not have access to. The server may have
205
+ // access to OTK and hence the nonce here. It's good to have both the nonce and OOB code
206
+ // since the user may not be using the OOB code. And it's simple to always include
207
+ // the nonce, so why not.
208
+ nonce,
209
+ initiator: Object.assign(Object.assign({}, initiator), { oneTimePbk: initiatorOneTimePrk.toJSON(), pbk: initiatorPrk.jwk.toJSON(), sigPbk: initiatorSigPrk.jwk.toJSON() }),
210
+ };
211
+ const otKeyCipher = yield this.keyGraph.encryptToString(otKey, plainOtKeyCipher);
212
+ // Content to be encrypted using the initiator's root key.
213
+ const initiatorRootKeyCipherClearJson = {
214
+ nonce,
215
+ oneTimePrk: initiatorOneTimePrk.toJSON(true),
216
+ // Should not need to keep this encrypted since we are using the global signing key.
217
+ // sigPrk: initiatorSigPrk.toJSON(true),
218
+ // Save it in case the initiator want to decode the otKeyCipher.
219
+ // Since the otKey is only used once, and that otKeyCipher contains only
220
+ // the public key of the initiator, it's safe just leave the otKey stored here.
221
+ otKey: otKey.toJSON(true),
222
+ // These should be storing information such as how the fields of the shared contact card is
223
+ // derived from the master contact card.
224
+ initiatorContactCard: contactCard,
225
+ initiator,
226
+ };
227
+ const rootKey = this.keyService.currentRootKey;
228
+ const initiatorRootKeyCipher = yield this.keyGraph.encryptToString(rootKey.jwk, initiatorRootKeyCipherClearJson);
229
+ // The raw OTK
230
+ const otKeyK = otKey.toJSON(true).k;
231
+ // API call
232
+ const lrMutation = new LrMutation({
233
+ mutation: InitiateKeyExchangeOtkMutation,
234
+ variables: {
235
+ input: {
236
+ // These will be stored on the server
237
+ initiatorRootKeyCipher,
238
+ initiatorPxkId: initiatorPrk.id,
239
+ initiatorSigPxkId: initiatorSigPrk.id,
240
+ // These will be sent to the responder
241
+ otKeyParams: JSON.stringify(otKey.toJSON()),
242
+ otKeyCipher,
243
+ sendEmail: email && {
244
+ email,
245
+ rawOtKey: otKeyK,
246
+ },
247
+ createTp: true,
248
+ initiatorPlainDataSig,
249
+ upgrade,
250
+ },
251
+ },
252
+ });
253
+ return { lrMutation, otKeyK };
254
+ });
255
+ }
256
+ respondOtk(input) {
257
+ return this.mutate(this.respondOtkMutation(input));
258
+ }
259
+ respondOtkMutation({ keyExchangeId, token, decryptedOtk, message, initiatorContactCard, responderContactCard, }) {
260
+ return __awaiter(this, void 0, void 0, function* () {
261
+ const rootKey = this.keyService.currentRootKey;
262
+ const masterKey = this.keyService.currentMasterKey;
263
+ const sharedKey = yield this.keyFactory.createKey();
264
+ const mkSharedKey = yield this.keyFactory.createKey();
265
+ const rkWrappedSharedKey = yield this.encryptionService.encrypt(rootKey.jwk, sharedKey.toJSON(true));
266
+ const mkWrappedMkSharedKey = yield this.encryptionService.encrypt(masterKey.jwk, mkSharedKey.toJSON(true));
267
+ const initiatorOneTimePbk = yield KeyFactoryService.asKey(decryptedOtk.otKeyCipherClearJson.initiator.oneTimePbk);
268
+ const initiatorPbk = yield KeyFactoryService.asKey(decryptedOtk.otKeyCipherClearJson.initiator.pbk);
269
+ const initiatorSigPbk = yield KeyFactoryService.asKey(decryptedOtk.otKeyCipherClearJson.initiator.sigPbk);
270
+ // Option 1: Using new Prk for each TP pair
271
+ // Create a new public signing key for the responder.
272
+ // const responderSigPrk = await this.keyService.createPkcSignKey()
273
+ // const rkWrappedResponderSigPrk = await this.encrypt(rootKey, responderSigPrk.toJSON(true));
274
+ // Option 2: Responder already has a signing Prk
275
+ const responderPrk = this.keyService.currentPxk;
276
+ const responderSigPrk = this.keyService.currentSigPxk;
277
+ const signedInitiatorPbk = yield this.encryptionService.sign(responderSigPrk.jwk, initiatorPbk.toJSON());
278
+ const signedInitiatorSigPbk = yield this.encryptionService.sign(responderSigPrk.jwk, initiatorSigPbk.toJSON());
279
+ const initiatorOneTimePbkCipherClearJson = {
280
+ nonce: decryptedOtk.otKeyCipherClearJson.nonce,
281
+ sharedKey: sharedKey.toJSON(true),
282
+ mkSharedKey: mkSharedKey.toJSON(true),
283
+ responder: {
284
+ pbk: responderPrk.jwk.toJSON(),
285
+ sigPbk: responderSigPrk.jwk.toJSON(),
286
+ message,
287
+ },
288
+ };
289
+ let receivedCardInput;
290
+ if (decryptedOtk.otKeyCipherClearJson.initiator.contactCard) {
291
+ // Set the info about the initiator to be the ones sent by the initiator. We need th responder to do the encryption here
292
+ // because the initiator does not have the shared key yet, and we want the responder to have a functional contact card after
293
+ // this exchange. The initiator can double check the contact details are correct and sign it when it completes the exchange.
294
+ const sharedCipherDataClearJson = decryptedOtk.otKeyCipherClearJson.initiator.contactCard
295
+ .sharedCipherDataClearJson;
296
+ // Create keys
297
+ const receiverKey = yield this.keyFactory.createKey();
298
+ const ccSharedKey = yield this.keyFactory.createKey();
299
+ const sigPxk = this.keyService.currentSigPxk;
300
+ receivedCardInput = {
301
+ receiverWrappedKey: JSON.stringify(yield this.encryptionService.encrypt(rootKey.jwk, receiverKey.toJSON(true))),
302
+ receiverWrappingKeyId: rootKey.id,
303
+ receiverCipherData: initiatorContactCard
304
+ ? JSON.stringify(yield this.encryptionService.encrypt(receiverKey, initiatorContactCard.receiverCipherDataClearJson))
305
+ : '',
306
+ sharedWrappedKey: JSON.stringify(yield this.encryptionService.encrypt(sharedKey, ccSharedKey.toJSON(true))),
307
+ };
308
+ const sharedCipherData = yield this.encryptionService.encrypt(ccSharedKey, sharedCipherDataClearJson);
309
+ receivedCardInput.sharedCipherDataSig = JSON.stringify(yield this.encryptionService.sign(sigPxk.jwk, sharedCipherData));
310
+ receivedCardInput.sigPxkId = sigPxk.id;
311
+ initiatorOneTimePbkCipherClearJson.responder.contactCard = Object.assign(Object.assign({}, initiatorOneTimePbkCipherClearJson.responder.contactCard), { sharedCipherKey: ccSharedKey.toJSON(true) });
312
+ }
313
+ let responderCardInput;
314
+ if (responderContactCard) {
315
+ // Create keys
316
+ const ownerKey = yield this.keyFactory.createKey();
317
+ const ccSharedKey = yield this.keyFactory.createKey();
318
+ const sigPxk = this.keyService.currentSigPxk;
319
+ responderCardInput = {
320
+ ownerWrappedKey: JSON.stringify(yield this.encryptionService.encrypt(rootKey.jwk, ownerKey.toJSON(true))),
321
+ ownerWrappingKeyId: rootKey.id,
322
+ ownerCipherData: responderContactCard.ownerCipherDataClearJson
323
+ ? JSON.stringify(yield this.encryptionService.encrypt(ownerKey, responderContactCard.ownerCipherDataClearJson))
324
+ : '',
325
+ sharedWrappedKey: JSON.stringify(yield this.encryptionService.encrypt(sharedKey, ccSharedKey.toJSON(true))),
326
+ };
327
+ const sharedCipherData = yield this.encryptionService.encrypt(ccSharedKey, responderContactCard.sharedCipherDataClearJson);
328
+ responderCardInput.sharedCipherDataSig = JSON.stringify(yield this.encryptionService.sign(sigPxk.jwk, sharedCipherData));
329
+ responderCardInput.sigPxkId = sigPxk.id;
330
+ if (responderContactCard.ownerPlainDataJson) {
331
+ responderCardInput.ownerPlainDataSig = JSON.stringify(yield this.encryptionService.sign(responderSigPrk.jwk, responderContactCard.ownerPlainDataJson));
332
+ }
333
+ // Contact card info readable by the initiator
334
+ initiatorOneTimePbkCipherClearJson.responder.contactCard = Object.assign(Object.assign({}, initiatorOneTimePbkCipherClearJson.responder.contactCard), { sharedCipherDataClearJson: responderContactCard.sharedCipherDataClearJson });
335
+ }
336
+ // Encrypt with one-time public key
337
+ let initiatorOneTimePbkCipher = yield this.encryptionService.encrypt(initiatorOneTimePbk, initiatorOneTimePbkCipherClearJson);
338
+ // Encrypt with the otk again to keep use of asymmetric keys to a minimum.
339
+ initiatorOneTimePbkCipher = yield this.encryptionService.encrypt(decryptedOtk.otKey, initiatorOneTimePbkCipher);
340
+ return new LrMutation({
341
+ mutation: RespondKeyExchangeOtkMutation,
342
+ variables: {
343
+ input: {
344
+ keyExchangeId,
345
+ keyExchangeToken: token,
346
+ rootKeyId: rootKey.id,
347
+ masterKeyId: masterKey.id,
348
+ // These will be stored on the server
349
+ responderPxkId: responderPrk.id,
350
+ responderSigPxkId: responderSigPrk.id,
351
+ signedInitiatorPbk: JSON.stringify(signedInitiatorPbk),
352
+ signedInitiatorSigPbk: JSON.stringify(signedInitiatorSigPbk),
353
+ // rkWrappedInitiatorSigPbk: JSON.stringify(rkWrappedInitiatorSigPbk),
354
+ // Option 1: Using new Prk for each TP pair
355
+ // rkWrappedResponderSigPrk: JSON.stringify(rkWrappedResponderSigPrk),
356
+ rkWrappedSharedKey: JSON.stringify(rkWrappedSharedKey),
357
+ mkWrappedMkSharedKey: JSON.stringify(mkWrappedMkSharedKey),
358
+ // These will be sent to the initiator
359
+ initiatorOneTimePbkCipher: JSON.stringify(initiatorOneTimePbkCipher),
360
+ initiatorContactCard: receivedCardInput,
361
+ responderContactCard: responderCardInput,
362
+ },
363
+ },
364
+ });
365
+ });
366
+ }
367
+ completeOtk(input) {
368
+ return this.mutate(this.completeOtkMutation(input));
369
+ }
370
+ completeOtkMutation({ keyExchangeId, initiatorRootKeyCipher, initiatorOneTimePbkCipher, responderContactCard, initiatorContactCard, }) {
371
+ return __awaiter(this, void 0, void 0, function* () {
372
+ const rootKey = this.keyService.currentRootKey;
373
+ const masterKey = this.keyService.currentMasterKey;
374
+ // Decrypt using the root key to get the Prk
375
+ const initiatorRootKeyCipherClearJson = (yield this.encryptionService.decrypt(rootKey.jwk, initiatorRootKeyCipher));
376
+ // The Prk is single-use and only used to send information from the responder back to the initiator.
377
+ const plainInitiatorOneTimePbkCipher = yield this.decryptResponseCipher(yield KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.otKey), yield KeyFactoryService.asKey(initiatorRootKeyCipherClearJson.oneTimePrk), initiatorOneTimePbkCipher);
378
+ // Check the nonce match to ensure the responder was the one holding the OTK
379
+ if (initiatorRootKeyCipherClearJson.nonce !==
380
+ plainInitiatorOneTimePbkCipher.nonce) {
381
+ throw new KcCodeMismatchException('The nonce returned by responder does not match with the one created by the initiator.');
382
+ }
383
+ // Option 1: Assuming the signing key is unique between users.
384
+ // const initiatorSigPrk = await KFS.asKey(ke.plainInitiatorRootKeyCipher.sigPrk);
385
+ // const rkWrappedInitiatorSigPrk = await this.encrypt(rootKey, initiatorSigPrk.toJSON(true));
386
+ // Option 2: Use the user's global signing key.
387
+ // In this case the initiatorSigPrk is already a part of the key graph.
388
+ // So there's nothing to do here.
389
+ // Protected the signing public key of the responder.
390
+ const initiatorSigPrk = this.keyService.currentSigPxk;
391
+ const responderSigPbk = yield KeyFactoryService.asKey(plainInitiatorOneTimePbkCipher.responder.sigPbk);
392
+ const responderPbk = yield KeyFactoryService.asKey(plainInitiatorOneTimePbkCipher.responder.pbk);
393
+ const signedResponderPbk = yield this.encryptionService.sign(initiatorSigPrk.jwk, responderPbk.toJSON());
394
+ const signedResponderSigPbk = yield this.encryptionService.sign(initiatorSigPrk.jwk, responderSigPbk.toJSON());
395
+ const sharedKey = yield KeyFactoryService.asKey(plainInitiatorOneTimePbkCipher.sharedKey);
396
+ const rkWrappedSharedKey = yield this.encryptionService.encrypt(rootKey.jwk, sharedKey.toJSON(true));
397
+ const mkSharedKey = yield KeyFactoryService.asKey(plainInitiatorOneTimePbkCipher.mkSharedKey);
398
+ const mkWrappedMkSharedKey = yield this.encryptionService.encrypt(masterKey.jwk, mkSharedKey.toJSON(true));
399
+ let responderContactCardCipherInput;
400
+ if (responderContactCard) {
401
+ // Create key
402
+ const receiverKey = yield this.keyFactory.createKey();
403
+ responderContactCardCipherInput = {
404
+ receiverWrappedKey: JSON.stringify(yield this.encryptionService.encrypt(rootKey.jwk, receiverKey.toJSON(true))),
405
+ receiverWrappingKeyId: rootKey.id,
406
+ receiverCipherData: JSON.stringify(yield this.encryptionService.encrypt(receiverKey, responderContactCard.receiverCipherDataClearJson)),
407
+ };
408
+ }
409
+ // Get the data needed from the initiator's cipher data.
410
+ let initiatorContactCardCipherInput;
411
+ let initiatorContactCardSharedCipherInput;
412
+ if (initiatorRootKeyCipherClearJson.initiatorContactCard) {
413
+ // The initiatorContactCard created during the creation of the invite and encrypted using the initiator's
414
+ // root key
415
+ const initiatorContactCardFromInit = initiatorRootKeyCipherClearJson.initiatorContactCard;
416
+ const ownerKey = yield this.keyFactory.createKey();
417
+ const sharedCipherKey = yield KeyFactoryService.asKey(plainInitiatorOneTimePbkCipher.responder.contactCard.sharedCipherKey);
418
+ const ownerWrappedKey = JSON.stringify(yield this.encryptionService.encrypt(rootKey.jwk, ownerKey.toJSON(true)));
419
+ // Allow the initiatorContactCard parameter to override
420
+ const ownerCipherDataClearJson = (initiatorContactCard === null || initiatorContactCard === void 0 ? void 0 : initiatorContactCard.ownerCipherDataClearJson) ||
421
+ initiatorContactCardFromInit.ownerCipherDataClearJson;
422
+ const ownerCipherData = ownerCipherDataClearJson
423
+ ? yield this.keyGraph.encryptToString(ownerKey, ownerCipherDataClearJson)
424
+ : '';
425
+ initiatorContactCardCipherInput = {
426
+ ownerWrappedKey,
427
+ ownerWrappingKeyId: rootKey.id,
428
+ ownerCipherData,
429
+ };
430
+ initiatorContactCardSharedCipherInput = {
431
+ sigPxkId: initiatorSigPrk.id,
432
+ };
433
+ const sharedCipherData = yield this.encryptionService.encrypt(sharedCipherKey, initiatorContactCardFromInit.sharedCipherDataClearJson);
434
+ initiatorContactCardSharedCipherInput.sharedCipherDataSig =
435
+ JSON.stringify(yield this.encryptionService.sign(initiatorSigPrk.jwk, sharedCipherData));
436
+ }
437
+ // TODO ideally we update the shared data in the contact card sent to the responder as well since that
438
+ // CC was created by the responder.
439
+ return new LrMutation({
440
+ mutation: CompleteKeyExchangeOtkMutation,
441
+ variables: {
442
+ input: {
443
+ keyExchangeId,
444
+ rootKeyId: rootKey.id,
445
+ masterKeyId: masterKey.id,
446
+ initiatorSigPxkId: initiatorSigPrk.id,
447
+ signedResponderPbk: JSON.stringify(signedResponderPbk),
448
+ signedResponderSigPbk: JSON.stringify(signedResponderSigPbk),
449
+ rkWrappedSharedKey: JSON.stringify(rkWrappedSharedKey),
450
+ mkWrappedMkSharedKey: JSON.stringify(mkWrappedMkSharedKey),
451
+ responderContactCardCipher: responderContactCardCipherInput,
452
+ initiatorContactCardCipher: initiatorContactCardCipherInput,
453
+ initiatorContactCardSharedCipher: initiatorContactCardSharedCipherInput,
454
+ },
455
+ },
456
+ });
457
+ });
458
+ }
459
+ };
460
+ KeyExchangeService.ɵprov = i0.ɵɵdefineInjectable({ factory: function KeyExchangeService_Factory() { return new KeyExchangeService(i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i0.INJECTOR), i0.ɵɵinject(i1.KeyFactoryService), i0.ɵɵinject(i2.KeyService), i0.ɵɵinject(i3.EncryptionService), i0.ɵɵinject(i4.KeyGraphService)); }, token: KeyExchangeService, providedIn: "root" });
461
+ KeyExchangeService.decorators = [
462
+ { type: Injectable, args: [{
463
+ providedIn: 'root',
464
+ },] }
465
+ ];
466
+ KeyExchangeService.ctorParameters = () => [
467
+ { type: NgZone },
468
+ { type: Injector },
469
+ { type: KeyFactoryService },
470
+ { type: KeyService },
471
+ { type: EncryptionService },
472
+ { type: KeyGraphService }
473
+ ];
474
+ KeyExchangeService = __decorate([
475
+ RunOutsideAngular({
476
+ ngZoneName: 'ngZone',
477
+ })
478
+ ], KeyExchangeService);
479
+ export { KeyExchangeService };
480
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LWV4Y2hhbmdlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb3JlL3NyYy9saWIva2V5LWV4Y2hhbmdlL2tleS1leGNoYW5nZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFN0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQU8xRCxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLGlCQUFpQixHQUNsQixNQUFNLGtDQUFrQyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbkUsT0FBTyxFQUNMLHlCQUF5QixFQUN6Qiw4QkFBOEIsRUFDOUIsMEJBQTBCLEVBQzFCLDBCQUEwQixFQUMxQiw4QkFBOEIsRUFFOUIsaUJBQWlCLEVBQ2pCLGtCQUFrQixFQUVsQixzQkFBc0IsRUFDdEIsNkJBQTZCLEdBQzlCLE1BQU0sb0JBQW9CLENBQUM7Ozs7OztJQTRIZixrQkFBa0IsU0FBbEIsa0JBQW1CLFNBQVEsU0FBUztJQUcvQyxZQUNVLE1BQWMsRUFDZCxRQUFrQixFQUNsQixVQUE2QixFQUM3QixVQUFzQixFQUN0QixpQkFBb0MsRUFDcEMsUUFBeUI7UUFFakMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBUFIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGFB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O1lBeko4QixNQUFNO1lBQWhCLFFBQVE7WUFhcEIsaUJBQWlCO1lBRWpCLFVBQVU7WUFMakIsaUJBQWlCO1lBSVYsZUFBZTs7QUE0SVgsa0JBQWtCO0lBTjlCLGlCQUFpQixDQUFDO1FBQ2pCLFVBQVUsRUFBRSxRQUFRO0tBQ3JCLENBQUM7R0FJVyxrQkFBa0IsQ0F3dUI5QjtTQXh1Qlksa0JBQWtCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSldLIH0gZnJvbSAnbm9kZS1qb3NlJztcbmltcG9ydCB7IExyTXV0YXRpb24sIExyU2VydmljZSB9IGZyb20gJy4uL2FwaS9sci1ncmFwaHFsJztcbmltcG9ydCB7XG4gIENvbnRhY3RDYXJkU2hhcmVkQ2lwaGVyRGF0YSxcbiAgSlNPTk9iamVjdCxcbiAgT3RLZXlDaXBoZXJDbGVhckpzb24yLFxufSBmcm9tICcuLi9hcGkvdHlwZXMnO1xuaW1wb3J0IHsgT3duZXJQbGFpbkRhdGFKc29uIH0gZnJvbSAnLi4vY29udGFjdC1jYXJkL2NvbnRhY3QtY2FyZDIuc2VydmljZSc7XG5pbXBvcnQge1xuICBFbmNyeXB0aW9uU2VydmljZSxcbiAgSm9zZVNlcmlhbGl6YXRpb24sXG59IGZyb20gJy4uL2VuY3J5cHRpb24vZW5jcnlwdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi4va2V5L2tleS1mYWN0b3J5LnNlcnZpY2UnO1xuaW1wb3J0IHsgS2V5R3JhcGhTZXJ2aWNlIH0gZnJvbSAnLi4va2V5L2tleS1ncmFwaC5zZXJ2aWNlJztcbmltcG9ydCB7IEtleVNlcnZpY2UgfSBmcm9tICcuLi9rZXkva2V5LnNlcnZpY2UnO1xuaW1wb3J0IHsgS2NDb2RlTWlzbWF0Y2hFeGNlcHRpb24gfSBmcm9tICcuLi9fY29tbW9uL2V4Y2VwdGlvbnMnO1xuaW1wb3J0IHsgUnVuT3V0c2lkZUFuZ3VsYXIgfSBmcm9tICcuLi9fY29tbW9uL3J1bi1vdXRzaWRlLWFuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQ2FuY2VsS2V5RXhjaGFuZ2VNdXRhdGlvbixcbiAgQ29tcGxldGVLZXlFeGNoYW5nZU90a011dGF0aW9uLFxuICBDdXJyZW50VXNlclNoYXJlZEtleVF1ZXJ5MixcbiAgRGVjbGluZUtleUV4Y2hhbmdlTXV0YXRpb24sXG4gIEluaXRpYXRlS2V5RXhjaGFuZ2VPdGtNdXRhdGlvbixcbiAgS2V5RXhjaGFuZ2VGaWVsZHNSZXN1bHQsXG4gIEtleUV4Y2hhbmdlUXVlcnkyLFxuICBLZXlFeGNoYW5nZXNRdWVyeTIsXG4gIEtleUV4Y2hhbmdlU3RhdGUyLFxuICBLZXlFeGNoYW5nZVRva2VuUXVlcnkyLFxuICBSZXNwb25kS2V5RXhjaGFuZ2VPdGtNdXRhdGlvbixcbn0gZnJvbSAnLi9rZXktZXhjaGFuZ2UuZ3FsJztcblxuLyoqXG4gKiBUaGUgZGVjcnlwdGVkIGNvbnRlbnQgb2YgdGhlIG9uZS10aW1lIGtleSBjaXBoZXI7XG4gKiBXaGVuIHVzZXIgc3VwcGxpZXMgdGhpcyBpbmZvcm1hdGlvbiB0aGUgbGliIGRvZXNuJ3QgbmVlZCB0byBkbyBhbm90aGVyIEFQSSBjYWxsXG4gKiB0byBmZXRjaCB0aGUga2V5IGV4Y2hhbmdlIG5vZGUuIEFuZCBzaW5jZSB0aGUgdHlwaWNhbCB1c2UgY2FzZSBpcyB0byBkaXNwbGF5XG4gKiBzb21lIGluZm9ybWF0aW9uIHRvIHRoZSB1c2VyLCB0aGUga2V5IGV4Y2hhbmdlIG5vZGUgd291bGQgYWxyZWFkeSBoYXZlIGJlZW5cbiAqIGZldGNoZWQgYW5kIGRlY3J5cHRlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZWNyeXB0ZWRPdGsyIHtcbiAgb3RLZXlDaXBoZXJDbGVhckpzb246IE90S2V5Q2lwaGVyQ2xlYXJKc29uMjtcbiAgb3RLZXk6IEpXSy5LZXk7IC8vIFRoZSBvbmUtdGltZSBrZXlcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250YWN0Q2FyZFJlY2VpdmVyQ2lwaGVyRGF0YSB7XG4gIC8vIFRoZSByZWNlaXZlciBvZiB0aGUgY29udGFjdCBjYXJkIGtlZXBzIGEgY29weVxuICAvLyBvZiB0aGUgb3duZXIncyBjb250YWN0IGNhcmQgaW5mb3JtYXRpb24sIGVuY3J5cHRlZCB1c2luZyB0aGUgcmVjZWl2ZXIncyBrZXlzLiBTbyB0aGF0IHdoZW5cbiAgLy8gdGhlIG93bmVyIGRlY2lkZXMgdG8gdXBkYXRlIHRoZWlyIHNoYXJlZCBjb250YWN0IGNhcmQgYXQgYSBsYXRlciBkYXRlLCB0aGUgcmVjZWl2ZXIgY2FuXG4gIC8vIGNvbXBhcmUgYWdhaW5zdCB0aGUgb3JpZ2luYWwgY29udGFjdCBjYXJkIHNlbnQgZHVyaW5nIGtleSBleGNoYW5nZS4gVGhpcyB3YXksIHRoZSBvd25lclxuICAvLyBjYW4ndCB1bmlsYXRlcmFsbHkgdXBkYXRlIHRoZWlyIHNoYXJlZCBjb250YWN0IGNhcmQgd2l0aG91dCB0aGUgcmVjZWl2ZXIga25vd2luZyBhYm91dCBpdC5cbiAgcmVjZWl2ZXJDaXBoZXJEYXRhQ2xlYXJKc29uOiBKU09OT2JqZWN0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhY3RDYXJkT3duZXJQbGFpbkRhdGEge1xuICAvLyBBY2Nlc3NpYmxlIGJ5IHRoZSBzZXJ2ZXIgYW5kIHRoZSBvd25lci4gU2VydmVyIHNpZGUgbm90aWZpY2F0aW9uIGVtYWlscyBuZWVkIHRvIGtub3cgc29tZVxuICAvLyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgb3duZXIuXG4gIC8vIFRoZSBvd25lciBjb3VsZCBlaXRoZXIgYmUgdGhlIGluaXRpYXRvciBvciB0aGUgcmVzcG9uZGVyLlxuICBvd25lclBsYWluRGF0YUpzb246IE93bmVyUGxhaW5EYXRhSnNvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250YWN0Q2FyZE93bmVyQ2lwaGVyRGF0YSB7XG4gIC8vIE93bmVyIG9ubHkgYWNjZXNzIHRvIHRoaXMgZGF0YVxuICBvd25lckNpcGhlckRhdGFDbGVhckpzb246IEpTT05PYmplY3Q7XG59XG5cbi8qKlxuICogU2VuZGluZyBjb250YWN0IGNhcmQgaW5mb3JtYXRpb24gZnJvbSB0aGUgb3duZXIgdG8gdGhlIHJlY2VpdmVyLlxuICovXG5leHBvcnQgdHlwZSBTZW5kQ29udGFjdENhcmRJbnB1dCA9IENvbnRhY3RDYXJkT3duZXJQbGFpbkRhdGEgJlxuICBDb250YWN0Q2FyZE93bmVyQ2lwaGVyRGF0YSAmXG4gIENvbnRhY3RDYXJkU2hhcmVkQ2lwaGVyRGF0YTtcblxuZXhwb3J0IGludGVyZmFjZSBJbml0aWF0ZU90a0lucHV0MiB7XG4gIC8vIE5vdGUgdGhhdCBpZiBuZWl0aGVyIGVtYWlsIG5vciByZXNwb25kZXJVc2VybmFtZSBhcmUgZ2l2ZW4sIHRoZSBvbmUtdGltZSBrZXlcbiAgLy8gY2FuIHN0aWxsIGJlIHNlbnQgdG8gdGhlIHJlc3BvbmRlciB2aWEgT09CXG4gIGVtYWlsPzogc3RyaW5nO1xuICBtZXNzYWdlPzogSlNPTk9iamVjdDtcbiAgY29udGFjdENhcmQ/OiBTZW5kQ29udGFjdENhcmRJbnB1dDtcbiAgLy8gSWYgVHJ1ZSwgdG8gdXBncmFkZSBhbiBlbWFpbCBpbnZpdGUgdG8gYW4gZXhpc3RpbmcgdXNlciBpbnZpdGUgaWYgdGhlIGVtYWlsXG4gIC8vIGlzIGFscmVhZHkgYXNzb2NpYXRlZCB3aXRoIGFuIGV4aXN0aW5nIHVzZXIuXG4gIHVwZ3JhZGU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc3BvbmRPdGtJbnB1dDIge1xuICBrZXlFeGNoYW5nZUlkOiBzdHJpbmc7XG4gIHRva2VuOiBzdHJpbmc7XG4gIGRlY3J5cHRlZE90azogRGVjcnlwdGVkT3RrMjtcbiAgbWVzc2FnZT86IEpTT05PYmplY3Q7XG4gIC8vIFRoZSBpbml0aWF0b3IgaXMgdGhlIG93bmVyIGZvIHRoZSBpbml0aWF0b3JDb250YWN0Q2FyZCwgdGhlIHJlc3BvbmRlclxuICAvLyBpcyB0aGUgcmVjZWl2ZXIuXG4gIGluaXRpYXRvckNvbnRhY3RDYXJkPzogQ29udGFjdENhcmRSZWNlaXZlckNpcGhlckRhdGE7XG4gIHJlc3BvbmRlckNvbnRhY3RDYXJkPzogU2VuZENvbnRhY3RDYXJkSW5wdXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcGxldGVPdGtJbnB1dDIge1xuICBrZXlFeGNoYW5nZUlkOiBzdHJpbmc7XG4gIC8vIFRoaXMgaXMgYSBwYXJ0IG9mIHRoZSBrZXkgZXhjaGFuZ2UgZGF0YS4gSXQncyBlbmNyeXB0ZWQgdXNpbmcgdGhlIHJvb3Qga2V5XG4gIGluaXRpYXRvclJvb3RLZXlDaXBoZXI6IHN0cmluZztcbiAgLy8gVGhpcyBpcyBhIHBhcnQgb2YgdGhlIGtleSBleGNoYW5nZSBkYXRhLiBJdCdzIGVuY3J5cHRlZCB1c2luZyB0aGUgb25lLXRpbWUga2V5LlxuICBpbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyOiBzdHJpbmc7XG4gIC8vIFRoZSByZXNwb25kZXIgaXMgdGhlIG93bmVyIGZvIHRoZSByZXNwb25kZXJDb250YWN0Q2FyZCwgdGhlIGluaXRpYXRvclxuICAvLyBpcyB0aGUgcmVjZWl2ZXIuXG4gIHJlc3BvbmRlckNvbnRhY3RDYXJkPzogQ29udGFjdENhcmRSZWNlaXZlckNpcGhlckRhdGE7XG4gIC8vIFRoZSBpbml0aWF0b3IgY2FuIHVwZGF0ZSB0aGUgY2lwaGVyIGRhdGEgdGhhdCBhcmUgb25seSB2aXNpYmxlIHRvIHRoZW0uIEl0IG1ha2VzXG4gIC8vIGxlc3Mgc2Vuc2UgdG8gdXBkYXRlIHRoZSBzaGFyZWQgZGF0YSBiZWNhdXNlIHRoZSByZXNwb25kZXIgd291bGQgaGF2ZSBhbHJlYWR5IHNlZW5cbiAgLy8gdGhlIHNoYXJlZCBkYXRhIGFuZCBhY2NlcHRlZCB0aGF0IGl0J3MgbGVnaXQuXG4gIC8vIEJ1dCBpbiBhbnkgY2FzZSwgdGhlIGluaXRpYXRvciBjYW4gdXBkYXRlIHRoZSBzaGFyZWQgY29udGFjdCBjYXJkIGluZm8gYXQgYW55IHRpbWUuXG4gIGluaXRpYXRvckNvbnRhY3RDYXJkPzogQ29udGFjdENhcmRPd25lckNpcGhlckRhdGE7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5pdGlhdG9yUm9vdEtleUNpcGhlckNsZWFySnNvbjIge1xuICBub25jZTogc3RyaW5nO1xuICBvbmVUaW1lUHJrOiBSZWNvcmQ8c3RyaW5nLCBKU09OT2JqZWN0PjsgLy8gb25lLXRpbWUgcHVibGljIGVuY3J5cHRpb24ga2V5IHJlc3BvbmRlciB1c2UgdG8gc2VuZCBkYXRhIGJhY2sgdG8gaW5pdGlhdG9yXG4gIG90S2V5OiBSZWNvcmQ8c3RyaW5nLCBKU09OT2JqZWN0PjsgLy8gb25lLXRpbWUgc3ltbWV0cmljIGtleSB0aGF0IG5lZWRzIHRvIGJlIHNoYXJlZCBPT0JcbiAgaW5pdGlhdG9yQ29udGFjdENhcmQ/OiBDb250YWN0Q2FyZE93bmVyQ2lwaGVyRGF0YSAmXG4gICAgQ29udGFjdENhcmRTaGFyZWRDaXBoZXJEYXRhO1xuICBpbml0aWF0b3I6IHtcbiAgICBtZXNzYWdlPzogSlNPTk9iamVjdDtcbiAgICBjb250YWN0Q2FyZD86IENvbnRhY3RDYXJkU2hhcmVkQ2lwaGVyRGF0YTtcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyQ2xlYXJKc29uIHtcbiAgbm9uY2U6IHN0cmluZztcbiAgc2hhcmVkS2V5OiBSZWNvcmQ8c3RyaW5nLCBKU09OT2JqZWN0PjtcbiAgbWtTaGFyZWRLZXk6IFJlY29yZDxzdHJpbmcsIEpTT05PYmplY3Q+O1xuICByZXNwb25kZXI6IHtcbiAgICBwYms6IFJlY29yZDxzdHJpbmcsIEpTT05PYmplY3Q+O1xuICAgIHNpZ1BiazogUmVjb3JkPHN0cmluZywgSlNPTk9iamVjdD47XG4gICAgbWVzc2FnZT86IEpTT05PYmplY3Q7XG4gICAgY29udGFjdENhcmQ/OiBDb250YWN0Q2FyZFNoYXJlZENpcGhlckRhdGEgJiB7XG4gICAgICAvLyBOb3RlIHRoYXQgdGhpcyBpcyBfbm90XyB0aGUgc2FtZSBrZXkgYXMgdGhlIHNoYXJlZEtleS4gVGhlIHNoYXJlZEtleSB3cmFwc1xuICAgICAgLy8gdGhpcyBrZXkgaW4gdGhlIGtleSBncmFwaC4gQnV0IGJlY2F1c2UgdGhpcyBrZXkgaGFzIG5vdCBiZWVuIGVudGVyZWQgaW50b1xuICAgICAgLy8gdGhlIGtleSBncmFwaCB3aGVuIHRoZSByZXNwb25kZXIgY2FsbHMgdGhlIEFQSSwgd2UgcGFzcyB0aGUgSldLIGRpcmVjdGx5IGhlcmUuXG4gICAgICBzaGFyZWRDaXBoZXJLZXk6IFJlY29yZDxzdHJpbmcsIEpTT05PYmplY3Q+O1xuICAgIH07XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0S2V5RXhjaGFuZ2VPcHRpb25zMiB7XG4gIC8vIFRoZSBvdEtleSBhcyBhIHJhdyBzdHJpbmcuIGkuZS4ga2V5LnRvSlNPTih0cnVlKS5rXG4gIG90S2V5Sz86IHN0cmluZztcbiAgLy8gVXNlciBuZWVkIHRoZSB0b2tlbiBpZiB0aGV5IGhhdmUgbm90IHJlc3BvbmRlZCB0byB0aGUga2V5IGV4Y2hhbmdlIHlldC5cbiAgLy8gT25jZSB0aGV5J3ZlIHJlc3BvbmRlZCAoaGVuY2UgcHJvdmVuIHRoZXkgaGF2ZSB0aGUgT09CIEtleSkgdGhleSBiZWNvbWVcbiAgLy8gdGhlIFwicmVzcG9uZGVyXCIgb2YgdGhpcyBleGNoYW5nZSwgYW5kIGNhbiBhY2Nlc3MgaXQgd2hlbiBzaWduZWQgaW4uXG4gIHRva2VuPzogc3RyaW5nO1xufVxuXG5AUnVuT3V0c2lkZUFuZ3VsYXIoe1xuICBuZ1pvbmVOYW1lOiAnbmdab25lJyxcbn0pXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgS2V5RXhjaGFuZ2VTZXJ2aWNlIGV4dGVuZHMgTHJTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBDTElFTlRfTk9OQ0VfTEVOR1RIID0gMzI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBwcml2YXRlIGtleUZhY3Rvcnk6IEtleUZhY3RvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5U2VydmljZTogS2V5U2VydmljZSxcbiAgICBwcml2YXRlIGVuY3J5cHRpb25TZXJ2aWNlOiBFbmNyeXB0aW9uU2VydmljZSxcbiAgICBwcml2YXRlIGtleUdyYXBoOiBLZXlHcmFwaFNlcnZpY2VcbiAgKSB7XG4gICAgc3VwZXIoaW5qZWN0b3IpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRPdEtleShcbiAgICBrZXlFeGNoYW5nZTogS2V5RXhjaGFuZ2VGaWVsZHNSZXN1bHQsXG4gICAgb3RLZXlLPzogc3RyaW5nXG4gICk6IFByb21pc2U8SldLLktleT4ge1xuICAgIGlmIChvdEtleUspIHtcbiAgICAgIHJldHVybiBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleSh7XG4gICAgICAgIC4uLkpTT04ucGFyc2Uoa2V5RXhjaGFuZ2Uub3RrLm90S2V5UGFyYW1zKSxcbiAgICAgICAgazogb3RLZXlLLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgIGtleUV4Y2hhbmdlLm90ay5zdGF0ZSA9PT0gJ09US19JTklUSUFURUQnICYmXG4gICAgICAha2V5RXhjaGFuZ2UuaXNJbml0aWF0b3IgJiZcbiAgICAgIGtleUV4Y2hhbmdlLm90ay5yZXNwb25kZXJQYmtDaXBoZXJcbiAgICApIHtcbiAgICAgIC8vIEFzc3VtaW5nIGV4aXN0aW5nIHVzZXIgZ2V0dGluZyBpbnZpdGVkIHdoZXJlIE9USyBpcyB3cmFwcGVkIGluIHJlc3BvbmRlcidzIHB1YmxpYyBrZXkuXG4gICAgICBjb25zdCBwcmsgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudFB4aztcbiAgICAgIGNvbnN0IGRlY3J5cHRlZENpcGhlciA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChcbiAgICAgICAgcHJrLmp3ayxcbiAgICAgICAgSlNPTi5wYXJzZShrZXlFeGNoYW5nZS5vdGsucmVzcG9uZGVyUGJrQ2lwaGVyKSxcbiAgICAgICAge1xuICAgICAgICAgIHNlcmlhbGl6YXRpb25zOiBbSm9zZVNlcmlhbGl6YXRpb24uQ09NUEFDVF0sXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICBpZiAoZGVjcnlwdGVkQ2lwaGVyLm90S2V5KSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShkZWNyeXB0ZWRDaXBoZXIub3RLZXkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVjcnlwdE90ayhcbiAgICBrZXlFeGNoYW5nZTogS2V5RXhjaGFuZ2VGaWVsZHNSZXN1bHQsXG4gICAgb3RLZXlLPzogc3RyaW5nXG4gICk6IFByb21pc2U8S2V5RXhjaGFuZ2VGaWVsZHNSZXN1bHQ+IHtcbiAgICBjb25zdCBvdEtleSA9IGF3YWl0IHRoaXMuZ2V0T3RLZXkoa2V5RXhjaGFuZ2UsIG90S2V5Syk7XG5cbiAgICBsZXQgb3RrID0ga2V5RXhjaGFuZ2Uub3RrO1xuXG4gICAgaWYgKG90S2V5ICYmIG90ay5vdEtleUNpcGhlcikge1xuICAgICAgb3RrID0ge1xuICAgICAgICAuLi5vdGssXG4gICAgICAgIG90S2V5LFxuICAgICAgICBvdEtleUNpcGhlckNsZWFySnNvbjogYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxuICAgICAgICAgIG90S2V5LFxuICAgICAgICAgIGtleUV4Y2hhbmdlLm90ay5vdEtleUNpcGhlclxuICAgICAgICApLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ua2V5RXhjaGFuZ2UsXG4gICAgICBvdGssXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVjcnlwdFJlc3BvbnNlQ2lwaGVyKFxuICAgIG90S2V5OiBKV0suS2V5LFxuICAgIG90UHJrOiBKV0suS2V5LFxuICAgIGNvbnRlbnQ6IEpTT05PYmplY3RcbiAgKTogUHJvbWlzZTxJbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyQ2xlYXJKc29uPiB7XG4gICAgLy8gVGhlIHJlc3BvbnNlIGNvdWxkIGJlIHdyYXBwZWQgYnkgdGhlIE90SyBpbiBhZGRpdGlvbiB0byB0aGUgT3RQYmtcbiAgICB0cnkge1xuICAgICAgY29udGVudCA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChvdEtleSwgY29udGVudCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvci5tZXNzYWdlICE9PSAnbm8ga2V5IGZvdW5kJykge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIC8vIERvIG5vdGhpbmcgdG8gc3VwcG9ydCBvbGRlciB2ZXJzaW9ucyB3aGVyZSBtZXNzYWdlIGlzIG5vdCB3cmFwcGVkIHdpdGggb3RrLlxuICAgIH1cblxuICAgIC8vIFRoZSBQcmsgaXMgc2luZ2xlLXVzZSBhbmQgb25seSB1c2VkIHRvIHNlbmQgaW5mb3JtYXRpb24gZnJvbSB0aGUgcmVzcG9uZGVyIGJhY2sgdG8gdGhlIGluaXRpYXRvci5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KG90UHJrLCBjb250ZW50KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVjcnlwdEtleUV4Y2hhbmdlQXNJbml0aWF0b3IoXG4gICAga2V5RXhjaGFuZ2U6IEtleUV4Y2hhbmdlRmllbGRzUmVzdWx0XG4gICk6IFByb21pc2U8S2V5RXhjaGFuZ2VGaWVsZHNSZXN1bHQ+IHtcbiAgICBjb25zdCByb290S2V5ID0gdGhpcy5rZXlTZXJ2aWNlLmN1cnJlbnRSb290S2V5O1xuXG4gICAgLy8gRGVjcnlwdCB1c2luZyB0aGUgcm9vdCBrZXkgdG8gZ2V0IHRoZSBQcmtcbiAgICBjb25zdCBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uID1cbiAgICAgIChhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICAgIHJvb3RLZXkuandrLFxuICAgICAgICBrZXlFeGNoYW5nZS5pbml0aWF0b3JSb290S2V5Q2lwaGVyXG4gICAgICApKSBhcyBJbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uMjtcblxuICAgIGNvbnN0IG90S2V5ID0gYXdhaXQgS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoXG4gICAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLm90S2V5XG4gICAgKTtcblxuICAgIGtleUV4Y2hhbmdlID0ge1xuICAgICAgLi4ua2V5RXhjaGFuZ2UsXG4gICAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLFxuICAgIH07XG5cbiAgICBsZXQgb3RrID0ga2V5RXhjaGFuZ2Uub3RrO1xuXG4gICAgaWYgKG90ay5pbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyKSB7XG4gICAgICBvdGsgPSB7XG4gICAgICAgIC4uLm90ayxcbiAgICAgICAgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvbjogYXdhaXQgdGhpcy5kZWNyeXB0UmVzcG9uc2VDaXBoZXIoXG4gICAgICAgICAgb3RLZXksXG4gICAgICAgICAgYXdhaXQgS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoXG4gICAgICAgICAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLm9uZVRpbWVQcmtcbiAgICAgICAgICApLFxuICAgICAgICAgIG90ay5pbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyXG4gICAgICAgICksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChvdGsub3RLZXlDaXBoZXIpIHtcbiAgICAgIG90ay5vdEtleUNpcGhlckNsZWFySnNvbiA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChcbiAgICAgICAgb3RLZXksXG4gICAgICAgIG90ay5vdEtleUNpcGhlclxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ua2V5RXhjaGFuZ2UsXG4gICAgICBvdGssXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZGVjcnlwdEtleUV4Y2hhbmdlQXNSZXNwb25kZXIoXG4gICAga2V5RXhjaGFuZ2U6IEtleUV4Y2hhbmdlRmllbGRzUmVzdWx0LFxuICAgIG90S2V5Sz86IHN0cmluZ1xuICApIHtcbiAgICByZXR1cm4gdGhpcy5kZWNyeXB0T3RrKGtleUV4Y2hhbmdlLCBvdEtleUspO1xuICB9XG5cbiAgYXN5bmMgZGVjcnlwdEtleUV4Y2hhbmdlKFxuICAgIGtleUV4Y2hhbmdlOiBLZXlFeGNoYW5nZUZpZWxkc1Jlc3VsdCxcbiAgICBvdEtleUs/OiBzdHJpbmdcbiAgKSB7XG4gICAgaWYgKGtleUV4Y2hhbmdlLmlzSW5pdGlhdG9yKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZWNyeXB0S2V5RXhjaGFuZ2VBc0luaXRpYXRvcihrZXlFeGNoYW5nZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmRlY3J5cHRLZXlFeGNoYW5nZUFzUmVzcG9uZGVyKGtleUV4Y2hhbmdlLCBvdEtleUspO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldEtleUV4Y2hhbmdlcyh7IHN0YXRlIH06IHsgc3RhdGU/OiBLZXlFeGNoYW5nZVN0YXRlMiB9ID0ge30pIHtcbiAgICBjb25zdCB7IGtleUV4Y2hhbmdlcyB9ID0gYXdhaXQgdGhpcy5xdWVyeSh7XG4gICAgICBxdWVyeTogS2V5RXhjaGFuZ2VzUXVlcnkyLFxuICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgIHN0YXRlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgIGtleUV4Y2hhbmdlcy5lZGdlcy5tYXAoKGVkZ2UpID0+IHRoaXMuZGVjcnlwdEtleUV4Y2hhbmdlKGVkZ2Uubm9kZSkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gaWQgSWYgdGhlIGN1cnJlbnQgdXNlciBjYW4gcmVzcG9uZGVyIHRoZSBrZXkgZXhjaGFuZ2UgaWYgdGhleSBhcmUgZWl0aGVyIHRoZSBpbml0aWF0b3Igb3IgdGhlIHJlY2VpdmVyLlxuICAgKiBAcGFyYW0gdG9rZW4gSWYgbm90IHNpZ25lZCBpbiwgb3Igbm90IHRoZSBpbml0aWF0b3Igb3IgcmVzcG9uZGVyLCAndG9rZW4nIG11c3QgYmUgZ2l2ZW4uXG4gICAqIEBwYXJhbSBvdEtleUsgSXMgdGhlIHJhdyBvbmUtdGltZSBrZXkgKHN0cmluZykuIElmIHRoZSByZXNwb25kZXIgaXMgZXhwbGljaXRseSBzcGVjaWZpZWQgYXQgdGltZSBvZiBpbml0aWF0aW9uLCB0aGVuXG4gICAqICAgaXQncyBwb3NzaWJsZSB0byBoYXZlIHRoZSBvdEtleSB3cmFwcGVkIGJ5IHRoZSBwdWJsaWMga2V5IG9mIHRoZSByZXNwb25kZXIuIEluIHdoaWNoIGNhc2UsIHRoZSBvdEtleUsgaXMgbm90IG5lZWRlZC5cbiAgICovXG4gIGFzeW5jIGdldEtleUV4Y2hhbmdlKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgeyBvdEtleUssIHRva2VuIH06IEdldEtleUV4Y2hhbmdlT3B0aW9uczIgPSB7fVxuICApIHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLnF1ZXJ5KHtcbiAgICAgIHF1ZXJ5OiB0b2tlbiA/IEtleUV4Y2hhbmdlVG9rZW5RdWVyeTIgOiBLZXlFeGNoYW5nZVF1ZXJ5MixcbiAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICBpZCxcbiAgICAgICAgdG9rZW4sXG4gICAgICB9LFxuICAgICAgaW5jbHVkZUtleUdyYXBoOiAhdG9rZW4sIC8vIGlmICF0b2tlbiB0aGVuIHdlIGFyZSBwb3N0IGF1dGgsIHNvIGNhbiBmZXRjaCBrZXlHcmFwaFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLmRlY3J5cHRLZXlFeGNoYW5nZShyZXMua2V5RXhjaGFuZ2UsIG90S2V5Syk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0Q3VycmVudFVzZXJTaGFyZWRLZXkoaW5wdXQ6IHtcbiAgICB1c2VybmFtZT86IHN0cmluZztcbiAgICB1c2VySWQ/OiBzdHJpbmc7XG4gIH0pIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeSh7XG4gICAgICBxdWVyeTogQ3VycmVudFVzZXJTaGFyZWRLZXlRdWVyeTIsXG4gICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgdXNlcm5hbWU6IGlucHV0LnVzZXJuYW1lLFxuICAgICAgICB1c2VySWQ6IGlucHV0LnVzZXJJZCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBjYW5jZWxLZXlFeGNoYW5nZShpZDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMubXV0YXRlKHRoaXMuY2FuY2VsS2V5RXhjaGFuZ2VNdXRhdGlvbihpZCkpO1xuICB9XG5cbiAgY2FuY2VsS2V5RXhjaGFuZ2VNdXRhdGlvbihpZDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBMck11dGF0aW9uKHtcbiAgICAgIG11dGF0aW9uOiBDYW5jZWxLZXlFeGNoYW5nZU11dGF0aW9uLFxuICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgIGlucHV0OiB7XG4gICAgICAgICAgaWQsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgZGVjbGluZUtleUV4Y2hhbmdlKGlkOiBzdHJpbmcsIHRva2VuOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5tdXRhdGUodGhpcy5kZWNsaW5lS2V5RXhjaGFuZ2VNdXRhdGlvbihpZCwgdG9rZW4pKTtcbiAgfVxuXG4gIGRlY2xpbmVLZXlFeGNoYW5nZU11dGF0aW9uKGlkOiBzdHJpbmcsIHRva2VuOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IExyTXV0YXRpb24oe1xuICAgICAgbXV0YXRpb246IERlY2xpbmVLZXlFeGNoYW5nZU11dGF0aW9uLFxuICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgIGlucHV0OiB7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgdG9rZW4sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgaW5pdGlhdGVPdGsoaW5wdXQ6IEluaXRpYXRlT3RrSW5wdXQyID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5tdXRhdGUoKGF3YWl0IHRoaXMuaW5pdGlhdGVPdGtNdXRhdGlvbihpbnB1dCkpLmxyTXV0YXRpb24pO1xuICB9XG5cbiAgYXN5bmMgaW5pdGlhdGVPdGtNdXRhdGlvbih7XG4gICAgbWVzc2FnZSxcbiAgICBlbWFpbCxcbiAgICBjb250YWN0Q2FyZCxcbiAgICB1cGdyYWRlLFxuICB9OiBJbml0aWF0ZU90a0lucHV0MiA9IHt9KSB7XG4gICAgY29uc3Qgb3RLZXkgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlS2V5KCk7XG4gICAgY29uc3Qgbm9uY2UgPSB0aGlzLmtleUZhY3RvcnkucmFuZG9tU3RyaW5nKHRoaXMuQ0xJRU5UX05PTkNFX0xFTkdUSCk7XG5cbiAgICAvLyBOZXcgUEtDIGtleSBmb3IgZW5jcnlwdGlvbi4gVGhpcyBrZXkgaXMgdXNlZCBvbmx5IG9uY2Ugd2hlbiB0aGUgcmVzcG9uZGVyIHNlbmRzXG4gICAgLy8gYmFjayB0aGVpciBzaWduaW5nIHB1YmxpYyBrZXkuXG4gICAgY29uc3QgaW5pdGlhdG9yT25lVGltZVByayA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVQa2NLZXkoKTtcblxuICAgIC8vIE9wdGlvbiAxOiBOZXcgUEtDIGtleSBmb3Igc2lnbmluZ1xuICAgIC8vIGNvbnN0IGluaXRpYXRvclNpZ1ByayA9IGF3YWl0IHRoaXMua2V5U2VydmljZS5jcmVhdGVQa2NTaWduS2V5KCk7XG5cbiAgICAvLyBPcHRpb24gMjogVXNlIHRoZSB1c2VyJ3MgZ2xvYmFsIHNpZ25pbmcga2V5LlxuICAgIC8vIFRoaXMga2V5IGlzIHVzZWQgdG8gcHJvdmUgdGhlIGluaXRpYXRvcidzIGlkZW50aXR5LlxuICAgIGNvbnN0IGluaXRpYXRvclByayA9IHRoaXMua2V5U2VydmljZS5jdXJyZW50UHhrO1xuICAgIGNvbnN0IGluaXRpYXRvclNpZ1ByayA9IHRoaXMua2V5U2VydmljZS5jdXJyZW50U2lnUHhrO1xuXG4gICAgbGV0IGluaXRpYXRvclBsYWluRGF0YVNpZzogc3RyaW5nID0gbnVsbDtcblxuICAgIGlmIChjb250YWN0Q2FyZCAmJiBjb250YWN0Q2FyZC5vd25lclBsYWluRGF0YUpzb24pIHtcbiAgICAgIGluaXRpYXRvclBsYWluRGF0YVNpZyA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnblRvU3RyaW5nKFxuICAgICAgICBpbml0aWF0b3JTaWdQcmsuandrLFxuICAgICAgICBjb250YWN0Q2FyZC5vd25lclBsYWluRGF0YUpzb25cbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgaW5pdGlhdG9yID0ge1xuICAgICAgbWVzc2FnZSxcbiAgICAgIGNvbnRhY3RDYXJkOiBjb250YWN0Q2FyZCAmJiB7XG4gICAgICAgIHNoYXJlZENpcGhlckRhdGFDbGVhckpzb246IGNvbnRhY3RDYXJkLnNoYXJlZENpcGhlckRhdGFDbGVhckpzb24sXG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBDb250ZW50IHRvIGJlIGVuY3J5cHRlZCB1c2luZyB0aGUgT1RLLlxuICAgIGNvbnN0IHBsYWluT3RLZXlDaXBoZXI6IE90S2V5Q2lwaGVyQ2xlYXJKc29uMiA9IHtcbiAgICAgIC8vIFRPRE8gTWFrZSBzdXJlIHdlIGFsc28gcHV0IHRoZSBPT0IgY29kZSBpbiBoZXJlIGFzIHdlbGwgc2luY2UgdGhlIE9PQiBjb2RlIGlzIHRoZVxuICAgICAgLy8gX29ubHlfIGluZm9ybWF0aW9uIHRoZSBLQyBzZXJ2ZXIgZG9lcyBub3QgaGF2ZSBhY2Nlc3MgdG8uIFRoZSBzZXJ2ZXIgbWF5IGhhdmVcbiAgICAgIC8vIGFjY2VzcyB0byBPVEsgYW5kIGhlbmNlIHRoZSBub25jZSBoZXJlLiBJdCdzIGdvb2QgdG8gaGF2ZSBib3RoIHRoZSBub25jZSBhbmQgT09CIGNvZGVcbiAgICAgIC8vIHNpbmNlIHRoZSB1c2VyIG1heSBub3QgYmUgdXNpbmcgdGhlIE9PQiBjb2RlLiBBbmQgaXQncyBzaW1wbGUgdG8gYWx3YXlzIGluY2x1ZGVcbiAgICAgIC8vIHRoZSBub25jZSwgc28gd2h5IG5vdC5cbiAgICAgIG5vbmNlLFxuICAgICAgaW5pdGlhdG9yOiB7XG4gICAgICAgIC4uLmluaXRpYXRvcixcbiAgICAgICAgb25lVGltZVBiazogaW5pdGlhdG9yT25lVGltZVByay50b0pTT04oKSwgLy8gb25lLXRpbWUgcHVibGljIGVuY3J5cHRpb24ga2V5IHJlc3BvbmRlciB1c2UgdG8gc2VuZCBkYXRhIGJhY2sgdG8gaW5pdGlhdG9yXG4gICAgICAgIHBiazogaW5pdGlhdG9yUHJrLmp3ay50b0pTT04oKSwgLy8gcHVibGljIGVuY3J5cHRpb24ga2V5XG4gICAgICAgIHNpZ1BiazogaW5pdGlhdG9yU2lnUHJrLmp3ay50b0pTT04oKSwgLy8gcHVibGljIHNpZ25pbmcga2V5XG4gICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCBvdEtleUNpcGhlciA9IGF3YWl0IHRoaXMua2V5R3JhcGguZW5jcnlwdFRvU3RyaW5nKFxuICAgICAgb3RLZXksXG4gICAgICBwbGFpbk90S2V5Q2lwaGVyXG4gICAgKTtcblxuICAgIC8vIENvbnRlbnQgdG8gYmUgZW5jcnlwdGVkIHVzaW5nIHRoZSBpbml0aWF0b3IncyByb290IGtleS5cbiAgICBjb25zdCBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uOiBJbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uMiA9IHtcbiAgICAgIG5vbmNlLFxuICAgICAgb25lVGltZVByazogaW5pdGlhdG9yT25lVGltZVByay50b0pTT04odHJ1ZSksXG4gICAgICAvLyBTaG91bGQgbm90IG5lZWQgdG8ga2VlcCB0aGlzIGVuY3J5cHRlZCBzaW5jZSB3ZSBhcmUgdXNpbmcgdGhlIGdsb2JhbCBzaWduaW5nIGtleS5cbiAgICAgIC8vIHNpZ1ByazogaW5pdGlhdG9yU2lnUHJrLnRvSlNPTih0cnVlKSxcblxuICAgICAgLy8gU2F2ZSBpdCBpbiBjYXNlIHRoZSBpbml0aWF0b3Igd2FudCB0byBkZWNvZGUgdGhlIG90S2V5Q2lwaGVyLlxuICAgICAgLy8gU2luY2UgdGhlIG90S2V5IGlzIG9ubHkgdXNlZCBvbmNlLCBhbmQgdGhhdCBvdEtleUNpcGhlciBjb250YWlucyBvbmx5XG4gICAgICAvLyB0aGUgcHVibGljIGtleSBvZiB0aGUgaW5pdGlhdG9yLCBpdCdzIHNhZmUganVzdCBsZWF2ZSB0aGUgb3RLZXkgc3RvcmVkIGhlcmUuXG4gICAgICBvdEtleTogb3RLZXkudG9KU09OKHRydWUpLFxuICAgICAgLy8gVGhlc2Ugc2hvdWxkIGJlIHN0b3JpbmcgaW5mb3JtYXRpb24gc3VjaCBhcyBob3cgdGhlIGZpZWxkcyBvZiB0aGUgc2hhcmVkIGNvbnRhY3QgY2FyZCBpc1xuICAgICAgLy8gZGVyaXZlZCBmcm9tIHRoZSBtYXN0ZXIgY29udGFjdCBjYXJkLlxuICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmQ6IGNvbnRhY3RDYXJkLFxuICAgICAgaW5pdGlhdG9yLFxuICAgIH07XG5cbiAgICBjb25zdCByb290S2V5ID0gdGhpcy5rZXlTZXJ2aWNlLmN1cnJlbnRSb290S2V5O1xuICAgIGNvbnN0IGluaXRpYXRvclJvb3RLZXlDaXBoZXIgPSBhd2FpdCB0aGlzLmtleUdyYXBoLmVuY3J5cHRUb1N0cmluZyhcbiAgICAgIHJvb3RLZXkuandrLFxuICAgICAgaW5pdGlhdG9yUm9vdEtleUNpcGhlckNsZWFySnNvblxuICAgICk7XG5cbiAgICAvLyBUaGUgcmF3IE9US1xuICAgIGNvbnN0IG90S2V5Szogc3RyaW5nID0gKG90S2V5LnRvSlNPTih0cnVlKSBhcyBKU09OT2JqZWN0KS5rO1xuXG4gICAgLy8gQVBJIGNhbGxcbiAgICBjb25zdCBsck11dGF0aW9uID0gbmV3IExyTXV0YXRpb24oe1xuICAgICAgbXV0YXRpb246IEluaXRpYXRlS2V5RXhjaGFuZ2VPdGtNdXRhdGlvbixcbiAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICBpbnB1dDoge1xuICAgICAgICAgIC8vIFRoZXNlIHdpbGwgYmUgc3RvcmVkIG9uIHRoZSBzZXJ2ZXJcbiAgICAgICAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyLFxuICAgICAgICAgIGluaXRpYXRvclB4a0lkOiBpbml0aWF0b3JQcmsuaWQsXG4gICAgICAgICAgaW5pdGlhdG9yU2lnUHhrSWQ6IGluaXRpYXRvclNpZ1Byay5pZCxcbiAgICAgICAgICAvLyBUaGVzZSB3aWxsIGJlIHNlbnQgdG8gdGhlIHJlc3BvbmRlclxuICAgICAgICAgIG90S2V5UGFyYW1zOiBKU09OLnN0cmluZ2lmeShvdEtleS50b0pTT04oKSksXG4gICAgICAgICAgb3RLZXlDaXBoZXIsXG4gICAgICAgICAgc2VuZEVtYWlsOiBlbWFpbCAmJiB7XG4gICAgICAgICAgICBlbWFpbCxcbiAgICAgICAgICAgIHJhd090S2V5OiBvdEtleUssXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjcmVhdGVUcDogdHJ1ZSxcbiAgICAgICAgICBpbml0aWF0b3JQbGFpbkRhdGFTaWcsXG4gICAgICAgICAgdXBncmFkZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyBsck11dGF0aW9uLCBvdEtleUsgfTtcbiAgfVxuXG4gIHJlc3BvbmRPdGsoaW5wdXQ6IFJlc3BvbmRPdGtJbnB1dDIpIHtcbiAgICByZXR1cm4gdGhpcy5tdXRhdGUodGhpcy5yZXNwb25kT3RrTXV0YXRpb24oaW5wdXQpKTtcbiAgfVxuXG4gIGFzeW5jIHJlc3BvbmRPdGtNdXRhdGlvbih7XG4gICAga2V5RXhjaGFuZ2VJZCxcbiAgICB0b2tlbixcbiAgICBkZWNyeXB0ZWRPdGssXG4gICAgbWVzc2FnZSxcbiAgICBpbml0aWF0b3JDb250YWN0Q2FyZCxcbiAgICByZXNwb25kZXJDb250YWN0Q2FyZCxcbiAgfTogUmVzcG9uZE90a0lucHV0Mikge1xuICAgIGNvbnN0IHJvb3RLZXkgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudFJvb3RLZXk7XG5cbiAgICBjb25zdCBtYXN0ZXJLZXkgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudE1hc3RlcktleTtcblxuICAgIGNvbnN0IHNoYXJlZEtleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcbiAgICBjb25zdCBta1NoYXJlZEtleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcblxuICAgIGNvbnN0IHJrV3JhcHBlZFNoYXJlZEtleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgIHJvb3RLZXkuandrLFxuICAgICAgc2hhcmVkS2V5LnRvSlNPTih0cnVlKVxuICAgICk7XG4gICAgY29uc3QgbWtXcmFwcGVkTWtTaGFyZWRLZXkgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICBtYXN0ZXJLZXkuandrLFxuICAgICAgbWtTaGFyZWRLZXkudG9KU09OKHRydWUpXG4gICAgKTtcblxuICAgIGNvbnN0IGluaXRpYXRvck9uZVRpbWVQYmsgPSBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShcbiAgICAgIGRlY3J5cHRlZE90ay5vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3Iub25lVGltZVBia1xuICAgICk7XG5cbiAgICBjb25zdCBpbml0aWF0b3JQYmsgPSBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShcbiAgICAgIGRlY3J5cHRlZE90ay5vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3IucGJrXG4gICAgKTtcbiAgICBjb25zdCBpbml0aWF0b3JTaWdQYmsgPSBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShcbiAgICAgIGRlY3J5cHRlZE90ay5vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3Iuc2lnUGJrXG4gICAgKTtcblxuICAgIC8vIE9wdGlvbiAxOiBVc2luZyBuZXcgUHJrIGZvciBlYWNoIFRQIHBhaXJcbiAgICAvLyBDcmVhdGUgYSBuZXcgcHVibGljIHNpZ25pbmcga2V5IGZvciB0aGUgcmVzcG9uZGVyLlxuICAgIC8vIGNvbnN0IHJlc3BvbmRlclNpZ1ByayA9IGF3YWl0IHRoaXMua2V5U2VydmljZS5jcmVhdGVQa2NTaWduS2V5KClcbiAgICAvLyBjb25zdCBya1dyYXBwZWRSZXNwb25kZXJTaWdQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHQocm9vdEtleSwgcmVzcG9uZGVyU2lnUHJrLnRvSlNPTih0cnVlKSk7XG5cbiAgICAvLyBPcHRpb24gMjogUmVzcG9uZGVyIGFscmVhZHkgaGFzIGEgc2lnbmluZyBQcmtcbiAgICBjb25zdCByZXNwb25kZXJQcmsgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudFB4aztcbiAgICBjb25zdCByZXNwb25kZXJTaWdQcmsgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudFNpZ1B4aztcblxuICAgIGNvbnN0IHNpZ25lZEluaXRpYXRvclBiayA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnbihcbiAgICAgIHJlc3BvbmRlclNpZ1Byay5qd2ssXG4gICAgICBpbml0aWF0b3JQYmsudG9KU09OKClcbiAgICApO1xuICAgIGNvbnN0IHNpZ25lZEluaXRpYXRvclNpZ1BiayA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnbihcbiAgICAgIHJlc3BvbmRlclNpZ1Byay5qd2ssXG4gICAgICBpbml0aWF0b3JTaWdQYmsudG9KU09OKClcbiAgICApO1xuXG4gICAgY29uc3QgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvbjogSW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvbiA9XG4gICAgICB7XG4gICAgICAgIG5vbmNlOiBkZWNyeXB0ZWRPdGsub3RLZXlDaXBoZXJDbGVhckpzb24ubm9uY2UsXG4gICAgICAgIHNoYXJlZEtleTogc2hhcmVkS2V5LnRvSlNPTih0cnVlKSxcbiAgICAgICAgbWtTaGFyZWRLZXk6IG1rU2hhcmVkS2V5LnRvSlNPTih0cnVlKSxcbiAgICAgICAgcmVzcG9uZGVyOiB7XG4gICAgICAgICAgcGJrOiByZXNwb25kZXJQcmsuandrLnRvSlNPTigpLCAvLyBwdWJsaWMga2V5XG4gICAgICAgICAgc2lnUGJrOiByZXNwb25kZXJTaWdQcmsuandrLnRvSlNPTigpLCAvLyBwdWJsaWMga2V5XG4gICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICBsZXQgcmVjZWl2ZWRDYXJkSW5wdXQ7XG4gICAgaWYgKGRlY3J5cHRlZE90ay5vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3IuY29udGFjdENhcmQpIHtcbiAgICAgIC8vIFNldCB0aGUgaW5mbyBhYm91dCB0aGUgaW5pdGlhdG9yIHRvIGJlIHRoZSBvbmVzIHNlbnQgYnkgdGhlIGluaXRpYXRvci4gV2UgbmVlZCB0aCByZXNwb25kZXIgdG8gZG8gdGhlIGVuY3J5cHRpb24gaGVyZVxuICAgICAgLy8gYmVjYXVzZSB0aGUgaW5pdGlhdG9yIGRvZXMgbm90IGhhdmUgdGhlIHNoYXJlZCBrZXkgeWV0LCBhbmQgd2Ugd2FudCB0aGUgcmVzcG9uZGVyIHRvIGhhdmUgYSBmdW5jdGlvbmFsIGNvbnRhY3QgY2FyZCBhZnRlclxuICAgICAgLy8gdGhpcyBleGNoYW5nZS4gVGhlIGluaXRpYXRvciBjYW4gZG91YmxlIGNoZWNrIHRoZSBjb250YWN0IGRldGFpbHMgYXJlIGNvcnJlY3QgYW5kIHNpZ24gaXQgd2hlbiBpdCBjb21wbGV0ZXMgdGhlIGV4Y2hhbmdlLlxuICAgICAgY29uc3Qgc2hhcmVkQ2lwaGVyRGF0YUNsZWFySnNvbiA9XG4gICAgICAgIGRlY3J5cHRlZE90ay5vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3IuY29udGFjdENhcmRcbiAgICAgICAgICAuc2hhcmVkQ2lwaGVyRGF0YUNsZWFySnNvbjtcblxuICAgICAgLy8gQ3JlYXRlIGtleXNcbiAgICAgIGNvbnN0IHJlY2VpdmVyS2V5ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZUtleSgpO1xuICAgICAgY29uc3QgY2NTaGFyZWRLZXkgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlS2V5KCk7XG4gICAgICBjb25zdCBzaWdQeGsgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudFNpZ1B4aztcblxuICAgICAgcmVjZWl2ZWRDYXJkSW5wdXQgPSB7XG4gICAgICAgIHJlY2VpdmVyV3JhcHBlZEtleTogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFxuICAgICAgICAgICAgcm9vdEtleS5qd2ssXG4gICAgICAgICAgICByZWNlaXZlcktleS50b0pTT04odHJ1ZSlcbiAgICAgICAgICApXG4gICAgICAgICksXG4gICAgICAgIHJlY2VpdmVyV3JhcHBpbmdLZXlJZDogcm9vdEtleS5pZCxcbiAgICAgICAgcmVjZWl2ZXJDaXBoZXJEYXRhOiBpbml0aWF0b3JDb250YWN0Q2FyZFxuICAgICAgICAgID8gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgICAgICAgICAgICByZWNlaXZlcktleSxcbiAgICAgICAgICAgICAgICBpbml0aWF0b3JDb250YWN0Q2FyZC5yZWNlaXZlckNpcGhlckRhdGFDbGVhckpzb25cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogJycsXG4gICAgICAgIHNoYXJlZFdyYXBwZWRLZXk6IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgICAgICAgIHNoYXJlZEtleSxcbiAgICAgICAgICAgIGNjU2hhcmVkS2V5LnRvSlNPTih0cnVlKVxuICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNoYXJlZENpcGhlckRhdGEgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICAgIGNjU2hhcmVkS2V5LFxuICAgICAgICBzaGFyZWRDaXBoZXJEYXRhQ2xlYXJKc29uXG4gICAgICApO1xuICAgICAgcmVjZWl2ZWRDYXJkSW5wdXQuc2hhcmVkQ2lwaGVyRGF0YVNpZyA9IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLnNpZ24oc2lnUHhrLmp3aywgc2hhcmVkQ2lwaGVyRGF0YSlcbiAgICAgICk7XG4gICAgICByZWNlaXZlZENhcmRJbnB1dC5zaWdQeGtJZCA9IHNpZ1B4ay5pZDtcblxuICAgICAgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvbi5yZXNwb25kZXIuY29udGFjdENhcmQgPSB7XG4gICAgICAgIC4uLmluaXRpYXRvck9uZVRpbWVQYmtDaXBoZXJDbGVhckpzb24ucmVzcG9uZGVyLmNvbnRhY3RDYXJkLFxuICAgICAgICBzaGFyZWRDaXBoZXJLZXk6IGNjU2hhcmVkS2V5LnRvSlNPTih0cnVlKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgbGV0IHJlc3BvbmRlckNhcmRJbnB1dDtcbiAgICBpZiAocmVzcG9uZGVyQ29udGFjdENhcmQpIHtcbiAgICAgIC8vIENyZWF0ZSBrZXlzXG4gICAgICBjb25zdCBvd25lcktleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcbiAgICAgIGNvbnN0IGNjU2hhcmVkS2V5ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZUtleSgpO1xuICAgICAgY29uc3Qgc2lnUHhrID0gdGhpcy5rZXlTZXJ2aWNlLmN1cnJlbnRTaWdQeGs7XG5cbiAgICAgIHJlc3BvbmRlckNhcmRJbnB1dCA9IHtcbiAgICAgICAgb3duZXJXcmFwcGVkS2V5OiBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICAgICAgICByb290S2V5Lmp3ayxcbiAgICAgICAgICAgIG93bmVyS2V5LnRvSlNPTih0cnVlKVxuICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgICAgb3duZXJXcmFwcGluZ0tleUlkOiByb290S2V5LmlkLFxuICAgICAgICBvd25lckNpcGhlckRhdGE6IHJlc3BvbmRlckNvbnRhY3RDYXJkLm93bmVyQ2lwaGVyRGF0YUNsZWFySnNvblxuICAgICAgICAgID8gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgICAgICAgICAgICBvd25lcktleSxcbiAgICAgICAgICAgICAgICByZXNwb25kZXJDb250YWN0Q2FyZC5vd25lckNpcGhlckRhdGFDbGVhckpzb25cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogJycsXG5cbiAgICAgICAgc2hhcmVkV3JhcHBlZEtleTogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFxuICAgICAgICAgICAgc2hhcmVkS2V5LFxuICAgICAgICAgICAgY2NTaGFyZWRLZXkudG9KU09OKHRydWUpXG4gICAgICAgICAgKVxuICAgICAgICApLFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2hhcmVkQ2lwaGVyRGF0YSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgICAgY2NTaGFyZWRLZXksXG4gICAgICAgIHJlc3BvbmRlckNvbnRhY3RDYXJkLnNoYXJlZENpcGhlckRhdGFDbGVhckpzb25cbiAgICAgICk7XG4gICAgICByZXNwb25kZXJDYXJkSW5wdXQuc2hhcmVkQ2lwaGVyRGF0YVNpZyA9IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLnNpZ24oc2lnUHhrLmp3aywgc2hhcmVkQ2lwaGVyRGF0YSlcbiAgICAgICk7XG4gICAgICByZXNwb25kZXJDYXJkSW5wdXQuc2lnUHhrSWQgPSBzaWdQeGsuaWQ7XG5cbiAgICAgIGlmIChyZXNwb25kZXJDb250YWN0Q2FyZC5vd25lclBsYWluRGF0YUpzb24pIHtcbiAgICAgICAgcmVzcG9uZGVyQ2FyZElucHV0Lm93bmVyUGxhaW5EYXRhU2lnID0gSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgICAgICAgcmVzcG9uZGVyU2lnUHJrLmp3ayxcbiAgICAgICAgICAgIHJlc3BvbmRlckNvbnRhY3RDYXJkLm93bmVyUGxhaW5EYXRhSnNvblxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ29udGFjdCBjYXJkIGluZm8gcmVhZGFibGUgYnkgdGhlIGluaXRpYXRvclxuICAgICAgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvbi5yZXNwb25kZXIuY29udGFjdENhcmQgPSB7XG4gICAgICAgIC4uLmluaXRpYXRvck9uZVRpbWVQYmtDaXBoZXJDbGVhckpzb24ucmVzcG9uZGVyLmNvbnRhY3RDYXJkLFxuICAgICAgICBzaGFyZWRDaXBoZXJEYXRhQ2xlYXJKc29uOlxuICAgICAgICAgIHJlc3BvbmRlckNvbnRhY3RDYXJkLnNoYXJlZENpcGhlckRhdGFDbGVhckpzb24sXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEVuY3J5cHQgd2l0aCBvbmUtdGltZSBwdWJsaWMga2V5XG4gICAgbGV0IGluaXRpYXRvck9uZVRpbWVQYmtDaXBoZXIgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICBpbml0aWF0b3JPbmVUaW1lUGJrLFxuICAgICAgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlckNsZWFySnNvblxuICAgICk7XG5cbiAgICAvLyBFbmNyeXB0IHdpdGggdGhlIG90ayBhZ2FpbiB0byBrZWVwIHVzZSBvZiBhc3ltbWV0cmljIGtleXMgdG8gYSBtaW5pbXVtLlxuICAgIGluaXRpYXRvck9uZVRpbWVQYmtDaXBoZXIgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICBkZWNyeXB0ZWRPdGsub3RLZXksXG4gICAgICBpbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyXG4gICAgKTtcblxuICAgIHJldHVybiBuZXcgTHJNdXRhdGlvbih7XG4gICAgICBtdXRhdGlvbjogUmVzcG9uZEtleUV4Y2hhbmdlT3RrTXV0YXRpb24sXG4gICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICBrZXlFeGNoYW5nZUlkLFxuICAgICAgICAgIGtleUV4Y2hhbmdlVG9rZW46IHRva2VuLFxuICAgICAgICAgIHJvb3RLZXlJZDogcm9vdEtleS5pZCxcbiAgICAgICAgICBtYXN0ZXJLZXlJZDogbWFzdGVyS2V5LmlkLFxuICAgICAgICAgIC8vIFRoZXNlIHdpbGwgYmUgc3RvcmVkIG9uIHRoZSBzZXJ2ZXJcbiAgICAgICAgICByZXNwb25kZXJQeGtJZDogcmVzcG9uZGVyUHJrLmlkLFxuICAgICAgICAgIHJlc3BvbmRlclNpZ1B4a0lkOiByZXNwb25kZXJTaWdQcmsuaWQsXG4gICAgICAgICAgc2lnbmVkSW5pdGlhdG9yUGJrOiBKU09OLnN0cmluZ2lmeShzaWduZWRJbml0aWF0b3JQYmspLFxuICAgICAgICAgIHNpZ25lZEluaXRpYXRvclNpZ1BiazogSlNPTi5zdHJpbmdpZnkoc2lnbmVkSW5pdGlhdG9yU2lnUGJrKSxcbiAgICAgICAgICAvLyBya1dyYXBwZWRJbml0aWF0b3JTaWdQYms6IEpTT04uc3RyaW5naWZ5KHJrV3JhcHBlZEluaXRpYXRvclNpZ1BiayksXG5cbiAgICAgICAgICAvLyBPcHRpb24gMTogVXNpbmcgbmV3IFByayBmb3IgZWFjaCBUUCBwYWlyXG4gICAgICAgICAgLy8gcmtXcmFwcGVkUmVzcG9uZGVyU2lnUHJrOiBKU09OLnN0cmluZ2lmeShya1dyYXBwZWRSZXNwb25kZXJTaWdQcmspLFxuICAgICAgICAgIHJrV3JhcHBlZFNoYXJlZEtleTogSlNPTi5zdHJpbmdpZnkocmtXcmFwcGVkU2hhcmVkS2V5KSxcbiAgICAgICAgICBta1dyYXBwZWRNa1NoYXJlZEtleTogSlNPTi5zdHJpbmdpZnkobWtXcmFwcGVkTWtTaGFyZWRLZXkpLFxuICAgICAgICAgIC8vIFRoZXNlIHdpbGwgYmUgc2VudCB0byB0aGUgaW5pdGlhdG9yXG4gICAgICAgICAgaW5pdGlhdG9yT25lVGltZVBia0NpcGhlcjogSlNPTi5zdHJpbmdpZnkoaW5pdGlhdG9yT25lVGltZVBia0NpcGhlciksXG4gICAgICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmQ6IHJlY2VpdmVkQ2FyZElucHV0LFxuICAgICAgICAgIHJlc3BvbmRlckNvbnRhY3RDYXJkOiByZXNwb25kZXJDYXJkSW5wdXQsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgY29tcGxldGVPdGsoaW5wdXQ6IENvbXBsZXRlT3RrSW5wdXQyKSB7XG4gICAgcmV0dXJuIHRoaXMubXV0YXRlKHRoaXMuY29tcGxldGVPdGtNdXRhdGlvbihpbnB1dCkpO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVPdGtNdXRhdGlvbih7XG4gICAga2V5RXhjaGFuZ2VJZCxcbiAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyLFxuICAgIGluaXRpYXRvck9uZVRpbWVQYmtDaXBoZXIsXG4gICAgcmVzcG9uZGVyQ29udGFjdENhcmQsXG4gICAgaW5pdGlhdG9yQ29udGFjdENhcmQsXG4gIH06IENvbXBsZXRlT3RrSW5wdXQyKSB7XG4gICAgY29uc3Qgcm9vdEtleSA9IHRoaXMua2V5U2VydmljZS5jdXJyZW50Um9vdEtleTtcbiAgICBjb25zdCBtYXN0ZXJLZXkgPSB0aGlzLmtleVNlcnZpY2UuY3VycmVudE1hc3RlcktleTtcblxuICAgIC8vIERlY3J5cHQgdXNpbmcgdGhlIHJvb3Qga2V5IHRvIGdldCB0aGUgUHJrXG4gICAgY29uc3QgaW5pdGlhdG9yUm9vdEtleUNpcGhlckNsZWFySnNvbiA9XG4gICAgICAoYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxuICAgICAgICByb290S2V5Lmp3ayxcbiAgICAgICAgaW5pdGlhdG9yUm9vdEtleUNpcGhlclxuICAgICAgKSkgYXMgSW5pdGlhdG9yUm9vdEtleUNpcGhlckNsZWFySnNvbjI7XG5cbiAgICAvLyBUaGUgUHJrIGlzIHNpbmdsZS11c2UgYW5kIG9ubHkgdXNlZCB0byBzZW5kIGluZm9ybWF0aW9uIGZyb20gdGhlIHJlc3BvbmRlciBiYWNrIHRvIHRoZSBpbml0aWF0b3IuXG4gICAgY29uc3QgcGxhaW5Jbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyID0gYXdhaXQgdGhpcy5kZWNyeXB0UmVzcG9uc2VDaXBoZXIoXG4gICAgICBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLm90S2V5KSxcbiAgICAgIGF3YWl0IEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KGluaXRpYXRvclJvb3RLZXlDaXBoZXJDbGVhckpzb24ub25lVGltZVByayksXG4gICAgICBpbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyXG4gICAgKTtcblxuICAgIC8vIENoZWNrIHRoZSBub25jZSBtYXRjaCB0byBlbnN1cmUgdGhlIHJlc3BvbmRlciB3YXMgdGhlIG9uZSBob2xkaW5nIHRoZSBPVEtcbiAgICBpZiAoXG4gICAgICBpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLm5vbmNlICE9PVxuICAgICAgcGxhaW5Jbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyLm5vbmNlXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgS2NDb2RlTWlzbWF0Y2hFeGNlcHRpb24oXG4gICAgICAgICdUaGUgbm9uY2UgcmV0dXJuZWQgYnkgcmVzcG9uZGVyIGRvZXMgbm90IG1hdGNoIHdpdGggdGhlIG9uZSBjcmVhdGVkIGJ5IHRoZSBpbml0aWF0b3IuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBPcHRpb24gMTogQXNzdW1pbmcgdGhlIHNpZ25pbmcga2V5IGlzIHVuaXF1ZSBiZXR3ZWVuIHVzZXJzLlxuICAgIC8vIGNvbnN0IGluaXRpYXRvclNpZ1ByayA9IGF3YWl0IEtGUy5hc0tleShrZS5wbGFpbkluaXRpYXRvclJvb3RLZXlDaXBoZXIuc2lnUHJrKTtcbiAgICAvLyBjb25zdCBya1dyYXBwZWRJbml0aWF0b3JTaWdQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHQocm9vdEtleSwgaW5pdGlhdG9yU2lnUHJrLnRvSlNPTih0cnVlKSk7XG5cbiAgICAvLyBPcHRpb24gMjogVXNlIHRoZSB1c2VyJ3MgZ2xvYmFsIHNpZ25pbmcga2V5LlxuICAgIC8vIEluIHRoaXMgY2FzZSB0aGUgaW5pdGlhdG9yU2lnUHJrIGlzIGFscmVhZHkgYSBwYXJ0IG9mIHRoZSBrZXkgZ3JhcGguXG4gICAgLy8gU28gdGhlcmUncyBub3RoaW5nIHRvIGRvIGhlcmUuXG5cbiAgICAvLyBQcm90ZWN0ZWQgdGhlIHNpZ25pbmcgcHVibGljIGtleSBvZiB0aGUgcmVzcG9uZGVyLlxuICAgIGNvbnN0IGluaXRpYXRvclNpZ1ByayA9IHRoaXMua2V5U2VydmljZS5jdXJyZW50U2lnUHhrO1xuICAgIGNvbnN0IHJlc3BvbmRlclNpZ1BiayA9IGF3YWl0IEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KFxuICAgICAgcGxhaW5Jbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyLnJlc3BvbmRlci5zaWdQYmtcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbmRlclBiayA9IGF3YWl0IEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KFxuICAgICAgcGxhaW5Jbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyLnJlc3BvbmRlci5wYmtcbiAgICApO1xuXG4gICAgY29uc3Qgc2lnbmVkUmVzcG9uZGVyUGJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgaW5pdGlhdG9yU2lnUHJrLmp3ayxcbiAgICAgIHJlc3BvbmRlclBiay50b0pTT04oKVxuICAgICk7XG4gICAgY29uc3Qgc2lnbmVkUmVzcG9uZGVyU2lnUGJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgaW5pdGlhdG9yU2lnUHJrLmp3ayxcbiAgICAgIHJlc3BvbmRlclNpZ1Biay50b0pTT04oKVxuICAgICk7XG5cbiAgICBjb25zdCBzaGFyZWRLZXkgPSBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShcbiAgICAgIHBsYWluSW5pdGlhdG9yT25lVGltZVBia0NpcGhlci5zaGFyZWRLZXlcbiAgICApO1xuICAgIGNvbnN0IHJrV3JhcHBlZFNoYXJlZEtleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgIHJvb3RLZXkuandrLFxuICAgICAgc2hhcmVkS2V5LnRvSlNPTih0cnVlKVxuICAgICk7XG5cbiAgICBjb25zdCBta1NoYXJlZEtleSA9IGF3YWl0IEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KFxuICAgICAgcGxhaW5Jbml0aWF0b3JPbmVUaW1lUGJrQ2lwaGVyLm1rU2hhcmVkS2V5XG4gICAgKTtcbiAgICBjb25zdCBta1dyYXBwZWRNa1NoYXJlZEtleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgIG1hc3RlcktleS5qd2ssXG4gICAgICBta1NoYXJlZEtleS50b0pTT04odHJ1ZSlcbiAgICApO1xuXG4gICAgbGV0IHJlc3BvbmRlckNvbnRhY3RDYXJkQ2lwaGVySW5wdXQ7XG4gICAgaWYgKHJlc3BvbmRlckNvbnRhY3RDYXJkKSB7XG4gICAgICAvLyBDcmVhdGUga2V5XG4gICAgICBjb25zdCByZWNlaXZlcktleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcblxuICAgICAgcmVzcG9uZGVyQ29udGFjdENhcmRDaXBoZXJJbnB1dCA9IHtcbiAgICAgICAgcmVjZWl2ZXJXcmFwcGVkS2V5OiBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICAgICAgICByb290S2V5Lmp3ayxcbiAgICAgICAgICAgIHJlY2VpdmVyS2V5LnRvSlNPTih0cnVlKVxuICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgICAgcmVjZWl2ZXJXcmFwcGluZ0tleUlkOiByb290S2V5LmlkLFxuICAgICAgICByZWNlaXZlckNpcGhlckRhdGE6IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgICAgICAgIHJlY2VpdmVyS2V5LFxuICAgICAgICAgICAgcmVzcG9uZGVyQ29udGFjdENhcmQucmVjZWl2ZXJDaXBoZXJEYXRhQ2xlYXJKc29uXG4gICAgICAgICAgKVxuICAgICAgICApLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIGRhdGEgbmVlZGVkIGZyb20gdGhlIGluaXRpYXRvcidzIGNpcGhlciBkYXRhLlxuICAgIGxldCBpbml0aWF0b3JDb250YWN0Q2FyZENpcGhlcklucHV0O1xuICAgIGxldCBpbml0aWF0b3JDb250YWN0Q2FyZFNoYXJlZENpcGhlcklucHV0O1xuICAgIGlmIChpbml0aWF0b3JSb290S2V5Q2lwaGVyQ2xlYXJKc29uLmluaXRpYXRvckNvbnRhY3RDYXJkKSB7XG4gICAgICAvLyBUaGUgaW5pdGlhdG9yQ29udGFjdENhcmQgY3JlYXRlZCBkdXJpbmcgdGhlIGNyZWF0aW9uIG9mIHRoZSBpbnZpdGUgYW5kIGVuY3J5cHRlZCB1c2luZyB0aGUgaW5pdGlhdG9yJ3NcbiAgICAgIC8vIHJvb3Qga2V5XG4gICAgICBjb25zdCBpbml0aWF0b3JDb250YWN0Q2FyZEZyb21Jbml0ID1cbiAgICAgICAgaW5pdGlhdG9yUm9vdEtleUNpcGhlckNsZWFySnNvbi5pbml0aWF0b3JDb250YWN0Q2FyZDtcbiAgICAgIGNvbnN0IG93bmVyS2V5ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZUtleSgpO1xuICAgICAgY29uc3Qgc2hhcmVkQ2lwaGVyS2V5ID0gYXdhaXQgS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoXG4gICAgICAgIHBsYWluSW5pdGlhdG9yT25lVGltZVBia0NpcGhlci5yZXNwb25kZXIuY29udGFjdENhcmQuc2hhcmVkQ2lwaGVyS2V5XG4gICAgICApO1xuXG4gICAgICBjb25zdCBvd25lcldyYXBwZWRLZXkgPSBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KHJvb3RLZXkuandrLCBvd25lcktleS50b0pTT04odHJ1ZSkpXG4gICAgICApO1xuXG4gICAgICAvLyBBbGxvdyB0aGUgaW5pdGlhdG9yQ29udGFjdENhcmQgcGFyYW1ldGVyIHRvIG92ZXJyaWRlXG4gICAgICBjb25zdCBvd25lckNpcGhlckRhdGFDbGVhckpzb24gPVxuICAgICAgICBpbml0aWF0b3JDb250YWN0Q2FyZD8ub3duZXJDaXBoZXJEYXRhQ2xlYXJKc29uIHx8XG4gICAgICAgIGluaXRpYXRvckNvbnRhY3RDYXJkRnJvbUluaXQub3duZXJDaXBoZXJEYXRhQ2xlYXJKc29uO1xuXG4gICAgICBjb25zdCBvd25lckNpcGhlckRhdGEgPSBvd25lckNpcGhlckRhdGFDbGVhckpzb25cbiAgICAgICAgPyBhd2FpdCB0aGlzLmtleUdyYXBoLmVuY3J5cHRUb1N0cmluZyhcbiAgICAgICAgICAgIG93bmVyS2V5LFxuICAgICAgICAgICAgb3duZXJDaXBoZXJEYXRhQ2xlYXJKc29uXG4gICAgICAgICAgKVxuICAgICAgICA6ICcnO1xuXG4gICAgICBpbml0aWF0b3JDb250YWN0Q2FyZENpcGhlcklucHV0ID0ge1xuICAgICAgICBvd25lcldyYXBwZWRLZXksXG4gICAgICAgIG93bmVyV3JhcHBpbmdLZXlJZDogcm9vdEtleS5pZCxcbiAgICAgICAgb3duZXJDaXBoZXJEYXRhLFxuICAgICAgfTtcblxuICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmRTaGFyZWRDaXBoZXJJbnB1dCA9IHtcbiAgICAgICAgc2lnUHhrSWQ6IGluaXRpYXRvclNpZ1Byay5pZCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNoYXJlZENpcGhlckRhdGEgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHQoXG4gICAgICAgIHNoYXJlZENpcGhlcktleSxcbiAgICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmRGcm9tSW5pdC5zaGFyZWRDaXBoZXJEYXRhQ2xlYXJKc29uXG4gICAgICApO1xuICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmRTaGFyZWRDaXBoZXJJbnB1dC5zaGFyZWRDaXBoZXJEYXRhU2lnID1cbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgICAgICAgaW5pdGlhdG9yU2lnUHJrLmp3ayxcbiAgICAgICAgICAgIHNoYXJlZENpcGhlckRhdGFcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVE9ETyBpZGVhbGx5IHdlIHVwZGF0ZSB0aGUgc2hhcmVkIGRhdGEgaW4gdGhlIGNvbnRhY3QgY2FyZCBzZW50IHRvIHRoZSByZXNwb25kZXIgYXMgd2VsbCBzaW5jZSB0aGF0XG4gICAgLy8gQ0Mgd2FzIGNyZWF0ZWQgYnkgdGhlIHJlc3BvbmRlci5cblxuICAgIHJldHVybiBuZXcgTHJNdXRhdGlvbih7XG4gICAgICBtdXRhdGlvbjogQ29tcGxldGVLZXlFeGNoYW5nZU90a011dGF0aW9uLFxuICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgIGlucHV0OiB7XG4gICAgICAgICAga2V5RXhjaGFuZ2VJZCxcbiAgICAgICAgICByb290S2V5SWQ6IHJvb3RLZXkuaWQsXG4gICAgICAgICAgbWFzdGVyS2V5SWQ6IG1hc3RlcktleS5pZCxcbiAgICAgICAgICBpbml0aWF0b3JTaWdQeGtJZDogaW5pdGlhdG9yU2lnUHJrLmlkLFxuICAgICAgICAgIHNpZ25lZFJlc3BvbmRlclBiazogSlNPTi5zdHJpbmdpZnkoc2lnbmVkUmVzcG9uZGVyUGJrKSxcbiAgICAgICAgICBzaWduZWRSZXNwb25kZXJTaWdQYms6IEpTT04uc3RyaW5naWZ5KHNpZ25lZFJlc3BvbmRlclNpZ1BiayksXG4gICAgICAgICAgcmtXcmFwcGVkU2hhcmVkS2V5OiBKU09OLnN0cmluZ2lmeShya1dyYXBwZWRTaGFyZWRLZXkpLFxuICAgICAgICAgIG1rV3JhcHBlZE1rU2hhcmVkS2V5OiBKU09OLnN0cmluZ2lmeShta1dyYXBwZWRNa1NoYXJlZEtleSksXG4gICAgICAgICAgcmVzcG9uZGVyQ29udGFjdENhcmRDaXBoZXI6IHJlc3BvbmRlckNvbnRhY3RDYXJkQ2lwaGVySW5wdXQsXG4gICAgICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmRDaXBoZXI6IGluaXRpYXRvckNvbnRhY3RDYXJkQ2lwaGVySW5wdXQsXG4gICAgICAgICAgaW5pdGlhdG9yQ29udGFjdENhcmRTaGFyZWRDaXBoZXI6XG4gICAgICAgICAgICBpbml0aWF0b3JDb250YWN0Q2FyZFNoYXJlZENpcGhlcklucHV0LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuIl19