@lifeready/core 1.0.13 → 1.0.15

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 (219) hide show
  1. package/README.md +62 -62
  2. package/bundles/lifeready-core.umd.js +14315 -14315
  3. package/bundles/lifeready-core.umd.js.map +1 -1
  4. package/bundles/lifeready-core.umd.min.js.map +1 -1
  5. package/esm2015/lib/_common/ast.js +40 -40
  6. package/esm2015/lib/_common/deferred-promise.js +24 -24
  7. package/esm2015/lib/_common/exceptions.js +157 -157
  8. package/esm2015/lib/_common/queries.gql.js +190 -190
  9. package/esm2015/lib/_common/run-outside-angular.js +79 -79
  10. package/esm2015/lib/_common/types.js +1 -1
  11. package/esm2015/lib/_common/utils.js +52 -52
  12. package/esm2015/lib/api/contact-card.gql.js +79 -79
  13. package/esm2015/lib/api/contact-card.service.js +154 -154
  14. package/esm2015/lib/api/contact-card2.gql.js +60 -60
  15. package/esm2015/lib/api/contact-card2.service.js +103 -103
  16. package/esm2015/lib/api/file.service.js +74 -74
  17. package/esm2015/lib/api/key-exchange.gql.js +188 -188
  18. package/esm2015/lib/api/key-exchange.service.js +442 -442
  19. package/esm2015/lib/api/key-exchange.types.js +18 -18
  20. package/esm2015/lib/api/key-exchange2.gql.js +171 -171
  21. package/esm2015/lib/api/key-exchange2.service.js +479 -479
  22. package/esm2015/lib/api/lock.gql.js +40 -40
  23. package/esm2015/lib/api/lock.service.js +64 -64
  24. package/esm2015/lib/api/lr-apollo.service.js +46 -46
  25. package/esm2015/lib/api/lr-graphql/index.js +6 -6
  26. package/esm2015/lib/api/lr-graphql/lr-graphql.service.js +155 -155
  27. package/esm2015/lib/api/lr-graphql/lr-merged-mutation.js +213 -213
  28. package/esm2015/lib/api/lr-graphql/lr-mutation-base.js +51 -51
  29. package/esm2015/lib/api/lr-graphql/lr-mutation.js +48 -48
  30. package/esm2015/lib/api/lr-graphql/lr.service.js +18 -18
  31. package/esm2015/lib/api/message.service.js +138 -138
  32. package/esm2015/lib/api/persist.service.js +181 -181
  33. package/esm2015/lib/api/query-processor/common-processors.service.js +93 -93
  34. package/esm2015/lib/api/query-processor/index.js +3 -3
  35. package/esm2015/lib/api/query-processor/query-processor.service.js +262 -262
  36. package/esm2015/lib/api/query-processor/tp-password-reset-processor.service.js +109 -109
  37. package/esm2015/lib/api/shared-contact-card.service.js +119 -119
  38. package/esm2015/lib/api/shared-contact-card2.gql.js +41 -41
  39. package/esm2015/lib/api/shared-contact-card2.service.js +117 -117
  40. package/esm2015/lib/api/time.service.js +146 -146
  41. package/esm2015/lib/api/types/graphql.types.js +7 -7
  42. package/esm2015/lib/api/types/index.js +3 -3
  43. package/esm2015/lib/api/types/lr-graphql.types.js +101 -101
  44. package/esm2015/lib/auth/auth.config.js +57 -57
  45. package/esm2015/lib/auth/auth.gql.js +48 -48
  46. package/esm2015/lib/auth/auth.types.js +27 -27
  47. package/esm2015/lib/auth/idle.service.js +168 -168
  48. package/esm2015/lib/auth/idle.types.js +7 -7
  49. package/esm2015/lib/auth/lbop.service.js +355 -355
  50. package/esm2015/lib/auth/life-ready-auth.service.js +488 -488
  51. package/esm2015/lib/auth/password.service.js +320 -320
  52. package/esm2015/lib/auth/register.service.js +172 -172
  53. package/esm2015/lib/auth/two-factor.service.js +74 -74
  54. package/esm2015/lib/category/category-meta.service.js +99 -99
  55. package/esm2015/lib/category/category.gql.js +406 -406
  56. package/esm2015/lib/category/category.service.js +390 -390
  57. package/esm2015/lib/category/category.types.js +29 -29
  58. package/esm2015/lib/cryptography/cryptography.types.js +11 -11
  59. package/esm2015/lib/cryptography/encryption.service.js +189 -189
  60. package/esm2015/lib/cryptography/key-factory.service.js +237 -237
  61. package/esm2015/lib/cryptography/key-graph.service.js +299 -299
  62. package/esm2015/lib/cryptography/key-meta.service.js +200 -200
  63. package/esm2015/lib/cryptography/key.service.js +124 -124
  64. package/esm2015/lib/cryptography/slip39.service.js +169 -169
  65. package/esm2015/lib/cryptography/web-crypto.service.js +29 -29
  66. package/esm2015/lib/items2/item2.gql.js +139 -139
  67. package/esm2015/lib/items2/item2.service.js +498 -498
  68. package/esm2015/lib/items2/item2.types.js +1 -1
  69. package/esm2015/lib/life-ready.config.js +84 -84
  70. package/esm2015/lib/life-ready.module.js +74 -74
  71. package/esm2015/lib/notification/notification.gql.js +43 -43
  72. package/esm2015/lib/notification/notification.service.js +118 -118
  73. package/esm2015/lib/plan/plan.gql.js +123 -123
  74. package/esm2015/lib/plan/plan.service.js +149 -149
  75. package/esm2015/lib/plan/plan.types.js +11 -11
  76. package/esm2015/lib/record/record-attachment.service.js +101 -101
  77. package/esm2015/lib/record/record.gql.js +179 -179
  78. package/esm2015/lib/record/record.service.js +206 -206
  79. package/esm2015/lib/record/record.types.js +15 -15
  80. package/esm2015/lib/record-type/record-type.service.js +75 -75
  81. package/esm2015/lib/record-type/record-type.types.js +28 -28
  82. package/esm2015/lib/scenario/scenario.constants.js +2 -2
  83. package/esm2015/lib/scenario/scenario.controller.js +34 -34
  84. package/esm2015/lib/scenario/scenario.gql.js +72 -72
  85. package/esm2015/lib/scenario/scenario.gql.private.js +198 -198
  86. package/esm2015/lib/scenario/scenario.service.js +538 -538
  87. package/esm2015/lib/scenario/scenario.types.js +1 -1
  88. package/esm2015/lib/trusted-parties/tp-assembly.gql.private.js +22 -22
  89. package/esm2015/lib/trusted-parties/tp-assembly.js +362 -362
  90. package/esm2015/lib/trusted-parties/tp-assembly.types.js +1 -1
  91. package/esm2015/lib/trusted-parties/tp-password-reset-request.service.js +113 -113
  92. package/esm2015/lib/trusted-parties/tp-password-reset-user.service.js +129 -129
  93. package/esm2015/lib/trusted-parties/tp-password-reset.constants.js +4 -4
  94. package/esm2015/lib/trusted-parties/tp-password-reset.controller.js +34 -34
  95. package/esm2015/lib/trusted-parties/tp-password-reset.gql.js +236 -236
  96. package/esm2015/lib/trusted-parties/tp-password-reset.service.js +95 -95
  97. package/esm2015/lib/trusted-parties/trusted-party.gql.js +148 -148
  98. package/esm2015/lib/trusted-parties/trusted-party.service.js +326 -326
  99. package/esm2015/lib/trusted-parties/trusted-party.types.js +41 -41
  100. package/esm2015/lib/trusted-parties/trusted-party2.gql.js +87 -87
  101. package/esm2015/lib/trusted-parties/trusted-party2.service.js +215 -215
  102. package/esm2015/lib/users/profile-details.service.js +214 -214
  103. package/esm2015/lib/users/profile.gql.js +97 -97
  104. package/esm2015/lib/users/profile.service.js +169 -169
  105. package/esm2015/lib/users/profile.types.js +34 -34
  106. package/esm2015/lib/users/user.gql.js +60 -60
  107. package/esm2015/lib/users/user.service.js +79 -79
  108. package/esm2015/lib/users/user.types.js +5 -5
  109. package/esm2015/lifeready-core.js +13 -13
  110. package/esm2015/public-api.js +71 -71
  111. package/fesm2015/lifeready-core.js +12258 -12258
  112. package/fesm2015/lifeready-core.js.map +1 -1
  113. package/lib/_common/ast.d.ts +11 -11
  114. package/lib/_common/deferred-promise.d.ts +12 -12
  115. package/lib/_common/exceptions.d.ts +109 -109
  116. package/lib/_common/queries.gql.d.ts +10 -10
  117. package/lib/_common/run-outside-angular.d.ts +14 -14
  118. package/lib/_common/types.d.ts +10 -10
  119. package/lib/_common/utils.d.ts +9 -9
  120. package/lib/api/contact-card.gql.d.ts +7 -7
  121. package/lib/api/contact-card.service.d.ts +52 -52
  122. package/lib/api/contact-card2.gql.d.ts +34 -34
  123. package/lib/api/contact-card2.service.d.ts +49 -49
  124. package/lib/api/file.service.d.ts +18 -18
  125. package/lib/api/key-exchange.gql.d.ts +9 -9
  126. package/lib/api/key-exchange.service.d.ts +39 -39
  127. package/lib/api/key-exchange.types.d.ts +196 -196
  128. package/lib/api/key-exchange2.gql.d.ts +125 -125
  129. package/lib/api/key-exchange2.service.d.ts +187 -187
  130. package/lib/api/lock.gql.d.ts +27 -27
  131. package/lib/api/lock.service.d.ts +34 -34
  132. package/lib/api/lr-apollo.service.d.ts +15 -15
  133. package/lib/api/lr-graphql/index.d.ts +5 -5
  134. package/lib/api/lr-graphql/lr-graphql.service.d.ts +60 -60
  135. package/lib/api/lr-graphql/lr-merged-mutation.d.ts +28 -28
  136. package/lib/api/lr-graphql/lr-mutation-base.d.ts +28 -28
  137. package/lib/api/lr-graphql/lr-mutation.d.ts +8 -8
  138. package/lib/api/lr-graphql/lr.service.d.ts +9 -9
  139. package/lib/api/message.service.d.ts +58 -58
  140. package/lib/api/persist.service.d.ts +31 -31
  141. package/lib/api/query-processor/common-processors.service.d.ts +36 -36
  142. package/lib/api/query-processor/index.d.ts +2 -2
  143. package/lib/api/query-processor/query-processor.service.d.ts +18 -18
  144. package/lib/api/query-processor/tp-password-reset-processor.service.d.ts +15 -15
  145. package/lib/api/shared-contact-card.service.d.ts +33 -33
  146. package/lib/api/shared-contact-card2.gql.d.ts +36 -36
  147. package/lib/api/shared-contact-card2.service.d.ts +45 -45
  148. package/lib/api/time.service.d.ts +16 -16
  149. package/lib/api/types/graphql.types.d.ts +29 -29
  150. package/lib/api/types/index.d.ts +2 -2
  151. package/lib/api/types/lr-graphql.types.d.ts +502 -502
  152. package/lib/auth/auth.config.d.ts +5 -5
  153. package/lib/auth/auth.gql.d.ts +15 -15
  154. package/lib/auth/auth.types.d.ts +66 -66
  155. package/lib/auth/idle.service.d.ts +40 -40
  156. package/lib/auth/idle.types.d.ts +10 -10
  157. package/lib/auth/lbop.service.d.ts +91 -91
  158. package/lib/auth/life-ready-auth.service.d.ts +61 -61
  159. package/lib/auth/password.service.d.ts +78 -78
  160. package/lib/auth/register.service.d.ts +25 -25
  161. package/lib/auth/two-factor.service.d.ts +15 -15
  162. package/lib/category/category-meta.service.d.ts +23 -23
  163. package/lib/category/category.gql.d.ts +45 -45
  164. package/lib/category/category.service.d.ts +67 -67
  165. package/lib/category/category.types.d.ts +79 -79
  166. package/lib/cryptography/cryptography.types.d.ts +83 -83
  167. package/lib/cryptography/encryption.service.d.ts +41 -41
  168. package/lib/cryptography/key-factory.service.d.ts +38 -38
  169. package/lib/cryptography/key-graph.service.d.ts +41 -41
  170. package/lib/cryptography/key-meta.service.d.ts +44 -44
  171. package/lib/cryptography/key.service.d.ts +36 -36
  172. package/lib/cryptography/slip39.service.d.ts +43 -43
  173. package/lib/cryptography/web-crypto.service.d.ts +5 -5
  174. package/lib/items2/item2.gql.d.ts +123 -123
  175. package/lib/items2/item2.service.d.ts +203 -203
  176. package/lib/items2/item2.types.d.ts +70 -70
  177. package/lib/life-ready.config.d.ts +14 -14
  178. package/lib/life-ready.module.d.ts +5 -5
  179. package/lib/notification/notification.gql.d.ts +37 -37
  180. package/lib/notification/notification.service.d.ts +63 -63
  181. package/lib/plan/plan.gql.d.ts +11 -11
  182. package/lib/plan/plan.service.d.ts +33 -33
  183. package/lib/plan/plan.types.d.ts +31 -31
  184. package/lib/record/record-attachment.service.d.ts +16 -16
  185. package/lib/record/record.gql.d.ts +14 -14
  186. package/lib/record/record.service.d.ts +25 -25
  187. package/lib/record/record.types.d.ts +57 -57
  188. package/lib/record-type/record-type.service.d.ts +11 -11
  189. package/lib/record-type/record-type.types.d.ts +50 -50
  190. package/lib/scenario/scenario.constants.d.ts +1 -1
  191. package/lib/scenario/scenario.controller.d.ts +10 -10
  192. package/lib/scenario/scenario.gql.d.ts +62 -62
  193. package/lib/scenario/scenario.gql.private.d.ts +16 -16
  194. package/lib/scenario/scenario.service.d.ts +233 -233
  195. package/lib/scenario/scenario.types.d.ts +50 -50
  196. package/lib/trusted-parties/tp-assembly.d.ts +177 -177
  197. package/lib/trusted-parties/tp-assembly.gql.private.d.ts +5 -5
  198. package/lib/trusted-parties/tp-assembly.types.d.ts +38 -38
  199. package/lib/trusted-parties/tp-password-reset-request.service.d.ts +20 -20
  200. package/lib/trusted-parties/tp-password-reset-user.service.d.ts +35 -35
  201. package/lib/trusted-parties/tp-password-reset.constants.d.ts +3 -3
  202. package/lib/trusted-parties/tp-password-reset.controller.d.ts +10 -10
  203. package/lib/trusted-parties/tp-password-reset.gql.d.ts +223 -223
  204. package/lib/trusted-parties/tp-password-reset.service.d.ts +188 -188
  205. package/lib/trusted-parties/trusted-party.gql.d.ts +9 -9
  206. package/lib/trusted-parties/trusted-party.service.d.ts +44 -44
  207. package/lib/trusted-parties/trusted-party.types.d.ts +102 -102
  208. package/lib/trusted-parties/trusted-party2.gql.d.ts +79 -79
  209. package/lib/trusted-parties/trusted-party2.service.d.ts +114 -114
  210. package/lib/users/profile-details.service.d.ts +21 -21
  211. package/lib/users/profile.gql.d.ts +11 -11
  212. package/lib/users/profile.service.d.ts +35 -35
  213. package/lib/users/profile.types.d.ts +96 -96
  214. package/lib/users/user.gql.d.ts +9 -9
  215. package/lib/users/user.service.d.ts +12 -12
  216. package/lib/users/user.types.d.ts +23 -23
  217. package/lifeready-core.d.ts +12 -12
  218. package/package.json +1 -1
  219. package/public-api.d.ts +67 -67
