@lifeready/core 1.0.21 → 1.0.22

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