@@ -1,320 +1,320 @@
1
- import { __awaiter } from "tslib";
2
- import { HttpClient } from '@angular/common/http';
3
- import { Inject, Injectable } from '@angular/core';
4
- import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
5
- import { ProfileService } from '../users/profile.service';
6
- import { EncryptionService } from '../cryptography/encryption.service';
7
- import { KeyGraphService } from '../cryptography/key-graph.service';
8
- import { LR_CONFIG } from '../life-ready.config';
9
- import { LrAuthException, LrBadArgumentException } from '../_common/exceptions';
10
- import { LrApolloService } from './../api/lr-apollo.service';
11
- import { PasswordChangeMutation, PasswordChangeRequestMutation, PasswordChangeConfigQuery, } from './auth.gql';
12
- import { WebCryptoService } from '../cryptography/web-crypto.service';
13
- import * as moment_ from 'moment';
14
- import { IdleService } from '../auth/idle.service';
15
- import { KeyFactoryService as KFS } from '../cryptography/key-factory.service';
16
- import * as i0 from "@angular/core";
17
- import * as i1 from "../life-ready.config";
18
- import * as i2 from "@angular/common/http";
19
- import * as i3 from "../api/lr-apollo.service";
20
- import * as i4 from "@aws-amplify/auth/lib-esm/Auth";
21
- import * as i5 from "../users/profile.service";
22
- import * as i6 from "../cryptography/key-factory.service";
23
- import * as i7 from "../cryptography/encryption.service";
24
- import * as i8 from "../cryptography/key-graph.service";
25
- import * as i9 from "../cryptography/web-crypto.service";
26
- import * as i10 from "./idle.service";
27
- // "why?" you ask: https://stackoverflow.com/questions/59735280/angular-8-moment-error-cannot-call-a-namespace-moment
28
- const moment = moment_;
29
- export class PasswordCheck {
30
- }
31
- export class PasswordService {
32
- constructor(config, http, apollo, auth, profileService, keyFactory, encryptionService, keyGraph, webCryptoService, idleService) {
33
- this.config = config;
34
- this.http = http;
35
- this.apollo = apollo;
36
- this.auth = auth;
37
- this.profileService = profileService;
38
- this.keyFactory = keyFactory;
39
- this.encryptionService = encryptionService;
40
- this.keyGraph = keyGraph;
41
- this.webCryptoService = webCryptoService;
42
- this.idleService = idleService;
43
- this.CLIENT_NONCE_LENGTH = 32;
44
- }
45
- checkPassword(password) {
46
- return __awaiter(this, void 0, void 0, function* () {
47
- const { years } = this.passwordStrength(password);
48
- return {
49
- length: password.length,
50
- timeToCrack: moment.duration({ years }),
51
- passwordExposed: yield this.getExposureCount(password),
52
- };
53
- });
54
- }
55
- getExposureCount(password) {
56
- return __awaiter(this, void 0, void 0, function* () {
57
- const sha1Password = yield this.webCryptoService.stringDigest('SHA-1', password);
58
- const first5sha1 = sha1Password.substring(0, 5);
59
- const response = yield this.http
60
- .get(`https://api.pwnedpasswords.com/range/${first5sha1}`, {
61
- responseType: 'text',
62
- })
63
- .toPromise();
64
- const results = new RegExp(`^(?:${sha1Password.substring(5)}:)(?<count>\\d+)$`, 'im').exec(response);
65
- if (results) {
66
- return +results.groups.count;
67
- }
68
- return 0;
69
- });
70
- }
71
- getPassIdpString(passIdp) {
72
- return passIdp.toJSON(true).k;
73
- }
74
- createPassKeyBundle(password) {
75
- return __awaiter(this, void 0, void 0, function* () {
76
- const passIdpParams = yield this.keyFactory.createPassIdpParams();
77
- const passIdp = (yield this.keyFactory.derivePassIdp(Object.assign({ password }, passIdpParams))).jwk;
78
- const passKeyParams = yield this.keyFactory.createPassKeyParams();
79
- const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, passKeyParams))).jwk;
80
- const passIdpVerifier = yield this.keyFactory.createPkcSignKey();
81
- const wrappedPassIdpVerifierPrk = yield this.encryptionService.encrypt(passKey, passIdpVerifier.toJSON(true));
82
- // There are two formats that the private key can be represented in JWK:
83
- // https://tools.ietf.org/html/rfc8017#page-9
84
- // The second form is an optimization:
85
- // https://crypto.stackexchange.com/questions/19413/what-are-dp-and-dq-in-encryption-by-rsa-in-c
86
- return {
87
- passKeyParams,
88
- passKey,
89
- passIdpParams,
90
- passIdp,
91
- passIdpVerifier,
92
- wrappedPassIdpVerifierPrk,
93
- };
94
- });
95
- }
96
- /**
97
- * We need to allow for interruption of the process at any point. Each API call can be considered
98
- * atomic and either succeeds or fails.
99
- *
100
- * The LR server APIs use semaphore tokens for locking critical operations, so concurrent calls will
101
- * fail.
102
- *
103
- * We assume the worst case for IdP API calls. So we use the semaphore token from LR to prevent
104
- * concurrent calls to IdP APIs, but we have to assume that the IdP API calls will either succeed or
105
- * fail within a reasonable amount of time.
106
- *
107
- * Each location where the server state changes can be a potential point of interruption.
108
- * Potential points of interruption are marked with: --Potential Failure Point--
109
- *
110
- * Places for timeout:
111
- * - Login age too old at call to: verifyPassword()
112
- * - Login age too old at call to: changePasswordMutation()
113
- * - Semaphore token expires at call to: changePasswordComplete()
114
- *
115
- * Tests:
116
- * - Potential Failure Point 1: should be able to restart the process, user remains signed in.
117
- * - Potential Failure Point 2: should enter recovery flow
118
- * - Potential Failure Point 3: should enter recovery flow
119
- * - Potential Failure Point 4: should enter recovery flow
120
- *
121
- */
122
- isLoginRequired() {
123
- return __awaiter(this, void 0, void 0, function* () {
124
- const changePasswordConfig = yield this.getChangePasswordConfig();
125
- const authTime = moment(changePasswordConfig.authTime);
126
- const serverTime = moment(changePasswordConfig.serverTime);
127
- const duration = moment.duration(serverTime.diff(authTime));
128
- const seconds = duration.asSeconds();
129
- if (seconds > changePasswordConfig.maxAuthAgeSeconds) {
130
- return true;
131
- }
132
- else {
133
- return false;
134
- }
135
- });
136
- }
137
- changePassword(password, newPassword) {
138
- return __awaiter(this, void 0, void 0, function* () {
139
- const cognitoUser = yield this.auth.currentAuthenticatedUser();
140
- // Validation
141
- // todo: Add this back in
142
- // Note the passIdp will always have a random salt, so will always be different to the current passIdp.
143
- if (password === newPassword) {
144
- throw new LrBadArgumentException('New password is the same as the current one.');
145
- }
146
- const { currentUser } = yield this.profileService.getCurrentUser();
147
- const { passIdp, signedChallenge } = yield this.verifyPassword(password, currentUser);
148
- // --Potential Failure Point 1--
149
- // verifyPassword() asks for a current password challenge hence changes server state.
150
- // Place break points here to test the failure scenarios.
151
- // Generate the new passIdp
152
- const newPassKey = yield this.createPassKeyBundle(newPassword);
153
- // Re-encrypt master key with new key
154
- const masterKey = yield this.keyGraph.getKey(currentUser.currentUserKey.masterKey.id);
155
- const newWrappedMasterKey = yield this.encryptionService.encrypt(newPassKey.passKey, masterKey.jwk.toJSON(true));
156
- // If the IdP change password failed, we need to go into recovery mode by forcing
157
- // a login. We can't logout the user just yet since the IdP password change needs
158
- // the user to be logged in. We _can_ removed any persisted session values for the IdP
159
- // but that seems like too much trouble.
160
- const { token, newPassKeyId } = yield this.changePasswordMutation(signedChallenge, currentUser.currentUserKey.masterKey.id, newWrappedMasterKey, newPassKey);
161
- // --Potential Failure Point 2--
162
- // changePasswordMutation() uploads new keys and obtains a semaphore lock to prevent any other
163
- // clients from performing IdP password change.
164
- // Now we can do the IdP password change.
165
- // todo: Add this back in
166
- yield this.auth.changePassword(cognitoUser, this.getPassIdpString(passIdp), this.getPassIdpString(newPassKey.passIdp));
167
- // --Potential Failure Point 3--
168
- // IdP password change
169
- // Note that changePassword() could throw an exception for a number of reason. It could throw
170
- // a network timeout for example. But we don't know if it's the response that timed out and
171
- // the idp password change was actually carried out. So we have to be extra conservative and
172
- // only act on a clear success. Otherwise we go into recover mode.
173
- yield this.changePasswordComplete(cognitoUser.getSignInUserSession().getAccessToken().getJwtToken(), true, token);
174
- });
175
- }
176
- changePasswordComplete(accessToken, useNewPassword, token = null) {
177
- return __awaiter(this, void 0, void 0, function* () {
178
- return this.http
179
- .post(`${this.config.authUrl}users/password-change-complete/`, Object.assign({ use_new_password: useNewPassword }, (token && { token })), {
180
- headers: {
181
- Authorization: `Bearer ${accessToken}`,
182
- },
183
- })
184
- .toPromise();
185
- });
186
- }
187
- getVerifierPrK(passKey, wrappedPrK) {
188
- return __awaiter(this, void 0, void 0, function* () {
189
- try {
190
- const prkJson = yield this.encryptionService.decrypt(passKey, wrappedPrK);
191
- return KFS.asKey(prkJson);
192
- }
193
- catch (error) {
194
- throw new LrAuthException('Wrong current password');
195
- }
196
- });
197
- }
198
- verifyPassword(password, currentUser) {
199
- return __awaiter(this, void 0, void 0, function* () {
200
- // Get information from the server to prepare for password change.
201
- const passwordRequest = yield this.apollo.mutate({
202
- mutation: PasswordChangeRequestMutation,
203
- variables: {},
204
- });
205
- // Get the old passKey so we can decrypt the old password verifier
206
- const passKeyResult = yield this.keyFactory.derivePassKey(Object.assign({ password }, currentUser.currentUserKey.passKey.passKeyParams));
207
- const verifierPrK = yield this.getVerifierPrK(passKeyResult.jwk, currentUser.currentUserKey.passKey.wrappedPassIdpVerifierPrk);
208
- // Sign the server challenge to prove to the server we can decrypt the password verifier.
209
- // Generate
210
- const clientNonce = this.keyFactory.randomString(this.CLIENT_NONCE_LENGTH);
211
- const signedChallenge = yield this.encryptionService.sign(verifierPrK, {
212
- serverNonce: passwordRequest.passwordChangeRequest.challenge.serverNonce,
213
- clientNonce,
214
- });
215
- const passIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password }, currentUser.currentUserKey.passKey.passIdpParams));
216
- return {
217
- passIdp: passIdpResult.jwk,
218
- signedChallenge,
219
- };
220
- });
221
- }
222
- changePasswordMutation(signedChallenge, masterKeyId, newWrappedMasterKey, passKeyBundle) {
223
- return __awaiter(this, void 0, void 0, function* () {
224
- const response = yield this.apollo.mutate({
225
- mutation: PasswordChangeMutation,
226
- variables: {
227
- input: {
228
- signedChallenge: JSON.stringify(signedChallenge),
229
- masterKeyId,
230
- newWrappedMasterKey: JSON.stringify(newWrappedMasterKey),
231
- newPassKey: {
232
- passIdpParams: JSON.stringify(passKeyBundle.passIdpParams),
233
- passIdpVerifierPbk: JSON.stringify(passKeyBundle.passIdpVerifier.toJSON()),
234
- wrappedPassIdpVerifierPrk: JSON.stringify(passKeyBundle.wrappedPassIdpVerifierPrk),
235
- passKeyParams: JSON.stringify(passKeyBundle.passKeyParams),
236
- },
237
- },
238
- },
239
- });
240
- return {
241
- token: response.passwordChange.token,
242
- newPassKeyId: response.passwordChange.newPassKey.id,
243
- };
244
- });
245
- }
246
- getChangePasswordConfig() {
247
- return __awaiter(this, void 0, void 0, function* () {
248
- const res = yield this.apollo.query({
249
- query: PasswordChangeConfigQuery,
250
- });
251
- const ret = res.passwordChangeConfig;
252
- ret.authTime = new Date(ret.authTime);
253
- ret.serverTime = new Date(ret.serverTime);
254
- return ret;
255
- });
256
- }
257
- passwordStrength(password) {
258
- const upper = /[A-Z]/g;
259
- const lower = /[a-z]/g;
260
- const digit = /[0-9]/g;
261
- const upperChoices = 26;
262
- const lowerChoices = 26;
263
- const digitChoices = 10;
264
- const specialChoices = 30; // /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g
265
- function instanceCount(str, re) {
266
- return ((str || '').match(re) || []).length;
267
- }
268
- const uppers = instanceCount(password, upper);
269
- const lowers = instanceCount(password, lower);
270
- const digits = instanceCount(password, digit);
271
- const specials = password.length - uppers - lowers - digits;
272
- let choices = 0;
273
- if (uppers) {
274
- choices += upperChoices;
275
- }
276
- if (lowers) {
277
- choices += lowerChoices;
278
- }
279
- if (digits) {
280
- choices += digitChoices;
281
- }
282
- if (specials) {
283
- choices += specialChoices;
284
- }
285
- if (password.length === 0) {
286
- return {
287
- years: 0,
288
- // bits of entropy
289
- bits: 0,
290
- };
291
- }
292
- const permutations = Math.pow(choices, password.length);
293
- const years = (54000 * permutations) /
294
- Math.pow(upperChoices + lowerChoices + digitChoices, 12);
295
- return {
296
- years,
297
- // bits of entropy
298
- bits: Math.round(Math.log2(permutations)),
299
- };
300
- }
301
- }
302
- PasswordService.ɵprov = i0.ɵɵdefineInjectable({ factory: function PasswordService_Factory() { return new PasswordService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.HttpClient), i0.ɵɵinject(i3.LrApolloService), i0.ɵɵinject(i4.AuthClass), i0.ɵɵinject(i5.ProfileService), i0.ɵɵinject(i6.KeyFactoryService), i0.ɵɵinject(i7.EncryptionService), i0.ɵɵinject(i8.KeyGraphService), i0.ɵɵinject(i9.WebCryptoService), i0.ɵɵinject(i10.IdleService)); }, token: PasswordService, providedIn: "root" });
303
- PasswordService.decorators = [
304
- { type: Injectable, args: [{
305
- providedIn: 'root',
306
- },] }
307
- ];
308
- PasswordService.ctorParameters = () => [
309
- { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
310
- { type: HttpClient },
311
- { type: LrApolloService },
312
- { type: AuthClass },
313
- { type: ProfileService },
314
- { type: KFS },
315
- { type: EncryptionService },
316
- { type: KeyGraphService },
317
- { type: WebCryptoService },
318
- { type: IdleService }
319
- ];
320
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIvb3B0L2F0bGFzc2lhbi9waXBlbGluZXMvYWdlbnQvYnVpbGQvcHJvamVjdHMvY29yZS9zcmMvIiwic291cmNlcyI6WyJsaWIvYXV0aC9wYXNzd29yZC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRTNELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFtQixTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsNkJBQTZCLEVBQzdCLHlCQUF5QixHQUMxQixNQUFNLFlBQVksQ0FBQztBQUVwQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUV0RSxPQUFPLEtBQUssT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixJQUFJLEdBQUcsRUFBRSxNQUFNLHFDQUFxQyxDQUFDOzs7Ozs7Ozs7Ozs7QUFFL0UscUhBQXFIO0FBQ3JILE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQztBQXlCdkIs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QjtRQUVELElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDekIsT0FBTztnQkFDTCxLQUFLLEVBQUUsQ0FBQztnQkFDUixrQkFBa0I7Z0JBQ2xCLElBQUksRUFBRSxDQUFDO2FBQ1IsQ0FBQztTQUNIO1FBRUQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXhELE1BQU0sS0FBSyxHQUNULENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztZQUN0QixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksR0FBRyxZQUFZLEdBQUcsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNELE9BQU87WUFDTCxLQUFLO1lBQ0wsa0JBQWtCO1lBQ2xCLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDMUMsQ0FBQztJQUNKLENBQUM7Ozs7WUE1WEYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7NENBS0ksTUFBTSxTQUFDLFNBQVM7WUEvRFosVUFBVTtZQVVWLGVBQWU7WUFQZixTQUFTO1lBRVQsY0FBYztZQWlCTyxHQUFHO1lBaEJ4QixpQkFBaUI7WUFDakIsZUFBZTtZQVVmLGdCQUFnQjtZQUloQixXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29nbml0b1VzZXIgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aCc7XG5pbXBvcnQgeyBBdXRoQ2xhc3MgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aC9saWItZXNtL0F1dGgnO1xuaW1wb3J0IHsgSldLLCBKV1MgfSBmcm9tICdub2RlLWpvc2UnO1xuaW1wb3J0IHsgUHJvZmlsZVNlcnZpY2UgfSBmcm9tICcuLi91c2Vycy9wcm9maWxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkvZW5jcnlwdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUdyYXBoU2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZ3JhcGguc2VydmljZSc7XG5pbXBvcnQgeyBMaWZlUmVhZHlDb25maWcsIExSX0NPTkZJRyB9IGZyb20gJy4uL2xpZmUtcmVhZHkuY29uZmlnJztcbmltcG9ydCB7IExyQXV0aEV4Y2VwdGlvbiwgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbiB9IGZyb20gJy4uL19jb21tb24vZXhjZXB0aW9ucyc7XG5pbXBvcnQgeyBMckFwb2xsb1NlcnZpY2UgfSBmcm9tICcuLy4uL2FwaS9sci1hcG9sbG8uc2VydmljZSc7XG5pbXBvcnQge1xuICBQYXNzd29yZENoYW5nZU11dGF0aW9uLFxuICBQYXNzd29yZENoYW5nZVJlcXVlc3RNdXRhdGlvbixcbiAgUGFzc3dvcmRDaGFuZ2VDb25maWdRdWVyeSxcbn0gZnJvbSAnLi9hdXRoLmdxbCc7XG5pbXBvcnQgeyBQYXNzS2V5QnVuZGxlIH0gZnJvbSAnLi9hdXRoLnR5cGVzJztcbmltcG9ydCB7IFdlYkNyeXB0b1NlcnZpY2UgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkvd2ViLWNyeXB0by5zZXJ2aWNlJztcbmltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSAnbW9tZW50JztcbmltcG9ydCAqIGFzIG1vbWVudF8gZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IEFwaUN1cnJlbnRVc2VyIH0gZnJvbSAnLi4vdXNlcnMvcHJvZmlsZS50eXBlcyc7XG5pbXBvcnQgeyBJZGxlU2VydmljZSB9IGZyb20gJy4uL2F1dGgvaWRsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIGFzIEtGUyB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZmFjdG9yeS5zZXJ2aWNlJztcblxuLy8gXCJ3aHk/XCIgeW91IGFzazogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTk3MzUyODAvYW5ndWxhci04LW1vbWVudC1lcnJvci1jYW5ub3QtY2FsbC1hLW5hbWVzcGFjZS1tb21lbnRcbmNvbnN0IG1vbWVudCA9IG1vbWVudF87XG5cbmludGVyZmFjZSBQYXNzd29yZENoYW5nZVJlcXVlc3RNdXRhdGlvbiB7XG4gIHBhc3N3b3JkQ2hhbmdlUmVxdWVzdDoge1xuICAgIGNoYWxsZW5nZToge1xuICAgICAgc2VydmVyTm9uY2U6IHN0cmluZztcbiAgICB9O1xuICB9O1xufVxuXG5pbnRlcmZhY2UgUGFzc3dvcmRDaGFuZ2VNdXRhdGlvbiB7XG4gIHBhc3N3b3JkQ2hhbmdlOiB7XG4gICAgdG9rZW46IHN0cmluZztcbiAgICBuZXdQYXNzS2V5OiB7XG4gICAgICBpZDogc3RyaW5nO1xuICAgIH07XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRDaGFuZ2VDb25maWcge1xuICBtYXhBdXRoQWdlU2Vjb25kczogbnVtYmVyO1xuICBhdXRoVGltZTogc3RyaW5nIHwgRGF0ZTtcbiAgc2VydmVyVGltZTogc3RyaW5nIHwgRGF0ZTtcbn1cblxuZXhwb3J0IGNsYXNzIFBhc3N3b3JkQ2hlY2sge1xuICBsZW5ndGg/OiBudW1iZXI7XG4gIHRpbWVUb0NyYWNrPzogRHVyYXRpb247XG4gIHBhc3N3b3JkRXhwb3NlZD86IG51bWJlcjtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFBhc3N3b3JkU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgQ0xJRU5UX05PTkNFX0xFTkdUSCA9IDMyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTFJfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogTGlmZVJlYWR5Q29uZmlnLFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBwcml2YXRlIGFwb2xsbzogTHJBcG9sbG9TZXJ2aWNlLFxuICAgIHByaXZhdGUgYXV0aDogQXV0aENsYXNzLFxuICAgIHByaXZhdGUgcHJvZmlsZVNlcnZpY2U6IFByb2ZpbGVTZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5RmFjdG9yeTogS0ZTLFxuICAgIHByaXZhdGUgZW5jcnlwdGlvblNlcnZpY2U6IEVuY3J5cHRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5R3JhcGg6IEtleUdyYXBoU2VydmljZSxcbiAgICBwcml2YXRlIHdlYkNyeXB0b1NlcnZpY2U6IFdlYkNyeXB0b1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBpZGxlU2VydmljZTogSWRsZVNlcnZpY2VcbiAgKSB7fVxuXG4gIHB1YmxpYyBhc3luYyBjaGVja1Bhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPFBhc3N3b3JkQ2hlY2s+IHtcbiAgICBjb25zdCB7IHllYXJzIH0gPSB0aGlzLnBhc3N3b3JkU3RyZW5ndGgocGFzc3dvcmQpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxlbmd0aDogcGFzc3dvcmQubGVuZ3RoLFxuICAgICAgdGltZVRvQ3JhY2s6IG1vbWVudC5kdXJhdGlvbih7IHllYXJzIH0pLFxuICAgICAgcGFzc3dvcmRFeHBvc2VkOiBhd2FpdCB0aGlzLmdldEV4cG9zdXJlQ291bnQocGFzc3dvcmQpLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0RXhwb3N1cmVDb3VudChwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBzaGExUGFzc3dvcmQgPSBhd2FpdCB0aGlzLndlYkNyeXB0b1NlcnZpY2Uuc3RyaW5nRGlnZXN0KFxuICAgICAgJ1NIQS0xJyxcbiAgICAgIHBhc3N3b3JkXG4gICAgKTtcbiAgICBjb25zdCBmaXJzdDVzaGExID0gc2hhMVBhc3N3b3JkLnN1YnN0cmluZygwLCA1KTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5odHRwXG4gICAgICAuZ2V0KGBodHRwczovL2FwaS5wd25lZHBhc3N3b3Jkcy5jb20vcmFuZ2UvJHtmaXJzdDVzaGExfWAsIHtcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgICB9KVxuICAgICAgLnRvUHJvbWlzZSgpO1xuXG4gICAgY29uc3QgcmVzdWx0cyA9IG5ldyBSZWdFeHAoXG4gICAgICBgXig/OiR7c2hhMVBhc3N3b3JkLnN1YnN0cmluZyg1KX06KSg/PGNvdW50PlxcXFxkKykkYCxcbiAgICAgICdpbSdcbiAgICApLmV4ZWMocmVzcG9uc2UpO1xuXG4gICAgaWYgKHJlc3VsdHMpIHtcbiAgICAgIHJldHVybiArcmVzdWx0cy5ncm91cHMuY291bnQ7XG4gICAgfVxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgcHVibGljIGdldFBhc3NJZHBTdHJpbmcocGFzc0lkcDogSldLLktleSkge1xuICAgIHJldHVybiAocGFzc0lkcC50b0pTT04odHJ1ZSkgYXMgYW55KS5rO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGNyZWF0ZVBhc3NLZXlCdW5kbGUocGFzc3dvcmQ6IHN0cmluZyk6IFByb21pc2U8UGFzc0tleUJ1bmRsZT4ge1xuICAgIGNvbnN0IHBhc3NJZHBQYXJhbXMgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlUGFzc0lkcFBhcmFtcygpO1xuICAgIGNvbnN0IHBhc3NJZHAgPSAoXG4gICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0lkcCh7XG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAuLi5wYXNzSWRwUGFyYW1zLFxuICAgICAgfSlcbiAgICApLmp3aztcblxuICAgIGNvbnN0IHBhc3NLZXlQYXJhbXMgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlUGFzc0tleVBhcmFtcygpO1xuICAgIGNvbnN0IHBhc3NLZXkgPSAoXG4gICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAuLi5wYXNzS2V5UGFyYW1zLFxuICAgICAgfSlcbiAgICApLmp3aztcblxuICAgIGNvbnN0IHBhc3NJZHBWZXJpZmllciA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVQa2NTaWduS2V5KCk7XG5cbiAgICBjb25zdCB3cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFxuICAgICAgcGFzc0tleSxcbiAgICAgIHBhc3NJZHBWZXJpZmllci50b0pTT04odHJ1ZSlcbiAgICApO1xuXG4gICAgLy8gVGhlcmUgYXJlIHR3byBmb3JtYXRzIHRoYXQgdGhlIHByaXZhdGUga2V5IGNhbiBiZSByZXByZXNlbnRlZCBpbiBKV0s6XG4gICAgLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzgwMTcjcGFnZS05XG4gICAgLy8gVGhlIHNlY29uZCBmb3JtIGlzIGFuIG9wdGltaXphdGlvbjpcbiAgICAvLyBodHRwczovL2NyeXB0by5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMTk0MTMvd2hhdC1hcmUtZHAtYW5kLWRxLWluLWVuY3J5cHRpb24tYnktcnNhLWluLWNcblxuICAgIHJldHVybiB7XG4gICAgICBwYXNzS2V5UGFyYW1zLFxuICAgICAgcGFzc0tleSxcbiAgICAgIHBhc3NJZHBQYXJhbXMsXG4gICAgICBwYXNzSWRwLFxuICAgICAgcGFzc0lkcFZlcmlmaWVyLFxuICAgICAgd3JhcHBlZFBhc3NJZHBWZXJpZmllclByayxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdlIG5lZWQgdG8gYWxsb3cgZm9yIGludGVycnVwdGlvbiBvZiB0aGUgcHJvY2VzcyBhdCBhbnkgcG9pbnQuIEVhY2ggQVBJIGNhbGwgY2FuIGJlIGNvbnNpZGVyZWRcbiAgICogYXRvbWljIGFuZCBlaXRoZXIgc3VjY2VlZHMgb3IgZmFpbHMuXG4gICAqXG4gICAqIFRoZSBMUiBzZXJ2ZXIgQVBJcyB1c2Ugc2VtYXBob3JlIHRva2VucyBmb3IgbG9ja2luZyBjcml0aWNhbCBvcGVyYXRpb25zLCBzbyBjb25jdXJyZW50IGNhbGxzIHdpbGxcbiAgICogZmFpbC5cbiAgICpcbiAgICogV2UgYXNzdW1lIHRoZSB3b3JzdCBjYXNlIGZvciBJZFAgQVBJIGNhbGxzLiBTbyB3ZSB1c2UgdGhlIHNlbWFwaG9yZSB0b2tlbiBmcm9tIExSIHRvIHByZXZlbnRcbiAgICogY29uY3VycmVudCBjYWxscyB0byBJZFAgQVBJcywgYnV0IHdlIGhhdmUgdG8gYXNzdW1lIHRoYXQgdGhlIElkUCBBUEkgY2FsbHMgd2lsbCBlaXRoZXIgc3VjY2VlZCBvclxuICAgKiBmYWlsIHdpdGhpbiBhIHJlYXNvbmFibGUgYW1vdW50IG9mIHRpbWUuXG4gICAqXG4gICAqIEVhY2ggbG9jYXRpb24gd2hlcmUgdGhlIHNlcnZlciBzdGF0ZSBjaGFuZ2VzIGNhbiBiZSBhIHBvdGVudGlhbCBwb2ludCBvZiBpbnRlcnJ1cHRpb24uXG4gICAqIFBvdGVudGlhbCBwb2ludHMgb2YgaW50ZXJydXB0aW9uIGFyZSBtYXJrZWQgd2l0aDogLS1Qb3RlbnRpYWwgRmFpbHVyZSBQb2ludC0tXG4gICAqXG4gICAqIFBsYWNlcyBmb3IgdGltZW91dDpcbiAgICogLSBMb2dpbiBhZ2UgdG9vIG9sZCBhdCBjYWxsIHRvOiB2ZXJpZnlQYXNzd29yZCgpXG4gICAqIC0gTG9naW4gYWdlIHRvbyBvbGQgYXQgY2FsbCB0bzogY2hhbmdlUGFzc3dvcmRNdXRhdGlvbigpXG4gICAqIC0gU2VtYXBob3JlIHRva2VuIGV4cGlyZXMgYXQgY2FsbCB0bzogY2hhbmdlUGFzc3dvcmRDb21wbGV0ZSgpXG4gICAqXG4gICAqIFRlc3RzOlxuICAgKiAtIFBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDE6IHNob3VsZCBiZSBhYmxlIHRvIHJlc3RhcnQgdGhlIHByb2Nlc3MsIHVzZXIgcmVtYWlucyBzaWduZWQgaW4uXG4gICAqIC0gUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMjogc2hvdWxkIGVudGVyIHJlY292ZXJ5IGZsb3dcbiAgICogLSBQb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAzOiBzaG91bGQgZW50ZXIgcmVjb3ZlcnkgZmxvd1xuICAgKiAtIFBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDQ6IHNob3VsZCBlbnRlciByZWNvdmVyeSBmbG93XG4gICAqXG4gICAqL1xuXG4gIHB1YmxpYyBhc3luYyBpc0xvZ2luUmVxdWlyZWQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgY2hhbmdlUGFzc3dvcmRDb25maWcgPSBhd2FpdCB0aGlzLmdldENoYW5nZVBhc3N3b3JkQ29uZmlnKCk7XG4gICAgY29uc3QgYXV0aFRpbWUgPSBtb21lbnQoY2hhbmdlUGFzc3dvcmRDb25maWcuYXV0aFRpbWUpO1xuICAgIGNvbnN0IHNlcnZlclRpbWUgPSBtb21lbnQoY2hhbmdlUGFzc3dvcmRDb25maWcuc2VydmVyVGltZSk7XG4gICAgY29uc3QgZHVyYXRpb24gPSBtb21lbnQuZHVyYXRpb24oc2VydmVyVGltZS5kaWZmKGF1dGhUaW1lKSk7XG4gICAgY29uc3Qgc2Vjb25kcyA9IGR1cmF0aW9uLmFzU2Vjb25kcygpO1xuICAgIGlmIChzZWNvbmRzID4gY2hhbmdlUGFzc3dvcmRDb25maWcubWF4QXV0aEFnZVNlY29uZHMpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGNoYW5nZVBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcsIG5ld1Bhc3N3b3JkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG5cbiAgICAvLyBWYWxpZGF0aW9uXG4gICAgLy8gdG9kbzogQWRkIHRoaXMgYmFjayBpblxuICAgIC8vIE5vdGUgdGhlIHBhc3NJZHAgd2lsbCBhbHdheXMgaGF2ZSBhIHJhbmRvbSBzYWx0LCBzbyB3aWxsIGFsd2F5cyBiZSBkaWZmZXJlbnQgdG8gdGhlIGN1cnJlbnQgcGFzc0lkcC5cbiAgICBpZiAocGFzc3dvcmQgPT09IG5ld1Bhc3N3b3JkKSB7XG4gICAgICB0aHJvdyBuZXcgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbihcbiAgICAgICAgJ05ldyBwYXNzd29yZCBpcyB0aGUgc2FtZSBhcyB0aGUgY3VycmVudCBvbmUuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGN1cnJlbnRVc2VyIH0gPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldEN1cnJlbnRVc2VyKCk7XG5cbiAgICBjb25zdCB7IHBhc3NJZHAsIHNpZ25lZENoYWxsZW5nZSB9ID0gYXdhaXQgdGhpcy52ZXJpZnlQYXNzd29yZChcbiAgICAgIHBhc3N3b3JkLFxuICAgICAgY3VycmVudFVzZXJcbiAgICApO1xuXG4gICAgLy8gLS1Qb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAxLS1cbiAgICAvLyB2ZXJpZnlQYXNzd29yZCgpIGFza3MgZm9yIGEgY3VycmVudCBwYXNzd29yZCBjaGFsbGVuZ2UgaGVuY2UgY2hhbmdlcyBzZXJ2ZXIgc3RhdGUuXG4gICAgLy8gUGxhY2UgYnJlYWsgcG9pbnRzIGhlcmUgdG8gdGVzdCB0aGUgZmFpbHVyZSBzY2VuYXJpb3MuXG5cbiAgICAvLyBHZW5lcmF0ZSB0aGUgbmV3IHBhc3NJZHBcbiAgICBjb25zdCBuZXdQYXNzS2V5ID0gYXdhaXQgdGhpcy5jcmVhdGVQYXNzS2V5QnVuZGxlKG5ld1Bhc3N3b3JkKTtcblxuICAgIC8vIFJlLWVuY3J5cHQgbWFzdGVyIGtleSB3aXRoIG5ldyBrZXlcbiAgICBjb25zdCBtYXN0ZXJLZXkgPSBhd2FpdCB0aGlzLmtleUdyYXBoLmdldEtleShcbiAgICAgIGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5Lm1hc3RlcktleS5pZFxuICAgICk7XG4gICAgY29uc3QgbmV3V3JhcHBlZE1hc3RlcktleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcbiAgICAgIG5ld1Bhc3NLZXkucGFzc0tleSxcbiAgICAgIG1hc3RlcktleS5qd2sudG9KU09OKHRydWUpXG4gICAgKTtcblxuICAgIC8vIElmIHRoZSBJZFAgY2hhbmdlIHBhc3N3b3JkIGZhaWxlZCwgd2UgbmVlZCB0byBnbyBpbnRvIHJlY292ZXJ5IG1vZGUgYnkgZm9yY2luZ1xuICAgIC8vIGEgbG9naW4uIFdlIGNhbid0IGxvZ291dCB0aGUgdXNlciBqdXN0IHlldCBzaW5jZSB0aGUgSWRQIHBhc3N3b3JkIGNoYW5nZSBuZWVkc1xuICAgIC8vIHRoZSB1c2VyIHRvIGJlIGxvZ2dlZCBpbi4gV2UgX2Nhbl8gcmVtb3ZlZCBhbnkgcGVyc2lzdGVkIHNlc3Npb24gdmFsdWVzIGZvciB0aGUgSWRQXG4gICAgLy8gYnV0IHRoYXQgc2VlbXMgbGlrZSB0b28gbXVjaCB0cm91YmxlLlxuXG4gICAgY29uc3QgeyB0b2tlbiwgbmV3UGFzc0tleUlkIH0gPSBhd2FpdCB0aGlzLmNoYW5nZVBhc3N3b3JkTXV0YXRpb24oXG4gICAgICBzaWduZWRDaGFsbGVuZ2UsXG4gICAgICBjdXJyZW50VXNlci5jdXJyZW50VXNlcktleS5tYXN0ZXJLZXkuaWQsXG4gICAgICBuZXdXcmFwcGVkTWFzdGVyS2V5LFxuICAgICAgbmV3UGFzc0tleVxuICAgICk7XG5cbiAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDItLVxuICAgIC8vIGNoYW5nZVBhc3N3b3JkTXV0YXRpb24oKSB1cGxvYWRzIG5ldyBrZXlzIGFuZCBvYnRhaW5zIGEgc2VtYXBob3JlIGxvY2sgdG8gcHJldmVudCBhbnkgb3RoZXJcbiAgICAvLyBjbGllbnRzIGZyb20gcGVyZm9ybWluZyBJZFAgcGFzc3dvcmQgY2hhbmdlLlxuXG4gICAgLy8gTm93IHdlIGNhbiBkbyB0aGUgSWRQIHBhc3N3b3JkIGNoYW5nZS5cbiAgICAvLyB0b2RvOiBBZGQgdGhpcyBiYWNrIGluXG4gICAgYXdhaXQgdGhpcy5hdXRoLmNoYW5nZVBhc3N3b3JkKFxuICAgICAgY29nbml0b1VzZXIsXG4gICAgICB0aGlzLmdldFBhc3NJZHBTdHJpbmcocGFzc0lkcCksXG4gICAgICB0aGlzLmdldFBhc3NJZHBTdHJpbmcobmV3UGFzc0tleS5wYXNzSWRwKVxuICAgICk7XG5cbiAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDMtLVxuICAgIC8vIElkUCBwYXNzd29yZCBjaGFuZ2VcblxuICAgIC8vIE5vdGUgdGhhdCBjaGFuZ2VQYXNzd29yZCgpIGNvdWxkIHRocm93IGFuIGV4Y2VwdGlvbiBmb3IgYSBudW1iZXIgb2YgcmVhc29uLiBJdCBjb3VsZCB0aHJvd1xuICAgIC8vIGEgbmV0d29yayB0aW1lb3V0IGZvciBleGFtcGxlLiBCdXQgd2UgZG9uJ3Qga25vdyBpZiBpdCdzIHRoZSByZXNwb25zZSB0aGF0IHRpbWVkIG91dCBhbmRcbiAgICAvLyB0aGUgaWRwIHBhc3N3b3JkIGNoYW5nZSB3YXMgYWN0dWFsbHkgY2FycmllZCBvdXQuIFNvIHdlIGhhdmUgdG8gYmUgZXh0cmEgY29uc2VydmF0aXZlIGFuZFxuICAgIC8vIG9ubHkgYWN0IG9uIGEgY2xlYXIgc3VjY2Vzcy4gT3RoZXJ3aXNlIHdlIGdvIGludG8gcmVjb3ZlciBtb2RlLlxuICAgIGF3YWl0IHRoaXMuY2hhbmdlUGFzc3dvcmRDb21wbGV0ZShcbiAgICAgIGNvZ25pdG9Vc2VyLmdldFNpZ25JblVzZXJTZXNzaW9uKCkuZ2V0QWNjZXNzVG9rZW4oKS5nZXRKd3RUb2tlbigpLFxuICAgICAgdHJ1ZSxcbiAgICAgIHRva2VuXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjaGFuZ2VQYXNzd29yZENvbXBsZXRlKFxuICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmcsXG4gICAgdXNlTmV3UGFzc3dvcmQ6IGJvb2xlYW4sXG4gICAgdG9rZW46IHN0cmluZyA9IG51bGxcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5odHRwXG4gICAgICAucG9zdChcbiAgICAgICAgYCR7dGhpcy5jb25maWcuYXV0aFVybH11c2Vycy9wYXNzd29yZC1jaGFuZ2UtY29tcGxldGUvYCxcbiAgICAgICAge1xuICAgICAgICAgIHVzZV9uZXdfcGFzc3dvcmQ6IHVzZU5ld1Bhc3N3b3JkLFxuICAgICAgICAgIC4uLih0b2tlbiAmJiB7IHRva2VuIH0pLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2FjY2Vzc1Rva2VufWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgKVxuICAgICAgLnRvUHJvbWlzZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRWZXJpZmllclBySyhcbiAgICBwYXNzS2V5OiBKV0suS2V5LFxuICAgIHdyYXBwZWRQcks6IG9iamVjdFxuICApOiBQcm9taXNlPEpXSy5LZXk+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcHJrSnNvbiA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChwYXNzS2V5LCB3cmFwcGVkUHJLKTtcbiAgICAgIHJldHVybiBLRlMuYXNLZXkocHJrSnNvbik7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBMckF1dGhFeGNlcHRpb24oJ1dyb25nIGN1cnJlbnQgcGFzc3dvcmQnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHZlcmlmeVBhc3N3b3JkKFxuICAgIHBhc3N3b3JkOiBzdHJpbmcsXG4gICAgY3VycmVudFVzZXI6IEFwaUN1cnJlbnRVc2VyXG4gICk6IFByb21pc2U8eyBwYXNzSWRwOiBKV0suS2V5OyBzaWduZWRDaGFsbGVuZ2U6IEpXUy5DcmVhdGVTaWduUmVzdWx0IH0+IHtcbiAgICAvLyBHZXQgaW5mb3JtYXRpb24gZnJvbSB0aGUgc2VydmVyIHRvIHByZXBhcmUgZm9yIHBhc3N3b3JkIGNoYW5nZS5cbiAgICBjb25zdCBwYXNzd29yZFJlcXVlc3QgPSBhd2FpdCB0aGlzLmFwb2xsby5tdXRhdGU8UGFzc3dvcmRDaGFuZ2VSZXF1ZXN0TXV0YXRpb24+KFxuICAgICAge1xuICAgICAgICBtdXRhdGlvbjogUGFzc3dvcmRDaGFuZ2VSZXF1ZXN0TXV0YXRpb24sXG4gICAgICAgIHZhcmlhYmxlczoge30sXG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIEdldCB0aGUgb2xkIHBhc3NLZXkgc28gd2UgY2FuIGRlY3J5cHQgdGhlIG9sZCBwYXNzd29yZCB2ZXJpZmllclxuICAgIGNvbnN0IHBhc3NLZXlSZXN1bHQgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XG4gICAgICBwYXNzd29yZCxcbiAgICAgIC4uLmN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkucGFzc0tleVBhcmFtcyxcbiAgICB9KTtcblxuICAgIGNvbnN0IHZlcmlmaWVyUHJLID0gYXdhaXQgdGhpcy5nZXRWZXJpZmllclBySyhcbiAgICAgIHBhc3NLZXlSZXN1bHQuandrLFxuICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS53cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrXG4gICAgKTtcblxuICAgIC8vIFNpZ24gdGhlIHNlcnZlciBjaGFsbGVuZ2UgdG8gcHJvdmUgdG8gdGhlIHNlcnZlciB3ZSBjYW4gZGVjcnlwdCB0aGUgcGFzc3dvcmQgdmVyaWZpZXIuXG4gICAgLy8gR2VuZXJhdGVcbiAgICBjb25zdCBjbGllbnROb25jZSA9IHRoaXMua2V5RmFjdG9yeS5yYW5kb21TdHJpbmcodGhpcy5DTElFTlRfTk9OQ0VfTEVOR1RIKTtcblxuICAgIGNvbnN0IHNpZ25lZENoYWxsZW5nZSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2Uuc2lnbih2ZXJpZmllclBySywge1xuICAgICAgc2VydmVyTm9uY2U6IHBhc3N3b3JkUmVxdWVzdC5wYXNzd29yZENoYW5nZVJlcXVlc3QuY2hhbGxlbmdlLnNlcnZlck5vbmNlLFxuICAgICAgY2xpZW50Tm9uY2UsXG4gICAgfSk7XG5cbiAgICBjb25zdCBwYXNzSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NJZHAoe1xuICAgICAgcGFzc3dvcmQsXG4gICAgICAuLi5jdXJyZW50VXNlci5jdXJyZW50VXNlcktleS5wYXNzS2V5LnBhc3NJZHBQYXJhbXMsXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFzc0lkcDogcGFzc0lkcFJlc3VsdC5qd2ssXG4gICAgICBzaWduZWRDaGFsbGVuZ2UsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hhbmdlUGFzc3dvcmRNdXRhdGlvbihcbiAgICBzaWduZWRDaGFsbGVuZ2U6IEpXUy5DcmVhdGVTaWduUmVzdWx0LFxuICAgIG1hc3RlcktleUlkOiBzdHJpbmcsXG4gICAgbmV3V3JhcHBlZE1hc3RlcktleTogb2JqZWN0LFxuICAgIHBhc3NLZXlCdW5kbGU6IFBhc3NLZXlCdW5kbGVcbiAgKTogUHJvbWlzZTx7IHRva2VuOiBzdHJpbmc7IG5ld1Bhc3NLZXlJZDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuYXBvbGxvLm11dGF0ZTxQYXNzd29yZENoYW5nZU11dGF0aW9uPih7XG4gICAgICBtdXRhdGlvbjogUGFzc3dvcmRDaGFuZ2VNdXRhdGlvbixcbiAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICBpbnB1dDoge1xuICAgICAgICAgIHNpZ25lZENoYWxsZW5nZTogSlNPTi5zdHJpbmdpZnkoc2lnbmVkQ2hhbGxlbmdlKSxcbiAgICAgICAgICBtYXN0ZXJLZXlJZCxcbiAgICAgICAgICBuZXdXcmFwcGVkTWFzdGVyS2V5OiBKU09OLnN0cmluZ2lmeShuZXdXcmFwcGVkTWFzdGVyS2V5KSxcbiAgICAgICAgICBuZXdQYXNzS2V5OiB7XG4gICAgICAgICAgICBwYXNzSWRwUGFyYW1zOiBKU09OLnN0cmluZ2lmeShwYXNzS2V5QnVuZGxlLnBhc3NJZHBQYXJhbXMpLFxuICAgICAgICAgICAgcGFzc0lkcFZlcmlmaWVyUGJrOiBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgcGFzc0tleUJ1bmRsZS5wYXNzSWRwVmVyaWZpZXIudG9KU09OKClcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB3cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrOiBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgcGFzc0tleUJ1bmRsZS53cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgcGFzc0tleVBhcmFtczogSlNPTi5zdHJpbmdpZnkocGFzc0tleUJ1bmRsZS5wYXNzS2V5UGFyYW1zKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgdG9rZW46IHJlc3BvbnNlLnBhc3N3b3JkQ2hhbmdlLnRva2VuLFxuICAgICAgbmV3UGFzc0tleUlkOiByZXNwb25zZS5wYXNzd29yZENoYW5nZS5uZXdQYXNzS2V5LmlkLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBnZXRDaGFuZ2VQYXNzd29yZENvbmZpZygpOiBQcm9taXNlPFBhc3N3b3JkQ2hhbmdlQ29uZmlnPiB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5hcG9sbG8ucXVlcnk8YW55Pih7XG4gICAgICBxdWVyeTogUGFzc3dvcmRDaGFuZ2VDb25maWdRdWVyeSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJldCA9IHJlcy5wYXNzd29yZENoYW5nZUNvbmZpZyBhcyBQYXNzd29yZENoYW5nZUNvbmZpZztcblxuICAgIHJldC5hdXRoVGltZSA9IG5ldyBEYXRlKHJldC5hdXRoVGltZSk7XG4gICAgcmV0LnNlcnZlclRpbWUgPSBuZXcgRGF0ZShyZXQuc2VydmVyVGltZSk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHB1YmxpYyBwYXNzd29yZFN0cmVuZ3RoKHBhc3N3b3JkKTogeyB5ZWFyczogbnVtYmVyOyBiaXRzOiBudW1iZXIgfSB7XG4gICAgY29uc3QgdXBwZXIgPSAvW0EtWl0vZztcbiAgICBjb25zdCBsb3dlciA9IC9bYS16XS9nO1xuICAgIGNvbnN0IGRpZ2l0ID0gL1swLTldL2c7XG5cbiAgICBjb25zdCB1cHBlckNob2ljZXMgPSAyNjtcbiAgICBjb25zdCBsb3dlckNob2ljZXMgPSAyNjtcbiAgICBjb25zdCBkaWdpdENob2ljZXMgPSAxMDtcbiAgICBjb25zdCBzcGVjaWFsQ2hvaWNlcyA9IDMwOyAvLyAvWyFcIiMkJSYnKCkqKywtLi86Ozw9Pj9AW1xcXV5fYHt8fX5dL2dcblxuICAgIGZ1bmN0aW9uIGluc3RhbmNlQ291bnQoc3RyLCByZSkge1xuICAgICAgcmV0dXJuICgoc3RyIHx8ICcnKS5tYXRjaChyZSkgfHwgW10pLmxlbmd0aDtcbiAgICB9XG5cbiAgICBjb25zdCB1cHBlcnMgPSBpbnN0YW5jZUNvdW50KHBhc3N3b3JkLCB1cHBlcik7XG4gICAgY29uc3QgbG93ZXJzID0gaW5zdGFuY2VDb3VudChwYXNzd29yZCwgbG93ZXIpO1xuICAgIGNvbnN0IGRpZ2l0cyA9IGluc3RhbmNlQ291bnQocGFzc3dvcmQsIGRpZ2l0KTtcbiAgICBjb25zdCBzcGVjaWFscyA9IHBhc3N3b3JkLmxlbmd0aCAtIHVwcGVycyAtIGxvd2VycyAtIGRpZ2l0cztcblxuICAgIGxldCBjaG9pY2VzID0gMDtcbiAgICBpZiAodXBwZXJzKSB7XG4gICAgICBjaG9pY2VzICs9IHVwcGVyQ2hvaWNlcztcbiAgICB9XG4gICAgaWYgKGxvd2Vycykge1xuICAgICAgY2hvaWNlcyArPSBsb3dlckNob2ljZXM7XG4gICAgfVxuICAgIGlmIChkaWdpdHMpIHtcbiAgICAgIGNob2ljZXMgKz0gZGlnaXRDaG9pY2VzO1xuICAgIH1cbiAgICBpZiAoc3BlY2lhbHMpIHtcbiAgICAgIGNob2ljZXMgKz0gc3BlY2lhbENob2ljZXM7XG4gICAgfVxuXG4gICAgaWYgKHBhc3N3b3JkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeWVhcnM6IDAsXG4gICAgICAgIC8vIGJpdHMgb2YgZW50cm9weVxuICAgICAgICBiaXRzOiAwLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwZXJtdXRhdGlvbnMgPSBNYXRoLnBvdyhjaG9pY2VzLCBwYXNzd29yZC5sZW5ndGgpO1xuXG4gICAgY29uc3QgeWVhcnMgPVxuICAgICAgKDU0MDAwICogcGVybXV0YXRpb25zKSAvXG4gICAgICBNYXRoLnBvdyh1cHBlckNob2ljZXMgKyBsb3dlckNob2ljZXMgKyBkaWdpdENob2ljZXMsIDEyKTtcbiAgICByZXR1cm4ge1xuICAgICAgeWVhcnMsXG4gICAgICAvLyBiaXRzIG9mIGVudHJvcHlcbiAgICAgIGJpdHM6IE1hdGgucm91bmQoTWF0aC5sb2cyKHBlcm11dGF0aW9ucykpLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==
1
+ import { __awaiter } from "tslib";
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Inject, Injectable } from '@angular/core';
4
+ import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
5
+ import { ProfileService } from '../users/profile.service';
6
+ import { EncryptionService } from '../cryptography/encryption.service';
7
+ import { KeyGraphService } from '../cryptography/key-graph.service';
8
+ import { LR_CONFIG } from '../life-ready.config';
9
+ import { LrAuthException, LrBadArgumentException } from '../_common/exceptions';
10
+ import { LrApolloService } from './../api/lr-apollo.service';
11
+ import { PasswordChangeMutation, PasswordChangeRequestMutation, PasswordChangeConfigQuery, } from './auth.gql';
12
+ import { WebCryptoService } from '../cryptography/web-crypto.service';
13
+ import * as moment_ from 'moment';
14
+ import { IdleService } from '../auth/idle.service';
15
+ import { KeyFactoryService as KFS } from '../cryptography/key-factory.service';
16
+ import * as i0 from "@angular/core";
17
+ import * as i1 from "../life-ready.config";
18
+ import * as i2 from "@angular/common/http";
19
+ import * as i3 from "../api/lr-apollo.service";
20
+ import * as i4 from "@aws-amplify/auth/lib-esm/Auth";
21
+ import * as i5 from "../users/profile.service";
22
+ import * as i6 from "../cryptography/key-factory.service";
23
+ import * as i7 from "../cryptography/encryption.service";
24
+ import * as i8 from "../cryptography/key-graph.service";
25
+ import * as i9 from "../cryptography/web-crypto.service";
26
+ import * as i10 from "./idle.service";
27
+ // "why?" you ask: https://stackoverflow.com/questions/59735280/angular-8-moment-error-cannot-call-a-namespace-moment
28
+ const moment = moment_;
29
+ export class PasswordCheck {
30
+ }
31
+ export class PasswordService {
32
+ constructor(config, http, apollo, auth, profileService, keyFactory, encryptionService, keyGraph, webCryptoService, idleService) {
33
+ this.config = config;
34
+ this.http = http;
35
+ this.apollo = apollo;
36
+ this.auth = auth;
37
+ this.profileService = profileService;
38
+ this.keyFactory = keyFactory;
39
+ this.encryptionService = encryptionService;
40
+ this.keyGraph = keyGraph;
41
+ this.webCryptoService = webCryptoService;
42
+ this.idleService = idleService;
43
+ this.CLIENT_NONCE_LENGTH = 32;
44
+ }
45
+ checkPassword(password) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const { years } = this.passwordStrength(password);
48
+ return {
49
+ length: password.length,
50
+ timeToCrack: moment.duration({ years }),
51
+ passwordExposed: yield this.getExposureCount(password),
52
+ };
53
+ });
54
+ }
55
+ getExposureCount(password) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const sha1Password = yield this.webCryptoService.stringDigest('SHA-1', password);
58
+ const first5sha1 = sha1Password.substring(0, 5);
59
+ const response = yield this.http
60
+ .get(`https://api.pwnedpasswords.com/range/${first5sha1}`, {
61
+ responseType: 'text',
62
+ })
63
+ .toPromise();
64
+ const results = new RegExp(`^(?:${sha1Password.substring(5)}:)(?<count>\\d+)$`, 'im').exec(response);
65
+ if (results) {
66
+ return +results.groups.count;
67
+ }
68
+ return 0;
69
+ });
70
+ }
71
+ getPassIdpString(passIdp) {
72
+ return passIdp.toJSON(true).k;
73
+ }
74
+ createPassKeyBundle(password) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ const passIdpParams = yield this.keyFactory.createPassIdpParams();
77
+ const passIdp = (yield this.keyFactory.derivePassIdp(Object.assign({ password }, passIdpParams))).jwk;
78
+ const passKeyParams = yield this.keyFactory.createPassKeyParams();
79
+ const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, passKeyParams))).jwk;
80
+ const passIdpVerifier = yield this.keyFactory.createPkcSignKey();
81
+ const wrappedPassIdpVerifierPrk = yield this.encryptionService.encrypt(passKey, passIdpVerifier.toJSON(true));
82
+ // There are two formats that the private key can be represented in JWK:
83
+ // https://tools.ietf.org/html/rfc8017#page-9
84
+ // The second form is an optimization:
85
+ // https://crypto.stackexchange.com/questions/19413/what-are-dp-and-dq-in-encryption-by-rsa-in-c
86
+ return {
87
+ passKeyParams,
88
+ passKey,
89
+ passIdpParams,
90
+ passIdp,
91
+ passIdpVerifier,
92
+ wrappedPassIdpVerifierPrk,
93
+ };
94
+ });
95
+ }
96
+ /**
97
+ * We need to allow for interruption of the process at any point. Each API call can be considered
98
+ * atomic and either succeeds or fails.
99
+ *
100
+ * The LR server APIs use semaphore tokens for locking critical operations, so concurrent calls will
101
+ * fail.
102
+ *
103
+ * We assume the worst case for IdP API calls. So we use the semaphore token from LR to prevent
104
+ * concurrent calls to IdP APIs, but we have to assume that the IdP API calls will either succeed or
105
+ * fail within a reasonable amount of time.
106
+ *
107
+ * Each location where the server state changes can be a potential point of interruption.
108
+ * Potential points of interruption are marked with: --Potential Failure Point--
109
+ *
110
+ * Places for timeout:
111
+ * - Login age too old at call to: verifyPassword()
112
+ * - Login age too old at call to: changePasswordMutation()
113
+ * - Semaphore token expires at call to: changePasswordComplete()
114
+ *
115
+ * Tests:
116
+ * - Potential Failure Point 1: should be able to restart the process, user remains signed in.
117
+ * - Potential Failure Point 2: should enter recovery flow
118
+ * - Potential Failure Point 3: should enter recovery flow
119
+ * - Potential Failure Point 4: should enter recovery flow
120
+ *
121
+ */
122
+ isLoginRequired() {
123
+ return __awaiter(this, void 0, void 0, function* () {
124
+ const changePasswordConfig = yield this.getChangePasswordConfig();
125
+ const authTime = moment(changePasswordConfig.authTime);
126
+ const serverTime = moment(changePasswordConfig.serverTime);
127
+ const duration = moment.duration(serverTime.diff(authTime));
128
+ const seconds = duration.asSeconds();
129
+ if (seconds > changePasswordConfig.maxAuthAgeSeconds) {
130
+ return true;
131
+ }
132
+ else {
133
+ return false;
134
+ }
135
+ });
136
+ }
137
+ changePassword(password, newPassword) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const cognitoUser = yield this.auth.currentAuthenticatedUser();
140
+ // Validation
141
+ // todo: Add this back in
142
+ // Note the passIdp will always have a random salt, so will always be different to the current passIdp.
143
+ if (password === newPassword) {
144
+ throw new LrBadArgumentException('New password is the same as the current one.');
145
+ }
146
+ const { currentUser } = yield this.profileService.getCurrentUser();
147
+ const { passIdp, signedChallenge } = yield this.verifyPassword(password, currentUser);
148
+ // --Potential Failure Point 1--
149
+ // verifyPassword() asks for a current password challenge hence changes server state.
150
+ // Place break points here to test the failure scenarios.
151
+ // Generate the new passIdp
152
+ const newPassKey = yield this.createPassKeyBundle(newPassword);
153
+ // Re-encrypt master key with new key
154
+ const masterKey = yield this.keyGraph.getKey(currentUser.currentUserKey.masterKey.id);
155
+ const newWrappedMasterKey = yield this.encryptionService.encrypt(newPassKey.passKey, masterKey.jwk.toJSON(true));
156
+ // If the IdP change password failed, we need to go into recovery mode by forcing
157
+ // a login. We can't logout the user just yet since the IdP password change needs
158
+ // the user to be logged in. We _can_ removed any persisted session values for the IdP
159
+ // but that seems like too much trouble.
160
+ const { token, newPassKeyId } = yield this.changePasswordMutation(signedChallenge, currentUser.currentUserKey.masterKey.id, newWrappedMasterKey, newPassKey);
161
+ // --Potential Failure Point 2--
162
+ // changePasswordMutation() uploads new keys and obtains a semaphore lock to prevent any other
163
+ // clients from performing IdP password change.
164
+ // Now we can do the IdP password change.
165
+ // todo: Add this back in
166
+ yield this.auth.changePassword(cognitoUser, this.getPassIdpString(passIdp), this.getPassIdpString(newPassKey.passIdp));
167
+ // --Potential Failure Point 3--
168
+ // IdP password change
169
+ // Note that changePassword() could throw an exception for a number of reason. It could throw
170
+ // a network timeout for example. But we don't know if it's the response that timed out and
171
+ // the idp password change was actually carried out. So we have to be extra conservative and
172
+ // only act on a clear success. Otherwise we go into recover mode.
173
+ yield this.changePasswordComplete(cognitoUser.getSignInUserSession().getAccessToken().getJwtToken(), true, token);
174
+ });
175
+ }
176
+ changePasswordComplete(accessToken, useNewPassword, token = null) {
177
+ return __awaiter(this, void 0, void 0, function* () {
178
+ return this.http
179
+ .post(`${this.config.authUrl}users/password-change-complete/`, Object.assign({ use_new_password: useNewPassword }, (token && { token })), {
180
+ headers: {
181
+ Authorization: `Bearer ${accessToken}`,
182
+ },
183
+ })
184
+ .toPromise();
185
+ });
186
+ }
187
+ getVerifierPrK(passKey, wrappedPrK) {
188
+ return __awaiter(this, void 0, void 0, function* () {
189
+ try {
190
+ const prkJson = yield this.encryptionService.decrypt(passKey, wrappedPrK);
191
+ return KFS.asKey(prkJson);
192
+ }
193
+ catch (error) {
194
+ throw new LrAuthException('Wrong current password');
195
+ }
196
+ });
197
+ }
198
+ verifyPassword(password, currentUser) {
199
+ return __awaiter(this, void 0, void 0, function* () {
200
+ // Get information from the server to prepare for password change.
201
+ const passwordRequest = yield this.apollo.mutate({
202
+ mutation: PasswordChangeRequestMutation,
203
+ variables: {},
204
+ });
205
+ // Get the old passKey so we can decrypt the old password verifier
206
+ const passKeyResult = yield this.keyFactory.derivePassKey(Object.assign({ password }, currentUser.currentUserKey.passKey.passKeyParams));
207
+ const verifierPrK = yield this.getVerifierPrK(passKeyResult.jwk, currentUser.currentUserKey.passKey.wrappedPassIdpVerifierPrk);
208
+ // Sign the server challenge to prove to the server we can decrypt the password verifier.
209
+ // Generate
210
+ const clientNonce = this.keyFactory.randomString(this.CLIENT_NONCE_LENGTH);
211
+ const signedChallenge = yield this.encryptionService.sign(verifierPrK, {
212
+ serverNonce: passwordRequest.passwordChangeRequest.challenge.serverNonce,
213
+ clientNonce,
214
+ });
215
+ const passIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password }, currentUser.currentUserKey.passKey.passIdpParams));
216
+ return {
217
+ passIdp: passIdpResult.jwk,
218
+ signedChallenge,
219
+ };
220
+ });
221
+ }
222
+ changePasswordMutation(signedChallenge, masterKeyId, newWrappedMasterKey, passKeyBundle) {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ const response = yield this.apollo.mutate({
225
+ mutation: PasswordChangeMutation,
226
+ variables: {
227
+ input: {
228
+ signedChallenge: JSON.stringify(signedChallenge),
229
+ masterKeyId,
230
+ newWrappedMasterKey: JSON.stringify(newWrappedMasterKey),
231
+ newPassKey: {
232
+ passIdpParams: JSON.stringify(passKeyBundle.passIdpParams),
233
+ passIdpVerifierPbk: JSON.stringify(passKeyBundle.passIdpVerifier.toJSON()),
234
+ wrappedPassIdpVerifierPrk: JSON.stringify(passKeyBundle.wrappedPassIdpVerifierPrk),
235
+ passKeyParams: JSON.stringify(passKeyBundle.passKeyParams),
236
+ },
237
+ },
238
+ },
239
+ });
240
+ return {
241
+ token: response.passwordChange.token,
242
+ newPassKeyId: response.passwordChange.newPassKey.id,
243
+ };
244
+ });
245
+ }
246
+ getChangePasswordConfig() {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ const res = yield this.apollo.query({
249
+ query: PasswordChangeConfigQuery,
250
+ });
251
+ const ret = res.passwordChangeConfig;
252
+ ret.authTime = new Date(ret.authTime);
253
+ ret.serverTime = new Date(ret.serverTime);
254
+ return ret;
255
+ });
256
+ }
257
+ passwordStrength(password) {
258
+ const upper = /[A-Z]/g;
259
+ const lower = /[a-z]/g;
260
+ const digit = /[0-9]/g;
261
+ const upperChoices = 26;
262
+ const lowerChoices = 26;
263
+ const digitChoices = 10;
264
+ const specialChoices = 30; // /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g
265
+ function instanceCount(str, re) {
266
+ return ((str || '').match(re) || []).length;
267
+ }
268
+ const uppers = instanceCount(password, upper);
269
+ const lowers = instanceCount(password, lower);
270
+ const digits = instanceCount(password, digit);
271
+ const specials = password.length - uppers - lowers - digits;
272
+ let choices = 0;
273
+ if (uppers) {
274
+ choices += upperChoices;
275
+ }
276
+ if (lowers) {
277
+ choices += lowerChoices;
278
+ }
279
+ if (digits) {
280
+ choices += digitChoices;
281
+ }
282
+ if (specials) {
283
+ choices += specialChoices;
284
+ }
285
+ if (password.length === 0) {
286
+ return {
287
+ years: 0,
288
+ // bits of entropy
289
+ bits: 0,
290
+ };
291
+ }
292
+ const permutations = Math.pow(choices, password.length);
293
+ const years = (54000 * permutations) /
294
+ Math.pow(upperChoices + lowerChoices + digitChoices, 12);
295
+ return {
296
+ years,
297
+ // bits of entropy
298
+ bits: Math.round(Math.log2(permutations)),
299
+ };
300
+ }
301
+ }
302
+ PasswordService.ɵprov = i0.ɵɵdefineInjectable({ factory: function PasswordService_Factory() { return new PasswordService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.HttpClient), i0.ɵɵinject(i3.LrApolloService), i0.ɵɵinject(i4.AuthClass), i0.ɵɵinject(i5.ProfileService), i0.ɵɵinject(i6.KeyFactoryService), i0.ɵɵinject(i7.EncryptionService), i0.ɵɵinject(i8.KeyGraphService), i0.ɵɵinject(i9.WebCryptoService), i0.ɵɵinject(i10.IdleService)); }, token: PasswordService, providedIn: "root" });
303
+ PasswordService.decorators = [
304
+ { type: Injectable, args: [{
305
+ providedIn: 'root',
306
+ },] }
307
+ ];
308
+ PasswordService.ctorParameters = () => [
309
+ { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
310
+ { type: HttpClient },
311
+ { type: LrApolloService },
312
+ { type: AuthClass },
313
+ { type: ProfileService },
314
+ { type: KFS },
315
+ { type: EncryptionService },
316
+ { type: KeyGraphService },
317
+ { type: WebCryptoService },
318
+ { type: IdleService }
319
+ ];
320
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJDOi9Qcm9qZWN0cy9rYy1jbGllbnQvcHJvamVjdHMvY29yZS9zcmMvIiwic291cmNlcyI6WyJsaWIvYXV0aC9wYXNzd29yZC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRTNELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFtQixTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsNkJBQTZCLEVBQzdCLHlCQUF5QixHQUMxQixNQUFNLFlBQVksQ0FBQztBQUVwQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUV0RSxPQUFPLEtBQUssT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixJQUFJLEdBQUcsRUFBRSxNQUFNLHFDQUFxQyxDQUFDOzs7Ozs7Ozs7Ozs7QUFFL0UscUhBQXFIO0FBQ3JILE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQztBQXlCdkIsTUFBTSxPQUFPLGFBQWE7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USxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDekIsT0FBTztnQkFDTCxLQUFLLEVBQUUsQ0FBQztnQkFDUixrQkFBa0I7Z0JBQ2xCLElBQUksRUFBRSxDQUFDO2FBQ1IsQ0FBQztTQUNIO1FBRUQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXhELE1BQU0sS0FBSyxHQUNULENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztZQUN0QixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksR0FBRyxZQUFZLEdBQUcsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzNELE9BQU87WUFDTCxLQUFLO1lBQ0wsa0JBQWtCO1lBQ2xCLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDMUMsQ0FBQztJQUNKLENBQUM7Ozs7WUE1WEYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7NENBS0ksTUFBTSxTQUFDLFNBQVM7WUEvRFosVUFBVTtZQVVWLGVBQWU7WUFQZixTQUFTO1lBRVQsY0FBYztZQWlCTyxHQUFHO1lBaEJ4QixpQkFBaUI7WUFDakIsZUFBZTtZQVVmLGdCQUFnQjtZQUloQixXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IENvZ25pdG9Vc2VyIH0gZnJvbSAnQGF3cy1hbXBsaWZ5L2F1dGgnO1xyXG5pbXBvcnQgeyBBdXRoQ2xhc3MgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aC9saWItZXNtL0F1dGgnO1xyXG5pbXBvcnQgeyBKV0ssIEpXUyB9IGZyb20gJ25vZGUtam9zZSc7XHJcbmltcG9ydCB7IFByb2ZpbGVTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlcnMvcHJvZmlsZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkvZW5jcnlwdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgS2V5R3JhcGhTZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2tleS1ncmFwaC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTGlmZVJlYWR5Q29uZmlnLCBMUl9DT05GSUcgfSBmcm9tICcuLi9saWZlLXJlYWR5LmNvbmZpZyc7XHJcbmltcG9ydCB7IExyQXV0aEV4Y2VwdGlvbiwgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbiB9IGZyb20gJy4uL19jb21tb24vZXhjZXB0aW9ucyc7XHJcbmltcG9ydCB7IExyQXBvbGxvU2VydmljZSB9IGZyb20gJy4vLi4vYXBpL2xyLWFwb2xsby5zZXJ2aWNlJztcclxuaW1wb3J0IHtcclxuICBQYXNzd29yZENoYW5nZU11dGF0aW9uLFxyXG4gIFBhc3N3b3JkQ2hhbmdlUmVxdWVzdE11dGF0aW9uLFxyXG4gIFBhc3N3b3JkQ2hhbmdlQ29uZmlnUXVlcnksXHJcbn0gZnJvbSAnLi9hdXRoLmdxbCc7XHJcbmltcG9ydCB7IFBhc3NLZXlCdW5kbGUgfSBmcm9tICcuL2F1dGgudHlwZXMnO1xyXG5pbXBvcnQgeyBXZWJDcnlwdG9TZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L3dlYi1jcnlwdG8uc2VydmljZSc7XHJcbmltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSAnbW9tZW50JztcclxuaW1wb3J0ICogYXMgbW9tZW50XyBmcm9tICdtb21lbnQnO1xyXG5pbXBvcnQgeyBBcGlDdXJyZW50VXNlciB9IGZyb20gJy4uL3VzZXJzL3Byb2ZpbGUudHlwZXMnO1xyXG5pbXBvcnQgeyBJZGxlU2VydmljZSB9IGZyb20gJy4uL2F1dGgvaWRsZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgS2V5RmFjdG9yeVNlcnZpY2UgYXMgS0ZTIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2tleS1mYWN0b3J5LnNlcnZpY2UnO1xyXG5cclxuLy8gXCJ3aHk/XCIgeW91IGFzazogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTk3MzUyODAvYW5ndWxhci04LW1vbWVudC1lcnJvci1jYW5ub3QtY2FsbC1hLW5hbWVzcGFjZS1tb21lbnRcclxuY29uc3QgbW9tZW50ID0gbW9tZW50XztcclxuXHJcbmludGVyZmFjZSBQYXNzd29yZENoYW5nZVJlcXVlc3RNdXRhdGlvbiB7XHJcbiAgcGFzc3dvcmRDaGFuZ2VSZXF1ZXN0OiB7XHJcbiAgICBjaGFsbGVuZ2U6IHtcclxuICAgICAgc2VydmVyTm9uY2U6IHN0cmluZztcclxuICAgIH07XHJcbiAgfTtcclxufVxyXG5cclxuaW50ZXJmYWNlIFBhc3N3b3JkQ2hhbmdlTXV0YXRpb24ge1xyXG4gIHBhc3N3b3JkQ2hhbmdlOiB7XHJcbiAgICB0b2tlbjogc3RyaW5nO1xyXG4gICAgbmV3UGFzc0tleToge1xyXG4gICAgICBpZDogc3RyaW5nO1xyXG4gICAgfTtcclxuICB9O1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFBhc3N3b3JkQ2hhbmdlQ29uZmlnIHtcclxuICBtYXhBdXRoQWdlU2Vjb25kczogbnVtYmVyO1xyXG4gIGF1dGhUaW1lOiBzdHJpbmcgfCBEYXRlO1xyXG4gIHNlcnZlclRpbWU6IHN0cmluZyB8IERhdGU7XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBQYXNzd29yZENoZWNrIHtcclxuICBsZW5ndGg/OiBudW1iZXI7XHJcbiAgdGltZVRvQ3JhY2s/OiBEdXJhdGlvbjtcclxuICBwYXNzd29yZEV4cG9zZWQ/OiBudW1iZXI7XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBQYXNzd29yZFNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgQ0xJRU5UX05PTkNFX0xFTkdUSCA9IDMyO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIEBJbmplY3QoTFJfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogTGlmZVJlYWR5Q29uZmlnLFxyXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgcHJpdmF0ZSBhcG9sbG86IExyQXBvbGxvU2VydmljZSxcclxuICAgIHByaXZhdGUgYXV0aDogQXV0aENsYXNzLFxyXG4gICAgcHJpdmF0ZSBwcm9maWxlU2VydmljZTogUHJvZmlsZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGtleUZhY3Rvcnk6IEtGUyxcclxuICAgIHByaXZhdGUgZW5jcnlwdGlvblNlcnZpY2U6IEVuY3J5cHRpb25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBrZXlHcmFwaDogS2V5R3JhcGhTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB3ZWJDcnlwdG9TZXJ2aWNlOiBXZWJDcnlwdG9TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBpZGxlU2VydmljZTogSWRsZVNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBjaGVja1Bhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPFBhc3N3b3JkQ2hlY2s+IHtcclxuICAgIGNvbnN0IHsgeWVhcnMgfSA9IHRoaXMucGFzc3dvcmRTdHJlbmd0aChwYXNzd29yZCk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbGVuZ3RoOiBwYXNzd29yZC5sZW5ndGgsXHJcbiAgICAgIHRpbWVUb0NyYWNrOiBtb21lbnQuZHVyYXRpb24oeyB5ZWFycyB9KSxcclxuICAgICAgcGFzc3dvcmRFeHBvc2VkOiBhd2FpdCB0aGlzLmdldEV4cG9zdXJlQ291bnQocGFzc3dvcmQpLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXRFeHBvc3VyZUNvdW50KHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xyXG4gICAgY29uc3Qgc2hhMVBhc3N3b3JkID0gYXdhaXQgdGhpcy53ZWJDcnlwdG9TZXJ2aWNlLnN0cmluZ0RpZ2VzdChcclxuICAgICAgJ1NIQS0xJyxcclxuICAgICAgcGFzc3dvcmRcclxuICAgICk7XHJcbiAgICBjb25zdCBmaXJzdDVzaGExID0gc2hhMVBhc3N3b3JkLnN1YnN0cmluZygwLCA1KTtcclxuXHJcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuaHR0cFxyXG4gICAgICAuZ2V0KGBodHRwczovL2FwaS5wd25lZHBhc3N3b3Jkcy5jb20vcmFuZ2UvJHtmaXJzdDVzaGExfWAsIHtcclxuICAgICAgICByZXNwb25zZVR5cGU6ICd0ZXh0JyxcclxuICAgICAgfSlcclxuICAgICAgLnRvUHJvbWlzZSgpO1xyXG5cclxuICAgIGNvbnN0IHJlc3VsdHMgPSBuZXcgUmVnRXhwKFxyXG4gICAgICBgXig/OiR7c2hhMVBhc3N3b3JkLnN1YnN0cmluZyg1KX06KSg/PGNvdW50PlxcXFxkKykkYCxcclxuICAgICAgJ2ltJ1xyXG4gICAgKS5leGVjKHJlc3BvbnNlKTtcclxuXHJcbiAgICBpZiAocmVzdWx0cykge1xyXG4gICAgICByZXR1cm4gK3Jlc3VsdHMuZ3JvdXBzLmNvdW50O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIDA7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZ2V0UGFzc0lkcFN0cmluZyhwYXNzSWRwOiBKV0suS2V5KSB7XHJcbiAgICByZXR1cm4gKHBhc3NJZHAudG9KU09OKHRydWUpIGFzIGFueSkuaztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBjcmVhdGVQYXNzS2V5QnVuZGxlKHBhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPFBhc3NLZXlCdW5kbGU+IHtcclxuICAgIGNvbnN0IHBhc3NJZHBQYXJhbXMgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlUGFzc0lkcFBhcmFtcygpO1xyXG4gICAgY29uc3QgcGFzc0lkcCA9IChcclxuICAgICAgYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NJZHAoe1xyXG4gICAgICAgIHBhc3N3b3JkLFxyXG4gICAgICAgIC4uLnBhc3NJZHBQYXJhbXMsXHJcbiAgICAgIH0pXHJcbiAgICApLmp3aztcclxuXHJcbiAgICBjb25zdCBwYXNzS2V5UGFyYW1zID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZVBhc3NLZXlQYXJhbXMoKTtcclxuICAgIGNvbnN0IHBhc3NLZXkgPSAoXHJcbiAgICAgIGF3YWl0IHRoaXMua2V5RmFjdG9yeS5kZXJpdmVQYXNzS2V5KHtcclxuICAgICAgICBwYXNzd29yZCxcclxuICAgICAgICAuLi5wYXNzS2V5UGFyYW1zLFxyXG4gICAgICB9KVxyXG4gICAgKS5qd2s7XHJcblxyXG4gICAgY29uc3QgcGFzc0lkcFZlcmlmaWVyID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmNyZWF0ZVBrY1NpZ25LZXkoKTtcclxuXHJcbiAgICBjb25zdCB3cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFxyXG4gICAgICBwYXNzS2V5LFxyXG4gICAgICBwYXNzSWRwVmVyaWZpZXIudG9KU09OKHRydWUpXHJcbiAgICApO1xyXG5cclxuICAgIC8vIFRoZXJlIGFyZSB0d28gZm9ybWF0cyB0aGF0IHRoZSBwcml2YXRlIGtleSBjYW4gYmUgcmVwcmVzZW50ZWQgaW4gSldLOlxyXG4gICAgLy8gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzgwMTcjcGFnZS05XHJcbiAgICAvLyBUaGUgc2Vjb25kIGZvcm0gaXMgYW4gb3B0aW1pemF0aW9uOlxyXG4gICAgLy8gaHR0cHM6Ly9jcnlwdG8uc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzE5NDEzL3doYXQtYXJlLWRwLWFuZC1kcS1pbi1lbmNyeXB0aW9uLWJ5LXJzYS1pbi1jXHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgcGFzc0tleVBhcmFtcyxcclxuICAgICAgcGFzc0tleSxcclxuICAgICAgcGFzc0lkcFBhcmFtcyxcclxuICAgICAgcGFzc0lkcCxcclxuICAgICAgcGFzc0lkcFZlcmlmaWVyLFxyXG4gICAgICB3cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFdlIG5lZWQgdG8gYWxsb3cgZm9yIGludGVycnVwdGlvbiBvZiB0aGUgcHJvY2VzcyBhdCBhbnkgcG9pbnQuIEVhY2ggQVBJIGNhbGwgY2FuIGJlIGNvbnNpZGVyZWRcclxuICAgKiBhdG9taWMgYW5kIGVpdGhlciBzdWNjZWVkcyBvciBmYWlscy5cclxuICAgKlxyXG4gICAqIFRoZSBMUiBzZXJ2ZXIgQVBJcyB1c2Ugc2VtYXBob3JlIHRva2VucyBmb3IgbG9ja2luZyBjcml0aWNhbCBvcGVyYXRpb25zLCBzbyBjb25jdXJyZW50IGNhbGxzIHdpbGxcclxuICAgKiBmYWlsLlxyXG4gICAqXHJcbiAgICogV2UgYXNzdW1lIHRoZSB3b3JzdCBjYXNlIGZvciBJZFAgQVBJIGNhbGxzLiBTbyB3ZSB1c2UgdGhlIHNlbWFwaG9yZSB0b2tlbiBmcm9tIExSIHRvIHByZXZlbnRcclxuICAgKiBjb25jdXJyZW50IGNhbGxzIHRvIElkUCBBUElzLCBidXQgd2UgaGF2ZSB0byBhc3N1bWUgdGhhdCB0aGUgSWRQIEFQSSBjYWxscyB3aWxsIGVpdGhlciBzdWNjZWVkIG9yXHJcbiAgICogZmFpbCB3aXRoaW4gYSByZWFzb25hYmxlIGFtb3VudCBvZiB0aW1lLlxyXG4gICAqXHJcbiAgICogRWFjaCBsb2NhdGlvbiB3aGVyZSB0aGUgc2VydmVyIHN0YXRlIGNoYW5nZXMgY2FuIGJlIGEgcG90ZW50aWFsIHBvaW50IG9mIGludGVycnVwdGlvbi5cclxuICAgKiBQb3RlbnRpYWwgcG9pbnRzIG9mIGludGVycnVwdGlvbiBhcmUgbWFya2VkIHdpdGg6IC0tUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQtLVxyXG4gICAqXHJcbiAgICogUGxhY2VzIGZvciB0aW1lb3V0OlxyXG4gICAqIC0gTG9naW4gYWdlIHRvbyBvbGQgYXQgY2FsbCB0bzogdmVyaWZ5UGFzc3dvcmQoKVxyXG4gICAqIC0gTG9naW4gYWdlIHRvbyBvbGQgYXQgY2FsbCB0bzogY2hhbmdlUGFzc3dvcmRNdXRhdGlvbigpXHJcbiAgICogLSBTZW1hcGhvcmUgdG9rZW4gZXhwaXJlcyBhdCBjYWxsIHRvOiBjaGFuZ2VQYXNzd29yZENvbXBsZXRlKClcclxuICAgKlxyXG4gICAqIFRlc3RzOlxyXG4gICAqIC0gUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgMTogc2hvdWxkIGJlIGFibGUgdG8gcmVzdGFydCB0aGUgcHJvY2VzcywgdXNlciByZW1haW5zIHNpZ25lZCBpbi5cclxuICAgKiAtIFBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDI6IHNob3VsZCBlbnRlciByZWNvdmVyeSBmbG93XHJcbiAgICogLSBQb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAzOiBzaG91bGQgZW50ZXIgcmVjb3ZlcnkgZmxvd1xyXG4gICAqIC0gUG90ZW50aWFsIEZhaWx1cmUgUG9pbnQgNDogc2hvdWxkIGVudGVyIHJlY292ZXJ5IGZsb3dcclxuICAgKlxyXG4gICAqL1xyXG5cclxuICBwdWJsaWMgYXN5bmMgaXNMb2dpblJlcXVpcmVkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgY29uc3QgY2hhbmdlUGFzc3dvcmRDb25maWcgPSBhd2FpdCB0aGlzLmdldENoYW5nZVBhc3N3b3JkQ29uZmlnKCk7XHJcbiAgICBjb25zdCBhdXRoVGltZSA9IG1vbWVudChjaGFuZ2VQYXNzd29yZENvbmZpZy5hdXRoVGltZSk7XHJcbiAgICBjb25zdCBzZXJ2ZXJUaW1lID0gbW9tZW50KGNoYW5nZVBhc3N3b3JkQ29uZmlnLnNlcnZlclRpbWUpO1xyXG4gICAgY29uc3QgZHVyYXRpb24gPSBtb21lbnQuZHVyYXRpb24oc2VydmVyVGltZS5kaWZmKGF1dGhUaW1lKSk7XHJcbiAgICBjb25zdCBzZWNvbmRzID0gZHVyYXRpb24uYXNTZWNvbmRzKCk7XHJcbiAgICBpZiAoc2Vjb25kcyA+IGNoYW5nZVBhc3N3b3JkQ29uZmlnLm1heEF1dGhBZ2VTZWNvbmRzKSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGNoYW5nZVBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcsIG5ld1Bhc3N3b3JkOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IGNvZ25pdG9Vc2VyOiBDb2duaXRvVXNlciA9IGF3YWl0IHRoaXMuYXV0aC5jdXJyZW50QXV0aGVudGljYXRlZFVzZXIoKTtcclxuXHJcbiAgICAvLyBWYWxpZGF0aW9uXHJcbiAgICAvLyB0b2RvOiBBZGQgdGhpcyBiYWNrIGluXHJcbiAgICAvLyBOb3RlIHRoZSBwYXNzSWRwIHdpbGwgYWx3YXlzIGhhdmUgYSByYW5kb20gc2FsdCwgc28gd2lsbCBhbHdheXMgYmUgZGlmZmVyZW50IHRvIHRoZSBjdXJyZW50IHBhc3NJZHAuXHJcbiAgICBpZiAocGFzc3dvcmQgPT09IG5ld1Bhc3N3b3JkKSB7XHJcbiAgICAgIHRocm93IG5ldyBMckJhZEFyZ3VtZW50RXhjZXB0aW9uKFxyXG4gICAgICAgICdOZXcgcGFzc3dvcmQgaXMgdGhlIHNhbWUgYXMgdGhlIGN1cnJlbnQgb25lLidcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB7IGN1cnJlbnRVc2VyIH0gPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldEN1cnJlbnRVc2VyKCk7XHJcblxyXG4gICAgY29uc3QgeyBwYXNzSWRwLCBzaWduZWRDaGFsbGVuZ2UgfSA9IGF3YWl0IHRoaXMudmVyaWZ5UGFzc3dvcmQoXHJcbiAgICAgIHBhc3N3b3JkLFxyXG4gICAgICBjdXJyZW50VXNlclxyXG4gICAgKTtcclxuXHJcbiAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDEtLVxyXG4gICAgLy8gdmVyaWZ5UGFzc3dvcmQoKSBhc2tzIGZvciBhIGN1cnJlbnQgcGFzc3dvcmQgY2hhbGxlbmdlIGhlbmNlIGNoYW5nZXMgc2VydmVyIHN0YXRlLlxyXG4gICAgLy8gUGxhY2UgYnJlYWsgcG9pbnRzIGhlcmUgdG8gdGVzdCB0aGUgZmFpbHVyZSBzY2VuYXJpb3MuXHJcblxyXG4gICAgLy8gR2VuZXJhdGUgdGhlIG5ldyBwYXNzSWRwXHJcbiAgICBjb25zdCBuZXdQYXNzS2V5ID0gYXdhaXQgdGhpcy5jcmVhdGVQYXNzS2V5QnVuZGxlKG5ld1Bhc3N3b3JkKTtcclxuXHJcbiAgICAvLyBSZS1lbmNyeXB0IG1hc3RlciBrZXkgd2l0aCBuZXcga2V5XHJcbiAgICBjb25zdCBtYXN0ZXJLZXkgPSBhd2FpdCB0aGlzLmtleUdyYXBoLmdldEtleShcclxuICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkubWFzdGVyS2V5LmlkXHJcbiAgICApO1xyXG4gICAgY29uc3QgbmV3V3JhcHBlZE1hc3RlcktleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcclxuICAgICAgbmV3UGFzc0tleS5wYXNzS2V5LFxyXG4gICAgICBtYXN0ZXJLZXkuandrLnRvSlNPTih0cnVlKVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBJZiB0aGUgSWRQIGNoYW5nZSBwYXNzd29yZCBmYWlsZWQsIHdlIG5lZWQgdG8gZ28gaW50byByZWNvdmVyeSBtb2RlIGJ5IGZvcmNpbmdcclxuICAgIC8vIGEgbG9naW4uIFdlIGNhbid0IGxvZ291dCB0aGUgdXNlciBqdXN0IHlldCBzaW5jZSB0aGUgSWRQIHBhc3N3b3JkIGNoYW5nZSBuZWVkc1xyXG4gICAgLy8gdGhlIHVzZXIgdG8gYmUgbG9nZ2VkIGluLiBXZSBfY2FuXyByZW1vdmVkIGFueSBwZXJzaXN0ZWQgc2Vzc2lvbiB2YWx1ZXMgZm9yIHRoZSBJZFBcclxuICAgIC8vIGJ1dCB0aGF0IHNlZW1zIGxpa2UgdG9vIG11Y2ggdHJvdWJsZS5cclxuXHJcbiAgICBjb25zdCB7IHRva2VuLCBuZXdQYXNzS2V5SWQgfSA9IGF3YWl0IHRoaXMuY2hhbmdlUGFzc3dvcmRNdXRhdGlvbihcclxuICAgICAgc2lnbmVkQ2hhbGxlbmdlLFxyXG4gICAgICBjdXJyZW50VXNlci5jdXJyZW50VXNlcktleS5tYXN0ZXJLZXkuaWQsXHJcbiAgICAgIG5ld1dyYXBwZWRNYXN0ZXJLZXksXHJcbiAgICAgIG5ld1Bhc3NLZXlcclxuICAgICk7XHJcblxyXG4gICAgLy8gLS1Qb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAyLS1cclxuICAgIC8vIGNoYW5nZVBhc3N3b3JkTXV0YXRpb24oKSB1cGxvYWRzIG5ldyBrZXlzIGFuZCBvYnRhaW5zIGEgc2VtYXBob3JlIGxvY2sgdG8gcHJldmVudCBhbnkgb3RoZXJcclxuICAgIC8vIGNsaWVudHMgZnJvbSBwZXJmb3JtaW5nIElkUCBwYXNzd29yZCBjaGFuZ2UuXHJcblxyXG4gICAgLy8gTm93IHdlIGNhbiBkbyB0aGUgSWRQIHBhc3N3b3JkIGNoYW5nZS5cclxuICAgIC8vIHRvZG86IEFkZCB0aGlzIGJhY2sgaW5cclxuICAgIGF3YWl0IHRoaXMuYXV0aC5jaGFuZ2VQYXNzd29yZChcclxuICAgICAgY29nbml0b1VzZXIsXHJcbiAgICAgIHRoaXMuZ2V0UGFzc0lkcFN0cmluZyhwYXNzSWRwKSxcclxuICAgICAgdGhpcy5nZXRQYXNzSWRwU3RyaW5nKG5ld1Bhc3NLZXkucGFzc0lkcClcclxuICAgICk7XHJcblxyXG4gICAgLy8gLS1Qb3RlbnRpYWwgRmFpbHVyZSBQb2ludCAzLS1cclxuICAgIC8vIElkUCBwYXNzd29yZCBjaGFuZ2VcclxuXHJcbiAgICAvLyBOb3RlIHRoYXQgY2hhbmdlUGFzc3dvcmQoKSBjb3VsZCB0aHJvdyBhbiBleGNlcHRpb24gZm9yIGEgbnVtYmVyIG9mIHJlYXNvbi4gSXQgY291bGQgdGhyb3dcclxuICAgIC8vIGEgbmV0d29yayB0aW1lb3V0IGZvciBleGFtcGxlLiBCdXQgd2UgZG9uJ3Qga25vdyBpZiBpdCdzIHRoZSByZXNwb25zZSB0aGF0IHRpbWVkIG91dCBhbmRcclxuICAgIC8vIHRoZSBpZHAgcGFzc3dvcmQgY2hhbmdlIHdhcyBhY3R1YWxseSBjYXJyaWVkIG91dC4gU28gd2UgaGF2ZSB0byBiZSBleHRyYSBjb25zZXJ2YXRpdmUgYW5kXHJcbiAgICAvLyBvbmx5IGFjdCBvbiBhIGNsZWFyIHN1Y2Nlc3MuIE90aGVyd2lzZSB3ZSBnbyBpbnRvIHJlY292ZXIgbW9kZS5cclxuICAgIGF3YWl0IHRoaXMuY2hhbmdlUGFzc3dvcmRDb21wbGV0ZShcclxuICAgICAgY29nbml0b1VzZXIuZ2V0U2lnbkluVXNlclNlc3Npb24oKS5nZXRBY2Nlc3NUb2tlbigpLmdldEp3dFRva2VuKCksXHJcbiAgICAgIHRydWUsXHJcbiAgICAgIHRva2VuXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGNoYW5nZVBhc3N3b3JkQ29tcGxldGUoXHJcbiAgICBhY2Nlc3NUb2tlbjogc3RyaW5nLFxyXG4gICAgdXNlTmV3UGFzc3dvcmQ6IGJvb2xlYW4sXHJcbiAgICB0b2tlbjogc3RyaW5nID0gbnVsbFxyXG4gICk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gdGhpcy5odHRwXHJcbiAgICAgIC5wb3N0KFxyXG4gICAgICAgIGAke3RoaXMuY29uZmlnLmF1dGhVcmx9dXNlcnMvcGFzc3dvcmQtY2hhbmdlLWNvbXBsZXRlL2AsXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgdXNlX25ld19wYXNzd29yZDogdXNlTmV3UGFzc3dvcmQsXHJcbiAgICAgICAgICAuLi4odG9rZW4gJiYgeyB0b2tlbiB9KSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIGhlYWRlcnM6IHtcclxuICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2FjY2Vzc1Rva2VufWAsXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH1cclxuICAgICAgKVxyXG4gICAgICAudG9Qcm9taXNlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGdldFZlcmlmaWVyUHJLKFxyXG4gICAgcGFzc0tleTogSldLLktleSxcclxuICAgIHdyYXBwZWRQcks6IG9iamVjdFxyXG4gICk6IFByb21pc2U8SldLLktleT4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcHJrSnNvbiA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChwYXNzS2V5LCB3cmFwcGVkUHJLKTtcclxuICAgICAgcmV0dXJuIEtGUy5hc0tleShwcmtKc29uKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIHRocm93IG5ldyBMckF1dGhFeGNlcHRpb24oJ1dyb25nIGN1cnJlbnQgcGFzc3dvcmQnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgdmVyaWZ5UGFzc3dvcmQoXHJcbiAgICBwYXNzd29yZDogc3RyaW5nLFxyXG4gICAgY3VycmVudFVzZXI6IEFwaUN1cnJlbnRVc2VyXHJcbiAgKTogUHJvbWlzZTx7IHBhc3NJZHA6IEpXSy5LZXk7IHNpZ25lZENoYWxsZW5nZTogSldTLkNyZWF0ZVNpZ25SZXN1bHQgfT4ge1xyXG4gICAgLy8gR2V0IGluZm9ybWF0aW9uIGZyb20gdGhlIHNlcnZlciB0byBwcmVwYXJlIGZvciBwYXNzd29yZCBjaGFuZ2UuXHJcbiAgICBjb25zdCBwYXNzd29yZFJlcXVlc3QgPSBhd2FpdCB0aGlzLmFwb2xsby5tdXRhdGU8UGFzc3dvcmRDaGFuZ2VSZXF1ZXN0TXV0YXRpb24+KFxyXG4gICAgICB7XHJcbiAgICAgICAgbXV0YXRpb246IFBhc3N3b3JkQ2hhbmdlUmVxdWVzdE11dGF0aW9uLFxyXG4gICAgICAgIHZhcmlhYmxlczoge30sXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBvbGQgcGFzc0tleSBzbyB3ZSBjYW4gZGVjcnlwdCB0aGUgb2xkIHBhc3N3b3JkIHZlcmlmaWVyXHJcbiAgICBjb25zdCBwYXNzS2V5UmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NLZXkoe1xyXG4gICAgICBwYXNzd29yZCxcclxuICAgICAgLi4uY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS5wYXNzS2V5UGFyYW1zLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdmVyaWZpZXJQcksgPSBhd2FpdCB0aGlzLmdldFZlcmlmaWVyUHJLKFxyXG4gICAgICBwYXNzS2V5UmVzdWx0Lmp3ayxcclxuICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS53cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrXHJcbiAgICApO1xyXG5cclxuICAgIC8vIFNpZ24gdGhlIHNlcnZlciBjaGFsbGVuZ2UgdG8gcHJvdmUgdG8gdGhlIHNlcnZlciB3ZSBjYW4gZGVjcnlwdCB0aGUgcGFzc3dvcmQgdmVyaWZpZXIuXHJcbiAgICAvLyBHZW5lcmF0ZVxyXG4gICAgY29uc3QgY2xpZW50Tm9uY2UgPSB0aGlzLmtleUZhY3RvcnkucmFuZG9tU3RyaW5nKHRoaXMuQ0xJRU5UX05PTkNFX0xFTkdUSCk7XHJcblxyXG4gICAgY29uc3Qgc2lnbmVkQ2hhbGxlbmdlID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKHZlcmlmaWVyUHJLLCB7XHJcbiAgICAgIHNlcnZlck5vbmNlOiBwYXNzd29yZFJlcXVlc3QucGFzc3dvcmRDaGFuZ2VSZXF1ZXN0LmNoYWxsZW5nZS5zZXJ2ZXJOb25jZSxcclxuICAgICAgY2xpZW50Tm9uY2UsXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBwYXNzSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NJZHAoe1xyXG4gICAgICBwYXNzd29yZCxcclxuICAgICAgLi4uY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS5wYXNzSWRwUGFyYW1zLFxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgcGFzc0lkcDogcGFzc0lkcFJlc3VsdC5qd2ssXHJcbiAgICAgIHNpZ25lZENoYWxsZW5nZSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGNoYW5nZVBhc3N3b3JkTXV0YXRpb24oXHJcbiAgICBzaWduZWRDaGFsbGVuZ2U6IEpXUy5DcmVhdGVTaWduUmVzdWx0LFxyXG4gICAgbWFzdGVyS2V5SWQ6IHN0cmluZyxcclxuICAgIG5ld1dyYXBwZWRNYXN0ZXJLZXk6IG9iamVjdCxcclxuICAgIHBhc3NLZXlCdW5kbGU6IFBhc3NLZXlCdW5kbGVcclxuICApOiBQcm9taXNlPHsgdG9rZW46IHN0cmluZzsgbmV3UGFzc0tleUlkOiBzdHJpbmcgfT4ge1xyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmFwb2xsby5tdXRhdGU8UGFzc3dvcmRDaGFuZ2VNdXRhdGlvbj4oe1xyXG4gICAgICBtdXRhdGlvbjogUGFzc3dvcmRDaGFuZ2VNdXRhdGlvbixcclxuICAgICAgdmFyaWFibGVzOiB7XHJcbiAgICAgICAgaW5wdXQ6IHtcclxuICAgICAgICAgIHNpZ25lZENoYWxsZW5nZTogSlNPTi5zdHJpbmdpZnkoc2lnbmVkQ2hhbGxlbmdlKSxcclxuICAgICAgICAgIG1hc3RlcktleUlkLFxyXG4gICAgICAgICAgbmV3V3JhcHBlZE1hc3RlcktleTogSlNPTi5zdHJpbmdpZnkobmV3V3JhcHBlZE1hc3RlcktleSksXHJcbiAgICAgICAgICBuZXdQYXNzS2V5OiB7XHJcbiAgICAgICAgICAgIHBhc3NJZHBQYXJhbXM6IEpTT04uc3RyaW5naWZ5KHBhc3NLZXlCdW5kbGUucGFzc0lkcFBhcmFtcyksXHJcbiAgICAgICAgICAgIHBhc3NJZHBWZXJpZmllclBiazogSlNPTi5zdHJpbmdpZnkoXHJcbiAgICAgICAgICAgICAgcGFzc0tleUJ1bmRsZS5wYXNzSWRwVmVyaWZpZXIudG9KU09OKClcclxuICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgd3JhcHBlZFBhc3NJZHBWZXJpZmllclByazogSlNPTi5zdHJpbmdpZnkoXHJcbiAgICAgICAgICAgICAgcGFzc0tleUJ1bmRsZS53cmFwcGVkUGFzc0lkcFZlcmlmaWVyUHJrXHJcbiAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgIHBhc3NLZXlQYXJhbXM6IEpTT04uc3RyaW5naWZ5KHBhc3NLZXlCdW5kbGUucGFzc0tleVBhcmFtcyksXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIHRva2VuOiByZXNwb25zZS5wYXNzd29yZENoYW5nZS50b2tlbixcclxuICAgICAgbmV3UGFzc0tleUlkOiByZXNwb25zZS5wYXNzd29yZENoYW5nZS5uZXdQYXNzS2V5LmlkLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldENoYW5nZVBhc3N3b3JkQ29uZmlnKCk6IFByb21pc2U8UGFzc3dvcmRDaGFuZ2VDb25maWc+IHtcclxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuYXBvbGxvLnF1ZXJ5PGFueT4oe1xyXG4gICAgICBxdWVyeTogUGFzc3dvcmRDaGFuZ2VDb25maWdRdWVyeSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHJldCA9IHJlcy5wYXNzd29yZENoYW5nZUNvbmZpZyBhcyBQYXNzd29yZENoYW5nZUNvbmZpZztcclxuXHJcbiAgICByZXQuYXV0aFRpbWUgPSBuZXcgRGF0ZShyZXQuYXV0aFRpbWUpO1xyXG4gICAgcmV0LnNlcnZlclRpbWUgPSBuZXcgRGF0ZShyZXQuc2VydmVyVGltZSk7XHJcbiAgICByZXR1cm4gcmV0O1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHBhc3N3b3JkU3RyZW5ndGgocGFzc3dvcmQpOiB7IHllYXJzOiBudW1iZXI7IGJpdHM6IG51bWJlciB9IHtcclxuICAgIGNvbnN0IHVwcGVyID0gL1tBLVpdL2c7XHJcbiAgICBjb25zdCBsb3dlciA9IC9bYS16XS9nO1xyXG4gICAgY29uc3QgZGlnaXQgPSAvWzAtOV0vZztcclxuXHJcbiAgICBjb25zdCB1cHBlckNob2ljZXMgPSAyNjtcclxuICAgIGNvbnN0IGxvd2VyQ2hvaWNlcyA9IDI2O1xyXG4gICAgY29uc3QgZGlnaXRDaG9pY2VzID0gMTA7XHJcbiAgICBjb25zdCBzcGVjaWFsQ2hvaWNlcyA9IDMwOyAvLyAvWyFcIiMkJSYnKCkqKywtLi86Ozw9Pj9AW1xcXV5fYHt8fX5dL2dcclxuXHJcbiAgICBmdW5jdGlvbiBpbnN0YW5jZUNvdW50KHN0ciwgcmUpIHtcclxuICAgICAgcmV0dXJuICgoc3RyIHx8ICcnKS5tYXRjaChyZSkgfHwgW10pLmxlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1cHBlcnMgPSBpbnN0YW5jZUNvdW50KHBhc3N3b3JkLCB1cHBlcik7XHJcbiAgICBjb25zdCBsb3dlcnMgPSBpbnN0YW5jZUNvdW50KHBhc3N3b3JkLCBsb3dlcik7XHJcbiAgICBjb25zdCBkaWdpdHMgPSBpbnN0YW5jZUNvdW50KHBhc3N3b3JkLCBkaWdpdCk7XHJcbiAgICBjb25zdCBzcGVjaWFscyA9IHBhc3N3b3JkLmxlbmd0aCAtIHVwcGVycyAtIGxvd2VycyAtIGRpZ2l0cztcclxuXHJcbiAgICBsZXQgY2hvaWNlcyA9IDA7XHJcbiAgICBpZiAodXBwZXJzKSB7XHJcbiAgICAgIGNob2ljZXMgKz0gdXBwZXJDaG9pY2VzO1xyXG4gICAgfVxyXG4gICAgaWYgKGxvd2Vycykge1xyXG4gICAgICBjaG9pY2VzICs9IGxvd2VyQ2hvaWNlcztcclxuICAgIH1cclxuICAgIGlmIChkaWdpdHMpIHtcclxuICAgICAgY2hvaWNlcyArPSBkaWdpdENob2ljZXM7XHJcbiAgICB9XHJcbiAgICBpZiAoc3BlY2lhbHMpIHtcclxuICAgICAgY2hvaWNlcyArPSBzcGVjaWFsQ2hvaWNlcztcclxuICAgIH1cclxuXHJcbiAgICBpZiAocGFzc3dvcmQubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgeWVhcnM6IDAsXHJcbiAgICAgICAgLy8gYml0cyBvZiBlbnRyb3B5XHJcbiAgICAgICAgYml0czogMCxcclxuICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBwZXJtdXRhdGlvbnMgPSBNYXRoLnBvdyhjaG9pY2VzLCBwYXNzd29yZC5sZW5ndGgpO1xyXG5cclxuICAgIGNvbnN0IHllYXJzID1cclxuICAgICAgKDU0MDAwICogcGVybXV0YXRpb25zKSAvXHJcbiAgICAgIE1hdGgucG93KHVwcGVyQ2hvaWNlcyArIGxvd2VyQ2hvaWNlcyArIGRpZ2l0Q2hvaWNlcywgMTIpO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeWVhcnMsXHJcbiAgICAgIC8vIGJpdHMgb2YgZW50cm9weVxyXG4gICAgICBiaXRzOiBNYXRoLnJvdW5kKE1hdGgubG9nMihwZXJtdXRhdGlvbnMpKSxcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiJdfQ==