@lifeready/core 1.0.15 → 1.0.16

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,237 +1,237 @@
1
- import { __awaiter } from "tslib";
2
- import { Injectable } from '@angular/core';
3
- import { JWK } from 'node-jose';
4
- import { WebCryptoService } from './web-crypto.service';
5
- import { LrBadArgumentException, LrSuspiciousException, } from '../_common/exceptions';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "./web-crypto.service";
8
- export function sha256(message) {
9
- return __awaiter(this, void 0, void 0, function* () {
10
- // encode as UTF-8
11
- const msgBuffer = new TextEncoder().encode(message);
12
- // hash the message
13
- const hashBuffer = yield crypto.subtle.digest('SHA-256', msgBuffer);
14
- // convert ArrayBuffer to Array
15
- const hashArray = Array.from(new Uint8Array(hashBuffer));
16
- // convert bytes to hex string
17
- const hashHex = hashArray
18
- .map((b) => ('00' + b.toString(16)).slice(-2))
19
- .join('');
20
- return hashHex;
21
- });
22
- }
23
- export class KeyFactoryService {
24
- constructor(webCryptoService) {
25
- this.webCryptoService = webCryptoService;
26
- // Global keys store. Otherwise, each call to asKey creates a new keyStore.
27
- // <AZ> Did not seem to improve speed.
28
- // public static keyStore = JWK.createKeyStore();
29
- // AZ: This can't be change easily. It's basically a PassK or PassIdp rotation.
30
- // todo: we should eventually increase this periodically to match with Moore's law.
31
- // The iterations for each key are kept by the server as well but we assume the value
32
- // from the server is not trustworthy, so need to have minimum thresholds here.
33
- // If creating new keys, these minimum are used.
34
- this.MIN_PASS_IDP_PBKDF_ITER = 100000;
35
- this.MIN_PASS_KEY_PBKDF_ITER = 100000;
36
- this.MIN_LBOP_KEY_PBKDF_ITER = 100000;
37
- // These are used as the default values. They must be larger than the minimum values.
38
- this.DEFAULT_PASS_IDP_PBKDF_ITER = this.MIN_PASS_IDP_PBKDF_ITER;
39
- this.DEFAULT_PASS_KEY_PBKDF_ITER = this.MIN_PASS_KEY_PBKDF_ITER;
40
- this.DEFAULT_LBOP_KEY_PBKDF_ITER = this.MIN_LBOP_KEY_PBKDF_ITER;
41
- this.crypto = this.webCryptoService.crypto;
42
- }
43
- static asKey(key, form, extras) {
44
- // <AZ> Using a single global key store did not seem to improve speed.
45
- // return KeyFactoryService.keyStore.add(key, form, extras);
46
- return JWK.asKey(key, form, extras);
47
- }
48
- randomString(digits) {
49
- if (digits <= 0) {
50
- throw new LrBadArgumentException('digits <= 0');
51
- }
52
- const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
53
- let array = new Uint32Array(digits);
54
- this.crypto.getRandomValues(array);
55
- array = array.map((x) => validChars.charCodeAt(x % validChars.length));
56
- return String.fromCharCode.apply(null, array);
57
- }
58
- randomDigitsNoZeros(digits) {
59
- return this.randomChoices([1, 2, 3, 4, 5, 6, 7, 8, 9], digits).join('');
60
- }
61
- randomChoices(array, chooseN) {
62
- if (array.length <= 1) {
63
- throw new LrBadArgumentException('array.length <= 0');
64
- }
65
- if (chooseN <= 0) {
66
- throw new LrBadArgumentException('chooseN <= 0');
67
- }
68
- const values = new Uint32Array(chooseN);
69
- this.crypto.getRandomValues(values);
70
- const ret = [];
71
- values.forEach((v) => ret.push(array[v % array.length]));
72
- return ret;
73
- }
74
- createSalt() {
75
- return this.randomString(16);
76
- }
77
- createKey() {
78
- return __awaiter(this, void 0, void 0, function* () {
79
- const key = yield this.crypto.subtle.generateKey({
80
- name: 'AES-GCM',
81
- length: 256,
82
- }, true, // whether the key is extractable (i.e. can be used in exportKey)
83
- ['encrypt', 'decrypt'] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
84
- );
85
- const jwk = yield this.crypto.subtle.exportKey('jwk', key);
86
- // Removing the fields not needed by node-jose
87
- delete jwk.ext;
88
- delete jwk.key_ops;
89
- return KeyFactoryService.asKey(jwk);
90
- });
91
- }
92
- createSignKey() {
93
- return __awaiter(this, void 0, void 0, function* () {
94
- const key = yield this.crypto.subtle.generateKey({
95
- name: 'HMAC',
96
- hash: { name: 'SHA-512' },
97
- }, true, ['sign', 'verify']);
98
- const jwk = yield this.crypto.subtle.exportKey('jwk', key);
99
- // Removing the fields not needed by node-jose
100
- delete jwk.key_ops;
101
- delete jwk.ext;
102
- return KeyFactoryService.asKey(jwk);
103
- });
104
- }
105
- createPkcKey() {
106
- return __awaiter(this, void 0, void 0, function* () {
107
- // node-jose is not using Forge properly. It should be calling the async version of
108
- // pki.rsa.generateKeyPair() with a callback. Instead it calls the sync version. Webcrypto
109
- // does not support sync version, so it uses the javascript implementation, which is way too slow.
110
- // So we generate using webcrypto and import the key.
111
- // Unfortunately Elliptical Curve is not supported by Webcrypto. So we have to settle for RSA.
112
- const key = yield this.crypto.subtle.generateKey({
113
- name: 'RSA-OAEP',
114
- modulusLength: 2048,
115
- // As per suggestion: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
116
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
117
- hash: { name: 'SHA-256' },
118
- }, true, // whether the key is extractable (i.e. can be used in exportKey)
119
- ['encrypt', 'decrypt'] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
120
- );
121
- const jwk = yield this.crypto.subtle.exportKey('jwk', key.privateKey);
122
- // Removing the fields not needed by node-jose
123
- delete jwk.key_ops;
124
- delete jwk.ext;
125
- return KeyFactoryService.asKey(jwk);
126
- });
127
- }
128
- createPkcSignKey() {
129
- return __awaiter(this, void 0, void 0, function* () {
130
- const key = yield this.crypto.subtle.generateKey({
131
- name: 'RSASSA-PKCS1-v1_5',
132
- modulusLength: 2048,
133
- // As per suggestion: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
134
- publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
135
- hash: { name: 'SHA-256' },
136
- }, true, // whether the key is extractable (i.e. can be used in exportKey)
137
- ['sign', 'verify'] // can be any combination of "sign" and "verify"
138
- );
139
- const jwk = yield this.crypto.subtle.exportKey('jwk', key.privateKey);
140
- // Removing the fields not needed by node-jose
141
- delete jwk.key_ops;
142
- delete jwk.ext;
143
- return KeyFactoryService.asKey(jwk);
144
- });
145
- }
146
- deriveKey({ password, salt, iterations, kid, }) {
147
- return __awaiter(this, void 0, void 0, function* () {
148
- const enc = new TextEncoder();
149
- const rawKey = yield this.crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveBits', 'deriveKey']);
150
- const passKey = yield crypto.subtle.deriveKey({
151
- name: 'PBKDF2',
152
- salt: new TextEncoder().encode(salt),
153
- iterations,
154
- hash: 'SHA-256',
155
- }, rawKey, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
156
- const passKeyJson = yield crypto.subtle.exportKey('jwk', passKey);
157
- if (kid) {
158
- passKeyJson.kid = kid;
159
- }
160
- const jwk = yield KeyFactoryService.asKey(passKeyJson);
161
- return { jwk };
162
- });
163
- }
164
- derivePassIdp(params) {
165
- return __awaiter(this, void 0, void 0, function* () {
166
- if (params.iterations < this.MIN_PASS_IDP_PBKDF_ITER) {
167
- throw new LrSuspiciousException(`The number of PassIdp key derivation iterations sent from the server (${params.iterations}) is lower than the minimum (${this.MIN_PASS_IDP_PBKDF_ITER})`);
168
- }
169
- return this.deriveKey(params);
170
- });
171
- }
172
- derivePassKey(params) {
173
- return __awaiter(this, void 0, void 0, function* () {
174
- if (params.iterations < this.MIN_PASS_KEY_PBKDF_ITER) {
175
- throw new LrSuspiciousException(`The number of PassKey key derivation iterations sent from the server(${params.iterations}) is lower than the minimum(${this.MIN_PASS_KEY_PBKDF_ITER})`);
176
- }
177
- return this.deriveKey(params);
178
- });
179
- }
180
- deriveLbopKey(params) {
181
- return __awaiter(this, void 0, void 0, function* () {
182
- if (params.iterations < this.MIN_LBOP_KEY_PBKDF_ITER) {
183
- throw new LrSuspiciousException(`The number of LbopKey key derivation iterations sent from the server(${params.iterations}) is lower than the minimum(${this.MIN_LBOP_KEY_PBKDF_ITER})`);
184
- }
185
- return this.deriveKey(params);
186
- });
187
- }
188
- createKid() {
189
- return __awaiter(this, void 0, void 0, function* () {
190
- // todo: AZ: node-jose source uses node's default UUID() function for kid, so just change to use that.
191
- // for now, we are just creating a new key to use it's kid.
192
- // The kid is a part of the JWK system. LR backend maintains the key hierarchy separately with it's own
193
- // key id. But we just use it here as a double check.
194
- return (yield this.createKey()).kid;
195
- });
196
- }
197
- createPassIdpParams() {
198
- return __awaiter(this, void 0, void 0, function* () {
199
- return {
200
- salt: this.createSalt(),
201
- iterations: this.DEFAULT_PASS_IDP_PBKDF_ITER,
202
- };
203
- });
204
- }
205
- createPassKeyParams() {
206
- return __awaiter(this, void 0, void 0, function* () {
207
- return {
208
- salt: this.createSalt(),
209
- kid: yield this.createKid(),
210
- iterations: this.DEFAULT_PASS_KEY_PBKDF_ITER,
211
- };
212
- });
213
- }
214
- createLbopKeyParams() {
215
- return __awaiter(this, void 0, void 0, function* () {
216
- return {
217
- salt: this.createSalt(),
218
- // todo: AZ: node-jose source uses node's default UUID() function for kid, so just change to use that.
219
- // for now, we are just creating a new key to use it's kid.
220
- // The kid is a part of the JWK system. LR backend maintains the key hierarchy separately with it's own
221
- // key id. But we just use it here as a double check.
222
- kid: yield this.createKid(),
223
- iterations: this.DEFAULT_PASS_KEY_PBKDF_ITER,
224
- };
225
- });
226
- }
227
- }
228
- KeyFactoryService.ɵprov = i0.ɵɵdefineInjectable({ factory: function KeyFactoryService_Factory() { return new KeyFactoryService(i0.ɵɵinject(i1.WebCryptoService)); }, token: KeyFactoryService, providedIn: "root" });
229
- KeyFactoryService.decorators = [
230
- { type: Injectable, args: [{
231
- providedIn: 'root',
232
- },] }
233
- ];
234
- KeyFactoryService.ctorParameters = () => [
235
- { type: WebCryptoService }
236
- ];
237
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LWZhY3Rvcnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJDOi9Qcm9qZWN0cy9rYy1jbGllbnQvcHJvamVjdHMvY29yZS9zcmMvIiwic291cmNlcyI6WyJsaWIvY3J5cHRvZ3JhcGh5L2tleS1mYWN0b3J5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVVoQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN4RCxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHFCQUFxQixHQUN0QixNQUFNLHVCQUF1QixDQUFDOzs7QUFFL0IsTUFBTSxVQUFnQixNQUFNLENBQUMsT0FBTzs7UUFDbEMsa0JBQWtCO1FBQ2xCLE1BQU0sU0FBUyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBELG1CQUFtQjtRQUNuQixNQUFNLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUVwRSwrQkFBK0I7UUFDL0IsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBRXpELDhCQUE4QjtRQUM5QixNQUFNLE9BQU8sR0FBRyxTQUFTO2FBQ3RCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzdDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNaLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7Q0FBQTtBQUtELE1BQU0sT0FBTyxpQkFBaUI7SUFDNUIsWUFBb0IsZ0JBQWtDO1FBQWxDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFJdEQsMkVBQTJFO1FBQzNFLHNDQUFzQztRQUN0QyxpREFBaUQ7UUFFakQsK0VBQStFO1FBQy9FLG1GQUFtRjtRQUNuRixxRkFBcUY7UUFDckYsK0VBQStFO1FBQy9FLGdEQUFnRDtRQUNoQyw0QkFBdUIsR0FBRyxNQUFNLENBQUM7UUFDakMsNEJBQXVCLEdBQUcsTUFBTSxDQUFDO1FBQ2pDLDRCQUF1QixHQUFHLE1BQU0sQ0FBQztRQUVqRCxxRkFBcUY7UUFDckUsZ0NBQTJCLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDO1FBQzNELGdDQUEyQixHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQztRQUMzRCxnQ0FBMkIsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUM7UUFuQnpFLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQztJQUM3QyxDQUFDO0lBb0JELE1BQU0sQ0FBQyxLQUFLLENBQ1YsR0FBMEMsRUFDMUMsSUFRUyxFQUNULE1BQWdDO1FBRWhDLHNFQUFzRTtRQUN0RSw0REFBNEQ7UUFDNUQsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELFlBQVksQ0FBQyxNQUFjO1FBQ3pCLElBQUksTUFBTSxJQUFJLENBQUMsRUFBRTtZQUNmLE1BQU0sSUFBSSxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUNqRDtRQUNELE1BQU0sVUFBVSxHQUNkLGdFQUFnRSxDQUFDO1FBQ25FLElBQUksS0FBSyxHQUFHLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25DLEtBQUssR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUN2RSxPQUFPLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQsbUJBQW1CLENBQUMsTUFBYztRQUNoQyxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRUQsYUFBYSxDQUFJLEtBQVUsRUFBRSxPQUFlO1FBQzFDLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUU7WUFDckIsTUFBTSxJQUFJLHNCQUFzQixDQUFDLG1CQUFtQixDQUFDLENBQUM7U0FDdkQ7UUFDRCxJQUFJLE9BQU8sSUFBSSxDQUFDLEVBQUU7WUFDaEIsTUFBTSxJQUFJLHNCQUFzQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQ2xEO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEMsTUFBTSxHQUFHLEdBQVEsRUFBRSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVLLFNBQVM7O1lBQ2IsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQzlDO2dCQUNFLElBQUksRUFBRSxTQUFTO2dCQUNmLE1BQU0sRUFBRSxHQUFHO2FBQ1osRUFDRCxJQUFJLEVBQUUsaUVBQWlFO1lBQ3ZFLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLDZEQUE2RDthQUNyRixDQUFDO1lBRUYsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBRTNELDhDQUE4QztZQUM5QyxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUM7WUFDZixPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUM7WUFFbkIsT0FBTyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEMsQ0FBQztLQUFBO0lBRUssYUFBYTs7WUFDakIsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQzlDO2dCQUNFLElBQUksRUFBRSxNQUFNO2dCQUNaLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7YUFDMUIsRUFDRCxJQUFJLEVBQ0osQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQ25CLENBQUM7WUFFRixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFFM0QsOENBQThDO1lBQzlDLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQztZQUNuQixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUM7WUFFZixPQUFPLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0QyxDQUFDO0tBQUE7SUFFSyxZQUFZOztZQUNoQixtRkFBbUY7WUFDbkYsMEZBQTBGO1lBQzFGLGtHQUFrRztZQUNsRyxxREFBcUQ7WUFDckQsOEZBQThGO1lBQzlGLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUM5QztnQkFDRSxJQUFJLEVBQUUsVUFBVTtnQkFDaEIsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLDRGQUE0RjtnQkFDNUYsY0FBYyxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDbEQsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTthQUMxQixFQUNELElBQUksRUFBRSxpRUFBaUU7WUFDdkUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUMsNkRBQTZEO2FBQ3JGLENBQUM7WUFFRixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3RFLDhDQUE4QztZQUM5QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUM7WUFDbkIsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDO1lBRWYsT0FBTyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEMsQ0FBQztLQUFBO0lBRUssZ0JBQWdCOztZQUNwQixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FDOUM7Z0JBQ0UsSUFBSSxFQUFFLG1CQUFtQjtnQkFDekIsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLDRGQUE0RjtnQkFDNUYsY0FBYyxFQUFFLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDbEQsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTthQUMxQixFQUNELElBQUksRUFBRSxpRUFBaUU7WUFDdkUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsZ0RBQWdEO2FBQ3BFLENBQUM7WUFFRixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRXRFLDhDQUE4QztZQUM5QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUM7WUFDbkIsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDO1lBRWYsT0FBTyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEMsQ0FBQztLQUFBO0lBRUssU0FBUyxDQUFDLEVBQ2QsUUFBUSxFQUNSLElBQUksRUFDSixVQUFVLEVBQ1YsR0FBRyxHQU1KOztZQUNDLE1BQU0sR0FBRyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7WUFDOUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQy9DLEtBQUssRUFDTCxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUNwQixRQUFRLEVBQ1IsS0FBSyxFQUNMLENBQUMsWUFBWSxFQUFFLFdBQVcsQ0FBQyxDQUM1QixDQUFDO1lBRUYsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FDM0M7Z0JBQ0UsSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsSUFBSSxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztnQkFDcEMsVUFBVTtnQkFDVixJQUFJLEVBQUUsU0FBUzthQUNoQixFQUNELE1BQU0sRUFDTixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUNoQyxJQUFJLEVBQ0osQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQ3ZCLENBQUM7WUFFRixNQUFNLFdBQVcsR0FBUSxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN2RSxJQUFJLEdBQUcsRUFBRTtnQkFDUCxXQUFXLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQzthQUN2QjtZQUVELE1BQU0sR0FBRyxHQUFHLE1BQU0saUJBQWlCLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXZELE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNqQixDQUFDO0tBQUE7SUFFSyxhQUFhLENBQUMsTUFBMkI7O1lBQzdDLElBQUksTUFBTSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLEVBQUU7Z0JBQ3BELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IseUVBQXlFLE1BQU0sQ0FBQyxVQUFVLGdDQUFnQyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsQ0FDMUosQ0FBQzthQUNIO1lBQ0QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hDLENBQUM7S0FBQTtJQUVLLGFBQWEsQ0FBQyxNQUEyQjs7WUFDN0MsSUFBSSxNQUFNLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsRUFBRTtnQkFDcEQsTUFBTSxJQUFJLHFCQUFxQixDQUM3Qix3RUFBd0UsTUFBTSxDQUFDLFVBQVUsK0JBQStCLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxDQUN4SixDQUFDO2FBQ0g7WUFDRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsQ0FBQztLQUFBO0lBRUssYUFBYSxDQUFDLE1BQTJCOztZQUM3QyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixFQUFFO2dCQUNwRCxNQUFNLElBQUkscUJBQXFCLENBQzdCLHdFQUF3RSxNQUFNLENBQUMsVUFBVSwrQkFBK0IsSUFBSSxDQUFDLHVCQUF1QixHQUFHLENBQ3hKLENBQUM7YUFDSDtZQUNELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxDQUFDO0tBQUE7SUFFSyxTQUFTOztZQUNiLHNHQUFzRztZQUN0RywyREFBMkQ7WUFDM0QsdUdBQXVHO1lBQ3ZHLHFEQUFxRDtZQUNyRCxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDdEMsQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixVQUFVLEVBQUUsSUFBSSxDQUFDLDJCQUEyQjthQUM3QyxDQUFDO1FBQ0osQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixHQUFHLEVBQUUsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUMzQixVQUFVLEVBQUUsSUFBSSxDQUFDLDJCQUEyQjthQUM3QyxDQUFDO1FBQ0osQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixzR0FBc0c7Z0JBQ3RHLDJEQUEyRDtnQkFDM0QsdUdBQXVHO2dCQUN2RyxxREFBcUQ7Z0JBQ3JELEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQzNCLFVBQVUsRUFBRSxJQUFJLENBQUMsMkJBQTJCO2FBQzdDLENBQUM7UUFDSixDQUFDO0tBQUE7Ozs7WUEzUUYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7WUF6QlEsZ0JBQWdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBKV0sgfSBmcm9tICdub2RlLWpvc2UnO1xyXG5pbXBvcnQge1xyXG4gIExib3BLZXlQYXJhbXMsXHJcbiAgUGFzc0lkcFBhcmFtcyxcclxuICBQYXNzS2V5UGFyYW1zLFxyXG4gIERlcml2ZUtleVJlc3VsdCxcclxuICBEZXJpdmVQYXNzSWRwUGFyYW1zLFxyXG4gIERlcml2ZVBhc3NLZXlQYXJhbXMsXHJcbiAgRGVyaXZlTGJvcEtleVBhcmFtcyxcclxufSBmcm9tICcuL2NyeXB0b2dyYXBoeS50eXBlcyc7XHJcbmltcG9ydCB7IFdlYkNyeXB0b1NlcnZpY2UgfSBmcm9tICcuL3dlYi1jcnlwdG8uc2VydmljZSc7XHJcbmltcG9ydCB7XHJcbiAgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbixcclxuICBMclN1c3BpY2lvdXNFeGNlcHRpb24sXHJcbn0gZnJvbSAnLi4vX2NvbW1vbi9leGNlcHRpb25zJztcclxuXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaGEyNTYobWVzc2FnZSkge1xyXG4gIC8vIGVuY29kZSBhcyBVVEYtOFxyXG4gIGNvbnN0IG1zZ0J1ZmZlciA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShtZXNzYWdlKTtcclxuXHJcbiAgLy8gaGFzaCB0aGUgbWVzc2FnZVxyXG4gIGNvbnN0IGhhc2hCdWZmZXIgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRpZ2VzdCgnU0hBLTI1NicsIG1zZ0J1ZmZlcik7XHJcblxyXG4gIC8vIGNvbnZlcnQgQXJyYXlCdWZmZXIgdG8gQXJyYXlcclxuICBjb25zdCBoYXNoQXJyYXkgPSBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGhhc2hCdWZmZXIpKTtcclxuXHJcbiAgLy8gY29udmVydCBieXRlcyB0byBoZXggc3RyaW5nXHJcbiAgY29uc3QgaGFzaEhleCA9IGhhc2hBcnJheVxyXG4gICAgLm1hcCgoYikgPT4gKCcwMCcgKyBiLnRvU3RyaW5nKDE2KSkuc2xpY2UoLTIpKVxyXG4gICAgLmpvaW4oJycpO1xyXG4gIHJldHVybiBoYXNoSGV4O1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgS2V5RmFjdG9yeVNlcnZpY2Uge1xyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgd2ViQ3J5cHRvU2VydmljZTogV2ViQ3J5cHRvU2VydmljZSkge1xyXG4gICAgdGhpcy5jcnlwdG8gPSB0aGlzLndlYkNyeXB0b1NlcnZpY2UuY3J5cHRvO1xyXG4gIH1cclxuICBwcml2YXRlIHJlYWRvbmx5IGNyeXB0bztcclxuICAvLyBHbG9iYWwga2V5cyBzdG9yZS4gT3RoZXJ3aXNlLCBlYWNoIGNhbGwgdG8gYXNLZXkgY3JlYXRlcyBhIG5ldyBrZXlTdG9yZS5cclxuICAvLyA8QVo+IERpZCBub3Qgc2VlbSB0byBpbXByb3ZlIHNwZWVkLlxyXG4gIC8vIHB1YmxpYyBzdGF0aWMga2V5U3RvcmUgPSBKV0suY3JlYXRlS2V5U3RvcmUoKTtcclxuXHJcbiAgLy8gQVo6IFRoaXMgY2FuJ3QgYmUgY2hhbmdlIGVhc2lseS4gSXQncyBiYXNpY2FsbHkgYSBQYXNzSyBvciBQYXNzSWRwIHJvdGF0aW9uLlxyXG4gIC8vIHRvZG86IHdlIHNob3VsZCBldmVudHVhbGx5IGluY3JlYXNlIHRoaXMgcGVyaW9kaWNhbGx5IHRvIG1hdGNoIHdpdGggTW9vcmUncyBsYXcuXHJcbiAgLy8gVGhlIGl0ZXJhdGlvbnMgZm9yIGVhY2gga2V5IGFyZSBrZXB0IGJ5IHRoZSBzZXJ2ZXIgYXMgd2VsbCBidXQgd2UgYXNzdW1lIHRoZSB2YWx1ZVxyXG4gIC8vIGZyb20gdGhlIHNlcnZlciBpcyBub3QgdHJ1c3R3b3J0aHksIHNvIG5lZWQgdG8gaGF2ZSBtaW5pbXVtIHRocmVzaG9sZHMgaGVyZS5cclxuICAvLyBJZiBjcmVhdGluZyBuZXcga2V5cywgdGhlc2UgbWluaW11bSBhcmUgdXNlZC5cclxuICBwdWJsaWMgcmVhZG9ubHkgTUlOX1BBU1NfSURQX1BCS0RGX0lURVIgPSAxMDAwMDA7XHJcbiAgcHVibGljIHJlYWRvbmx5IE1JTl9QQVNTX0tFWV9QQktERl9JVEVSID0gMTAwMDAwO1xyXG4gIHB1YmxpYyByZWFkb25seSBNSU5fTEJPUF9LRVlfUEJLREZfSVRFUiA9IDEwMDAwMDtcclxuXHJcbiAgLy8gVGhlc2UgYXJlIHVzZWQgYXMgdGhlIGRlZmF1bHQgdmFsdWVzLiBUaGV5IG11c3QgYmUgbGFyZ2VyIHRoYW4gdGhlIG1pbmltdW0gdmFsdWVzLlxyXG4gIHB1YmxpYyByZWFkb25seSBERUZBVUxUX1BBU1NfSURQX1BCS0RGX0lURVIgPSB0aGlzLk1JTl9QQVNTX0lEUF9QQktERl9JVEVSO1xyXG4gIHB1YmxpYyByZWFkb25seSBERUZBVUxUX1BBU1NfS0VZX1BCS0RGX0lURVIgPSB0aGlzLk1JTl9QQVNTX0tFWV9QQktERl9JVEVSO1xyXG4gIHB1YmxpYyByZWFkb25seSBERUZBVUxUX0xCT1BfS0VZX1BCS0RGX0lURVIgPSB0aGlzLk1JTl9MQk9QX0tFWV9QQktERl9JVEVSO1xyXG5cclxuICBzdGF0aWMgYXNLZXkoXHJcbiAgICBrZXk6IHN0cmluZyB8IEJ1ZmZlciB8IG9iamVjdCB8IEpXSy5SYXdLZXksXHJcbiAgICBmb3JtPzpcclxuICAgICAgfCAnanNvbidcclxuICAgICAgfCAncHJpdmF0ZSdcclxuICAgICAgfCAncGtjczgnXHJcbiAgICAgIHwgJ3B1YmxpYydcclxuICAgICAgfCAnc3BraSdcclxuICAgICAgfCAncGtpeCdcclxuICAgICAgfCAneDUwOSdcclxuICAgICAgfCAncGVtJyxcclxuICAgIGV4dHJhcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbiAgKTogUHJvbWlzZTxKV0suS2V5PiB7XHJcbiAgICAvLyA8QVo+IFVzaW5nIGEgc2luZ2xlIGdsb2JhbCBrZXkgc3RvcmUgZGlkIG5vdCBzZWVtIHRvIGltcHJvdmUgc3BlZWQuXHJcbiAgICAvLyByZXR1cm4gS2V5RmFjdG9yeVNlcnZpY2Uua2V5U3RvcmUuYWRkKGtleSwgZm9ybSwgZXh0cmFzKTtcclxuICAgIHJldHVybiBKV0suYXNLZXkoa2V5LCBmb3JtLCBleHRyYXMpO1xyXG4gIH1cclxuXHJcbiAgcmFuZG9tU3RyaW5nKGRpZ2l0czogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIGlmIChkaWdpdHMgPD0gMCkge1xyXG4gICAgICB0aHJvdyBuZXcgTHJCYWRBcmd1bWVudEV4Y2VwdGlvbignZGlnaXRzIDw9IDAnKTtcclxuICAgIH1cclxuICAgIGNvbnN0IHZhbGlkQ2hhcnMgPVxyXG4gICAgICAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xyXG4gICAgbGV0IGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KGRpZ2l0cyk7XHJcbiAgICB0aGlzLmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpO1xyXG4gICAgYXJyYXkgPSBhcnJheS5tYXAoKHgpID0+IHZhbGlkQ2hhcnMuY2hhckNvZGVBdCh4ICUgdmFsaWRDaGFycy5sZW5ndGgpKTtcclxuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGFycmF5KTtcclxuICB9XHJcblxyXG4gIHJhbmRvbURpZ2l0c05vWmVyb3MoZGlnaXRzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMucmFuZG9tQ2hvaWNlcyhbMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOV0sIGRpZ2l0cykuam9pbignJyk7XHJcbiAgfVxyXG5cclxuICByYW5kb21DaG9pY2VzPFQ+KGFycmF5OiBUW10sIGNob29zZU46IG51bWJlcik6IFRbXSB7XHJcbiAgICBpZiAoYXJyYXkubGVuZ3RoIDw9IDEpIHtcclxuICAgICAgdGhyb3cgbmV3IExyQmFkQXJndW1lbnRFeGNlcHRpb24oJ2FycmF5Lmxlbmd0aCA8PSAwJyk7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hvb3NlTiA8PSAwKSB7XHJcbiAgICAgIHRocm93IG5ldyBMckJhZEFyZ3VtZW50RXhjZXB0aW9uKCdjaG9vc2VOIDw9IDAnKTtcclxuICAgIH1cclxuICAgIGNvbnN0IHZhbHVlcyA9IG5ldyBVaW50MzJBcnJheShjaG9vc2VOKTtcclxuICAgIHRoaXMuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyh2YWx1ZXMpO1xyXG4gICAgY29uc3QgcmV0OiBUW10gPSBbXTtcclxuICAgIHZhbHVlcy5mb3JFYWNoKCh2KSA9PiByZXQucHVzaChhcnJheVt2ICUgYXJyYXkubGVuZ3RoXSkpO1xyXG4gICAgcmV0dXJuIHJldDtcclxuICB9XHJcblxyXG4gIGNyZWF0ZVNhbHQoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLnJhbmRvbVN0cmluZygxNik7XHJcbiAgfVxyXG5cclxuICBhc3luYyBjcmVhdGVLZXkoKTogUHJvbWlzZTxKV0suS2V5PiB7XHJcbiAgICBjb25zdCBrZXkgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuZ2VuZXJhdGVLZXkoXHJcbiAgICAgIHtcclxuICAgICAgICBuYW1lOiAnQUVTLUdDTScsXHJcbiAgICAgICAgbGVuZ3RoOiAyNTYsIC8vIGNhbiBiZSAgMTI4LCAxOTIsIG9yIDI1NlxyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLCAvLyB3aGV0aGVyIHRoZSBrZXkgaXMgZXh0cmFjdGFibGUgKGkuZS4gY2FuIGJlIHVzZWQgaW4gZXhwb3J0S2V5KVxyXG4gICAgICBbJ2VuY3J5cHQnLCAnZGVjcnlwdCddIC8vIG11c3QgYmUgW1wiZW5jcnlwdFwiLCBcImRlY3J5cHRcIl0gb3IgW1wid3JhcEtleVwiLCBcInVud3JhcEtleVwiXVxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBqd2sgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuZXhwb3J0S2V5KCdqd2snLCBrZXkpO1xyXG5cclxuICAgIC8vIFJlbW92aW5nIHRoZSBmaWVsZHMgbm90IG5lZWRlZCBieSBub2RlLWpvc2VcclxuICAgIGRlbGV0ZSBqd2suZXh0O1xyXG4gICAgZGVsZXRlIGp3ay5rZXlfb3BzO1xyXG5cclxuICAgIHJldHVybiBLZXlGYWN0b3J5U2VydmljZS5hc0tleShqd2spO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgY3JlYXRlU2lnbktleSgpOiBQcm9taXNlPEpXSy5LZXk+IHtcclxuICAgIGNvbnN0IGtleSA9IGF3YWl0IHRoaXMuY3J5cHRvLnN1YnRsZS5nZW5lcmF0ZUtleShcclxuICAgICAge1xyXG4gICAgICAgIG5hbWU6ICdITUFDJyxcclxuICAgICAgICBoYXNoOiB7IG5hbWU6ICdTSEEtNTEyJyB9LFxyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLFxyXG4gICAgICBbJ3NpZ24nLCAndmVyaWZ5J11cclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgandrID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmV4cG9ydEtleSgnandrJywga2V5KTtcclxuXHJcbiAgICAvLyBSZW1vdmluZyB0aGUgZmllbGRzIG5vdCBuZWVkZWQgYnkgbm9kZS1qb3NlXHJcbiAgICBkZWxldGUgandrLmtleV9vcHM7XHJcbiAgICBkZWxldGUgandrLmV4dDtcclxuXHJcbiAgICByZXR1cm4gS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoandrKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGNyZWF0ZVBrY0tleSgpOiBQcm9taXNlPEpXSy5LZXk+IHtcclxuICAgIC8vIG5vZGUtam9zZSBpcyBub3QgdXNpbmcgRm9yZ2UgcHJvcGVybHkuIEl0IHNob3VsZCBiZSBjYWxsaW5nIHRoZSBhc3luYyB2ZXJzaW9uIG9mXHJcbiAgICAvLyBwa2kucnNhLmdlbmVyYXRlS2V5UGFpcigpIHdpdGggYSBjYWxsYmFjay4gSW5zdGVhZCBpdCBjYWxscyB0aGUgc3luYyB2ZXJzaW9uLiBXZWJjcnlwdG9cclxuICAgIC8vIGRvZXMgbm90IHN1cHBvcnQgc3luYyB2ZXJzaW9uLCBzbyBpdCB1c2VzIHRoZSBqYXZhc2NyaXB0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyB3YXkgdG9vIHNsb3cuXHJcbiAgICAvLyBTbyB3ZSBnZW5lcmF0ZSB1c2luZyB3ZWJjcnlwdG8gYW5kIGltcG9ydCB0aGUga2V5LlxyXG4gICAgLy8gVW5mb3J0dW5hdGVseSBFbGxpcHRpY2FsIEN1cnZlIGlzIG5vdCBzdXBwb3J0ZWQgYnkgV2ViY3J5cHRvLiBTbyB3ZSBoYXZlIHRvIHNldHRsZSBmb3IgUlNBLlxyXG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmdlbmVyYXRlS2V5KFxyXG4gICAgICB7XHJcbiAgICAgICAgbmFtZTogJ1JTQS1PQUVQJyxcclxuICAgICAgICBtb2R1bHVzTGVuZ3RoOiAyMDQ4LCAvLyBjYW4gYmUgMTAyNCwgMjA0OCwgMzA3MiwgNDA5NiAuLi4gMTYzODRcclxuICAgICAgICAvLyBBcyBwZXIgc3VnZ2VzdGlvbjogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JzYUhhc2hlZEtleUdlblBhcmFtc1xyXG4gICAgICAgIHB1YmxpY0V4cG9uZW50OiBuZXcgVWludDhBcnJheShbMHgwMSwgMHgwMCwgMHgwMV0pLFxyXG4gICAgICAgIGhhc2g6IHsgbmFtZTogJ1NIQS0yNTYnIH0sIC8vIGNhbiBiZSBcIlNIQS0xXCIsIFwiU0hBLTI1NlwiLCBcIlNIQS0zODRcIiwgb3IgXCJTSEEtNTEyXCJcclxuICAgICAgfSxcclxuICAgICAgdHJ1ZSwgLy8gd2hldGhlciB0aGUga2V5IGlzIGV4dHJhY3RhYmxlIChpLmUuIGNhbiBiZSB1c2VkIGluIGV4cG9ydEtleSlcclxuICAgICAgWydlbmNyeXB0JywgJ2RlY3J5cHQnXSAvLyBtdXN0IGJlIFtcImVuY3J5cHRcIiwgXCJkZWNyeXB0XCJdIG9yIFtcIndyYXBLZXlcIiwgXCJ1bndyYXBLZXlcIl1cclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgandrID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmV4cG9ydEtleSgnandrJywga2V5LnByaXZhdGVLZXkpO1xyXG4gICAgLy8gUmVtb3ZpbmcgdGhlIGZpZWxkcyBub3QgbmVlZGVkIGJ5IG5vZGUtam9zZVxyXG4gICAgZGVsZXRlIGp3ay5rZXlfb3BzO1xyXG4gICAgZGVsZXRlIGp3ay5leHQ7XHJcblxyXG4gICAgcmV0dXJuIEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KGp3ayk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBjcmVhdGVQa2NTaWduS2V5KCk6IFByb21pc2U8SldLLktleT4ge1xyXG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmdlbmVyYXRlS2V5KFxyXG4gICAgICB7XHJcbiAgICAgICAgbmFtZTogJ1JTQVNTQS1QS0NTMS12MV81JyxcclxuICAgICAgICBtb2R1bHVzTGVuZ3RoOiAyMDQ4LCAvLyBjYW4gYmUgMTAyNCwgMjA0OCwgb3IgNDA5NlxyXG4gICAgICAgIC8vIEFzIHBlciBzdWdnZXN0aW9uOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUnNhSGFzaGVkS2V5R2VuUGFyYW1zXHJcbiAgICAgICAgcHVibGljRXhwb25lbnQ6IG5ldyBVaW50OEFycmF5KFsweDAxLCAweDAwLCAweDAxXSksXHJcbiAgICAgICAgaGFzaDogeyBuYW1lOiAnU0hBLTI1NicgfSwgLy8gY2FuIGJlIFwiU0hBLTFcIiwgXCJTSEEtMjU2XCIsIFwiU0hBLTM4NFwiLCBvciBcIlNIQS01MTJcIlxyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLCAvLyB3aGV0aGVyIHRoZSBrZXkgaXMgZXh0cmFjdGFibGUgKGkuZS4gY2FuIGJlIHVzZWQgaW4gZXhwb3J0S2V5KVxyXG4gICAgICBbJ3NpZ24nLCAndmVyaWZ5J10gLy8gY2FuIGJlIGFueSBjb21iaW5hdGlvbiBvZiBcInNpZ25cIiBhbmQgXCJ2ZXJpZnlcIlxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBqd2sgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuZXhwb3J0S2V5KCdqd2snLCBrZXkucHJpdmF0ZUtleSk7XHJcblxyXG4gICAgLy8gUmVtb3ZpbmcgdGhlIGZpZWxkcyBub3QgbmVlZGVkIGJ5IG5vZGUtam9zZVxyXG4gICAgZGVsZXRlIGp3ay5rZXlfb3BzO1xyXG4gICAgZGVsZXRlIGp3ay5leHQ7XHJcblxyXG4gICAgcmV0dXJuIEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KGp3ayk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBkZXJpdmVLZXkoe1xyXG4gICAgcGFzc3dvcmQsXHJcbiAgICBzYWx0LFxyXG4gICAgaXRlcmF0aW9ucyxcclxuICAgIGtpZCxcclxuICB9OiB7XHJcbiAgICBwYXNzd29yZDogc3RyaW5nO1xyXG4gICAgc2FsdDogc3RyaW5nO1xyXG4gICAgaXRlcmF0aW9uczogbnVtYmVyO1xyXG4gICAga2lkPzogc3RyaW5nO1xyXG4gIH0pOiBQcm9taXNlPERlcml2ZUtleVJlc3VsdD4ge1xyXG4gICAgY29uc3QgZW5jID0gbmV3IFRleHRFbmNvZGVyKCk7XHJcbiAgICBjb25zdCByYXdLZXkgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuaW1wb3J0S2V5KFxyXG4gICAgICAncmF3JyxcclxuICAgICAgZW5jLmVuY29kZShwYXNzd29yZCksXHJcbiAgICAgICdQQktERjInLFxyXG4gICAgICBmYWxzZSxcclxuICAgICAgWydkZXJpdmVCaXRzJywgJ2Rlcml2ZUtleSddXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IHBhc3NLZXkgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRlcml2ZUtleShcclxuICAgICAge1xyXG4gICAgICAgIG5hbWU6ICdQQktERjInLFxyXG4gICAgICAgIHNhbHQ6IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzYWx0KSxcclxuICAgICAgICBpdGVyYXRpb25zLFxyXG4gICAgICAgIGhhc2g6ICdTSEEtMjU2JyxcclxuICAgICAgfSxcclxuICAgICAgcmF3S2V5LFxyXG4gICAgICB7IG5hbWU6ICdBRVMtR0NNJywgbGVuZ3RoOiAyNTYgfSxcclxuICAgICAgdHJ1ZSxcclxuICAgICAgWydlbmNyeXB0JywgJ2RlY3J5cHQnXVxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBwYXNzS2V5SnNvbjogYW55ID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5leHBvcnRLZXkoJ2p3aycsIHBhc3NLZXkpO1xyXG4gICAgaWYgKGtpZCkge1xyXG4gICAgICBwYXNzS2V5SnNvbi5raWQgPSBraWQ7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgandrID0gYXdhaXQgS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkocGFzc0tleUpzb24pO1xyXG5cclxuICAgIHJldHVybiB7IGp3ayB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZGVyaXZlUGFzc0lkcChwYXJhbXM6IERlcml2ZVBhc3NJZHBQYXJhbXMpOiBQcm9taXNlPERlcml2ZUtleVJlc3VsdD4ge1xyXG4gICAgaWYgKHBhcmFtcy5pdGVyYXRpb25zIDwgdGhpcy5NSU5fUEFTU19JRFBfUEJLREZfSVRFUikge1xyXG4gICAgICB0aHJvdyBuZXcgTHJTdXNwaWNpb3VzRXhjZXB0aW9uKFxyXG4gICAgICAgIGBUaGUgbnVtYmVyIG9mIFBhc3NJZHAga2V5IGRlcml2YXRpb24gaXRlcmF0aW9ucyBzZW50IGZyb20gdGhlIHNlcnZlciAoJHtwYXJhbXMuaXRlcmF0aW9uc30pIGlzIGxvd2VyIHRoYW4gdGhlIG1pbmltdW0gKCR7dGhpcy5NSU5fUEFTU19JRFBfUEJLREZfSVRFUn0pYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuZGVyaXZlS2V5KHBhcmFtcyk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBkZXJpdmVQYXNzS2V5KHBhcmFtczogRGVyaXZlUGFzc0tleVBhcmFtcyk6IFByb21pc2U8RGVyaXZlS2V5UmVzdWx0PiB7XHJcbiAgICBpZiAocGFyYW1zLml0ZXJhdGlvbnMgPCB0aGlzLk1JTl9QQVNTX0tFWV9QQktERl9JVEVSKSB7XHJcbiAgICAgIHRocm93IG5ldyBMclN1c3BpY2lvdXNFeGNlcHRpb24oXHJcbiAgICAgICAgYFRoZSBudW1iZXIgb2YgUGFzc0tleSBrZXkgZGVyaXZhdGlvbiBpdGVyYXRpb25zIHNlbnQgZnJvbSB0aGUgc2VydmVyKCR7cGFyYW1zLml0ZXJhdGlvbnN9KSBpcyBsb3dlciB0aGFuIHRoZSBtaW5pbXVtKCR7dGhpcy5NSU5fUEFTU19LRVlfUEJLREZfSVRFUn0pYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuZGVyaXZlS2V5KHBhcmFtcyk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBkZXJpdmVMYm9wS2V5KHBhcmFtczogRGVyaXZlTGJvcEtleVBhcmFtcyk6IFByb21pc2U8RGVyaXZlS2V5UmVzdWx0PiB7XHJcbiAgICBpZiAocGFyYW1zLml0ZXJhdGlvbnMgPCB0aGlzLk1JTl9MQk9QX0tFWV9QQktERl9JVEVSKSB7XHJcbiAgICAgIHRocm93IG5ldyBMclN1c3BpY2lvdXNFeGNlcHRpb24oXHJcbiAgICAgICAgYFRoZSBudW1iZXIgb2YgTGJvcEtleSBrZXkgZGVyaXZhdGlvbiBpdGVyYXRpb25zIHNlbnQgZnJvbSB0aGUgc2VydmVyKCR7cGFyYW1zLml0ZXJhdGlvbnN9KSBpcyBsb3dlciB0aGFuIHRoZSBtaW5pbXVtKCR7dGhpcy5NSU5fTEJPUF9LRVlfUEJLREZfSVRFUn0pYFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuZGVyaXZlS2V5KHBhcmFtcyk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBjcmVhdGVLaWQoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgIC8vIHRvZG86IEFaOiBub2RlLWpvc2Ugc291cmNlIHVzZXMgbm9kZSdzIGRlZmF1bHQgVVVJRCgpIGZ1bmN0aW9uIGZvciBraWQsIHNvIGp1c3QgY2hhbmdlIHRvIHVzZSB0aGF0LlxyXG4gICAgLy8gZm9yIG5vdywgd2UgYXJlIGp1c3QgY3JlYXRpbmcgYSBuZXcga2V5IHRvIHVzZSBpdCdzIGtpZC5cclxuICAgIC8vIFRoZSBraWQgaXMgYSBwYXJ0IG9mIHRoZSBKV0sgc3lzdGVtLiBMUiBiYWNrZW5kIG1haW50YWlucyB0aGUga2V5IGhpZXJhcmNoeSBzZXBhcmF0ZWx5IHdpdGggaXQncyBvd25cclxuICAgIC8vIGtleSBpZC4gQnV0IHdlIGp1c3QgdXNlIGl0IGhlcmUgYXMgYSBkb3VibGUgY2hlY2suXHJcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuY3JlYXRlS2V5KCkpLmtpZDtcclxuICB9XHJcblxyXG4gIGFzeW5jIGNyZWF0ZVBhc3NJZHBQYXJhbXMoKTogUHJvbWlzZTxQYXNzSWRwUGFyYW1zPiB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBzYWx0OiB0aGlzLmNyZWF0ZVNhbHQoKSxcclxuICAgICAgaXRlcmF0aW9uczogdGhpcy5ERUZBVUxUX1BBU1NfSURQX1BCS0RGX0lURVIsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgY3JlYXRlUGFzc0tleVBhcmFtcygpOiBQcm9taXNlPFBhc3NLZXlQYXJhbXM+IHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIHNhbHQ6IHRoaXMuY3JlYXRlU2FsdCgpLFxyXG4gICAgICBraWQ6IGF3YWl0IHRoaXMuY3JlYXRlS2lkKCksXHJcbiAgICAgIGl0ZXJhdGlvbnM6IHRoaXMuREVGQVVMVF9QQVNTX0tFWV9QQktERl9JVEVSLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGNyZWF0ZUxib3BLZXlQYXJhbXMoKTogUHJvbWlzZTxMYm9wS2V5UGFyYW1zPiB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBzYWx0OiB0aGlzLmNyZWF0ZVNhbHQoKSxcclxuICAgICAgLy8gdG9kbzogQVo6IG5vZGUtam9zZSBzb3VyY2UgdXNlcyBub2RlJ3MgZGVmYXVsdCBVVUlEKCkgZnVuY3Rpb24gZm9yIGtpZCwgc28ganVzdCBjaGFuZ2UgdG8gdXNlIHRoYXQuXHJcbiAgICAgIC8vIGZvciBub3csIHdlIGFyZSBqdXN0IGNyZWF0aW5nIGEgbmV3IGtleSB0byB1c2UgaXQncyBraWQuXHJcbiAgICAgIC8vIFRoZSBraWQgaXMgYSBwYXJ0IG9mIHRoZSBKV0sgc3lzdGVtLiBMUiBiYWNrZW5kIG1haW50YWlucyB0aGUga2V5IGhpZXJhcmNoeSBzZXBhcmF0ZWx5IHdpdGggaXQncyBvd25cclxuICAgICAgLy8ga2V5IGlkLiBCdXQgd2UganVzdCB1c2UgaXQgaGVyZSBhcyBhIGRvdWJsZSBjaGVjay5cclxuICAgICAga2lkOiBhd2FpdCB0aGlzLmNyZWF0ZUtpZCgpLFxyXG4gICAgICBpdGVyYXRpb25zOiB0aGlzLkRFRkFVTFRfUEFTU19LRVlfUEJLREZfSVRFUixcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiJdfQ==
1
+ import { __awaiter } from "tslib";
2
+ import { Injectable } from '@angular/core';
3
+ import { JWK } from 'node-jose';
4
+ import { WebCryptoService } from './web-crypto.service';
5
+ import { LrBadArgumentException, LrSuspiciousException, } from '../_common/exceptions';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "./web-crypto.service";
8
+ export function sha256(message) {
9
+ return __awaiter(this, void 0, void 0, function* () {
10
+ // encode as UTF-8
11
+ const msgBuffer = new TextEncoder().encode(message);
12
+ // hash the message
13
+ const hashBuffer = yield crypto.subtle.digest('SHA-256', msgBuffer);
14
+ // convert ArrayBuffer to Array
15
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
16
+ // convert bytes to hex string
17
+ const hashHex = hashArray
18
+ .map((b) => ('00' + b.toString(16)).slice(-2))
19
+ .join('');
20
+ return hashHex;
21
+ });
22
+ }
23
+ export class KeyFactoryService {
24
+ constructor(webCryptoService) {
25
+ this.webCryptoService = webCryptoService;
26
+ // Global keys store. Otherwise, each call to asKey creates a new keyStore.
27
+ // <AZ> Did not seem to improve speed.
28
+ // public static keyStore = JWK.createKeyStore();
29
+ // AZ: This can't be change easily. It's basically a PassK or PassIdp rotation.
30
+ // todo: we should eventually increase this periodically to match with Moore's law.
31
+ // The iterations for each key are kept by the server as well but we assume the value
32
+ // from the server is not trustworthy, so need to have minimum thresholds here.
33
+ // If creating new keys, these minimum are used.
34
+ this.MIN_PASS_IDP_PBKDF_ITER = 100000;
35
+ this.MIN_PASS_KEY_PBKDF_ITER = 100000;
36
+ this.MIN_LBOP_KEY_PBKDF_ITER = 100000;
37
+ // These are used as the default values. They must be larger than the minimum values.
38
+ this.DEFAULT_PASS_IDP_PBKDF_ITER = this.MIN_PASS_IDP_PBKDF_ITER;
39
+ this.DEFAULT_PASS_KEY_PBKDF_ITER = this.MIN_PASS_KEY_PBKDF_ITER;
40
+ this.DEFAULT_LBOP_KEY_PBKDF_ITER = this.MIN_LBOP_KEY_PBKDF_ITER;
41
+ this.crypto = this.webCryptoService.crypto;
42
+ }
43
+ static asKey(key, form, extras) {
44
+ // <AZ> Using a single global key store did not seem to improve speed.
45
+ // return KeyFactoryService.keyStore.add(key, form, extras);
46
+ return JWK.asKey(key, form, extras);
47
+ }
48
+ randomString(digits) {
49
+ if (digits <= 0) {
50
+ throw new LrBadArgumentException('digits <= 0');
51
+ }
52
+ const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
53
+ let array = new Uint32Array(digits);
54
+ this.crypto.getRandomValues(array);
55
+ array = array.map((x) => validChars.charCodeAt(x % validChars.length));
56
+ return String.fromCharCode.apply(null, array);
57
+ }
58
+ randomDigitsNoZeros(digits) {
59
+ return this.randomChoices([1, 2, 3, 4, 5, 6, 7, 8, 9], digits).join('');
60
+ }
61
+ randomChoices(array, chooseN) {
62
+ if (array.length <= 1) {
63
+ throw new LrBadArgumentException('array.length <= 0');
64
+ }
65
+ if (chooseN <= 0) {
66
+ throw new LrBadArgumentException('chooseN <= 0');
67
+ }
68
+ const values = new Uint32Array(chooseN);
69
+ this.crypto.getRandomValues(values);
70
+ const ret = [];
71
+ values.forEach((v) => ret.push(array[v % array.length]));
72
+ return ret;
73
+ }
74
+ createSalt() {
75
+ return this.randomString(16);
76
+ }
77
+ createKey() {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ const key = yield this.crypto.subtle.generateKey({
80
+ name: 'AES-GCM',
81
+ length: 256,
82
+ }, true, // whether the key is extractable (i.e. can be used in exportKey)
83
+ ['encrypt', 'decrypt'] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
84
+ );
85
+ const jwk = yield this.crypto.subtle.exportKey('jwk', key);
86
+ // Removing the fields not needed by node-jose
87
+ delete jwk.ext;
88
+ delete jwk.key_ops;
89
+ return KeyFactoryService.asKey(jwk);
90
+ });
91
+ }
92
+ createSignKey() {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ const key = yield this.crypto.subtle.generateKey({
95
+ name: 'HMAC',
96
+ hash: { name: 'SHA-512' },
97
+ }, true, ['sign', 'verify']);
98
+ const jwk = yield this.crypto.subtle.exportKey('jwk', key);
99
+ // Removing the fields not needed by node-jose
100
+ delete jwk.key_ops;
101
+ delete jwk.ext;
102
+ return KeyFactoryService.asKey(jwk);
103
+ });
104
+ }
105
+ createPkcKey() {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ // node-jose is not using Forge properly. It should be calling the async version of
108
+ // pki.rsa.generateKeyPair() with a callback. Instead it calls the sync version. Webcrypto
109
+ // does not support sync version, so it uses the javascript implementation, which is way too slow.
110
+ // So we generate using webcrypto and import the key.
111
+ // Unfortunately Elliptical Curve is not supported by Webcrypto. So we have to settle for RSA.
112
+ const key = yield this.crypto.subtle.generateKey({
113
+ name: 'RSA-OAEP',
114
+ modulusLength: 2048,
115
+ // As per suggestion: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
116
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
117
+ hash: { name: 'SHA-256' },
118
+ }, true, // whether the key is extractable (i.e. can be used in exportKey)
119
+ ['encrypt', 'decrypt'] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
120
+ );
121
+ const jwk = yield this.crypto.subtle.exportKey('jwk', key.privateKey);
122
+ // Removing the fields not needed by node-jose
123
+ delete jwk.key_ops;
124
+ delete jwk.ext;
125
+ return KeyFactoryService.asKey(jwk);
126
+ });
127
+ }
128
+ createPkcSignKey() {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ const key = yield this.crypto.subtle.generateKey({
131
+ name: 'RSASSA-PKCS1-v1_5',
132
+ modulusLength: 2048,
133
+ // As per suggestion: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
134
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
135
+ hash: { name: 'SHA-256' },
136
+ }, true, // whether the key is extractable (i.e. can be used in exportKey)
137
+ ['sign', 'verify'] // can be any combination of "sign" and "verify"
138
+ );
139
+ const jwk = yield this.crypto.subtle.exportKey('jwk', key.privateKey);
140
+ // Removing the fields not needed by node-jose
141
+ delete jwk.key_ops;
142
+ delete jwk.ext;
143
+ return KeyFactoryService.asKey(jwk);
144
+ });
145
+ }
146
+ deriveKey({ password, salt, iterations, kid, }) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const enc = new TextEncoder();
149
+ const rawKey = yield this.crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveBits', 'deriveKey']);
150
+ const passKey = yield crypto.subtle.deriveKey({
151
+ name: 'PBKDF2',
152
+ salt: new TextEncoder().encode(salt),
153
+ iterations,
154
+ hash: 'SHA-256',
155
+ }, rawKey, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
156
+ const passKeyJson = yield crypto.subtle.exportKey('jwk', passKey);
157
+ if (kid) {
158
+ passKeyJson.kid = kid;
159
+ }
160
+ const jwk = yield KeyFactoryService.asKey(passKeyJson);
161
+ return { jwk };
162
+ });
163
+ }
164
+ derivePassIdp(params) {
165
+ return __awaiter(this, void 0, void 0, function* () {
166
+ if (params.iterations < this.MIN_PASS_IDP_PBKDF_ITER) {
167
+ throw new LrSuspiciousException(`The number of PassIdp key derivation iterations sent from the server (${params.iterations}) is lower than the minimum (${this.MIN_PASS_IDP_PBKDF_ITER})`);
168
+ }
169
+ return this.deriveKey(params);
170
+ });
171
+ }
172
+ derivePassKey(params) {
173
+ return __awaiter(this, void 0, void 0, function* () {
174
+ if (params.iterations < this.MIN_PASS_KEY_PBKDF_ITER) {
175
+ throw new LrSuspiciousException(`The number of PassKey key derivation iterations sent from the server(${params.iterations}) is lower than the minimum(${this.MIN_PASS_KEY_PBKDF_ITER})`);
176
+ }
177
+ return this.deriveKey(params);
178
+ });
179
+ }
180
+ deriveLbopKey(params) {
181
+ return __awaiter(this, void 0, void 0, function* () {
182
+ if (params.iterations < this.MIN_LBOP_KEY_PBKDF_ITER) {
183
+ throw new LrSuspiciousException(`The number of LbopKey key derivation iterations sent from the server(${params.iterations}) is lower than the minimum(${this.MIN_LBOP_KEY_PBKDF_ITER})`);
184
+ }
185
+ return this.deriveKey(params);
186
+ });
187
+ }
188
+ createKid() {
189
+ return __awaiter(this, void 0, void 0, function* () {
190
+ // todo: AZ: node-jose source uses node's default UUID() function for kid, so just change to use that.
191
+ // for now, we are just creating a new key to use it's kid.
192
+ // The kid is a part of the JWK system. LR backend maintains the key hierarchy separately with it's own
193
+ // key id. But we just use it here as a double check.
194
+ return (yield this.createKey()).kid;
195
+ });
196
+ }
197
+ createPassIdpParams() {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ return {
200
+ salt: this.createSalt(),
201
+ iterations: this.DEFAULT_PASS_IDP_PBKDF_ITER,
202
+ };
203
+ });
204
+ }
205
+ createPassKeyParams() {
206
+ return __awaiter(this, void 0, void 0, function* () {
207
+ return {
208
+ salt: this.createSalt(),
209
+ kid: yield this.createKid(),
210
+ iterations: this.DEFAULT_PASS_KEY_PBKDF_ITER,
211
+ };
212
+ });
213
+ }
214
+ createLbopKeyParams() {
215
+ return __awaiter(this, void 0, void 0, function* () {
216
+ return {
217
+ salt: this.createSalt(),
218
+ // todo: AZ: node-jose source uses node's default UUID() function for kid, so just change to use that.
219
+ // for now, we are just creating a new key to use it's kid.
220
+ // The kid is a part of the JWK system. LR backend maintains the key hierarchy separately with it's own
221
+ // key id. But we just use it here as a double check.
222
+ kid: yield this.createKid(),
223
+ iterations: this.DEFAULT_PASS_KEY_PBKDF_ITER,
224
+ };
225
+ });
226
+ }
227
+ }
228
+ KeyFactoryService.ɵprov = i0.ɵɵdefineInjectable({ factory: function KeyFactoryService_Factory() { return new KeyFactoryService(i0.ɵɵinject(i1.WebCryptoService)); }, token: KeyFactoryService, providedIn: "root" });
229
+ KeyFactoryService.decorators = [
230
+ { type: Injectable, args: [{
231
+ providedIn: 'root',
232
+ },] }
233
+ ];
234
+ KeyFactoryService.ctorParameters = () => [
235
+ { type: WebCryptoService }
236
+ ];
237
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LWZhY3Rvcnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIvb3B0L2F0bGFzc2lhbi9waXBlbGluZXMvYWdlbnQvYnVpbGQvcHJvamVjdHMvY29yZS9zcmMvIiwic291cmNlcyI6WyJsaWIvY3J5cHRvZ3JhcGh5L2tleS1mYWN0b3J5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVVoQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN4RCxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHFCQUFxQixHQUN0QixNQUFNLHVCQUF1QixDQUFDOzs7QUFFL0IsTUFBTSxVQUFnQixNQUFNLENBQUMsT0FBTzs7UUFDbEMsa0JBQWtCO1FBQ2xCLE1BQU0sU0FBUyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBELG1CQUFtQjtRQUNuQixNQUFNLFVBQVUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUVwRSwrQkFBK0I7UUFDL0IsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBRXpELDhCQUE4QjtRQUM5QixNQUFNLE9BQU8sR0FBRyxTQUFTO2FBQ3RCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzdDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNaLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENB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LHNHQUFzRztZQUN0RywyREFBMkQ7WUFDM0QsdUdBQXVHO1lBQ3ZHLHFEQUFxRDtZQUNyRCxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDdEMsQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixVQUFVLEVBQUUsSUFBSSxDQUFDLDJCQUEyQjthQUM3QyxDQUFDO1FBQ0osQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixHQUFHLEVBQUUsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUMzQixVQUFVLEVBQUUsSUFBSSxDQUFDLDJCQUEyQjthQUM3QyxDQUFDO1FBQ0osQ0FBQztLQUFBO0lBRUssbUJBQW1COztZQUN2QixPQUFPO2dCQUNMLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN2QixzR0FBc0c7Z0JBQ3RHLDJEQUEyRDtnQkFDM0QsdUdBQXVHO2dCQUN2RyxxREFBcUQ7Z0JBQ3JELEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQzNCLFVBQVUsRUFBRSxJQUFJLENBQUMsMkJBQTJCO2FBQzdDLENBQUM7UUFDSixDQUFDO0tBQUE7Ozs7WUEzUUYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7WUF6QlEsZ0JBQWdCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSldLIH0gZnJvbSAnbm9kZS1qb3NlJztcbmltcG9ydCB7XG4gIExib3BLZXlQYXJhbXMsXG4gIFBhc3NJZHBQYXJhbXMsXG4gIFBhc3NLZXlQYXJhbXMsXG4gIERlcml2ZUtleVJlc3VsdCxcbiAgRGVyaXZlUGFzc0lkcFBhcmFtcyxcbiAgRGVyaXZlUGFzc0tleVBhcmFtcyxcbiAgRGVyaXZlTGJvcEtleVBhcmFtcyxcbn0gZnJvbSAnLi9jcnlwdG9ncmFwaHkudHlwZXMnO1xuaW1wb3J0IHsgV2ViQ3J5cHRvU2VydmljZSB9IGZyb20gJy4vd2ViLWNyeXB0by5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIExyQmFkQXJndW1lbnRFeGNlcHRpb24sXG4gIExyU3VzcGljaW91c0V4Y2VwdGlvbixcbn0gZnJvbSAnLi4vX2NvbW1vbi9leGNlcHRpb25zJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNoYTI1NihtZXNzYWdlKSB7XG4gIC8vIGVuY29kZSBhcyBVVEYtOFxuICBjb25zdCBtc2dCdWZmZXIgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobWVzc2FnZSk7XG5cbiAgLy8gaGFzaCB0aGUgbWVzc2FnZVxuICBjb25zdCBoYXNoQnVmZmVyID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5kaWdlc3QoJ1NIQS0yNTYnLCBtc2dCdWZmZXIpO1xuXG4gIC8vIGNvbnZlcnQgQXJyYXlCdWZmZXIgdG8gQXJyYXlcbiAgY29uc3QgaGFzaEFycmF5ID0gQXJyYXkuZnJvbShuZXcgVWludDhBcnJheShoYXNoQnVmZmVyKSk7XG5cbiAgLy8gY29udmVydCBieXRlcyB0byBoZXggc3RyaW5nXG4gIGNvbnN0IGhhc2hIZXggPSBoYXNoQXJyYXlcbiAgICAubWFwKChiKSA9PiAoJzAwJyArIGIudG9TdHJpbmcoMTYpKS5zbGljZSgtMikpXG4gICAgLmpvaW4oJycpO1xuICByZXR1cm4gaGFzaEhleDtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIEtleUZhY3RvcnlTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSB3ZWJDcnlwdG9TZXJ2aWNlOiBXZWJDcnlwdG9TZXJ2aWNlKSB7XG4gICAgdGhpcy5jcnlwdG8gPSB0aGlzLndlYkNyeXB0b1NlcnZpY2UuY3J5cHRvO1xuICB9XG4gIHByaXZhdGUgcmVhZG9ubHkgY3J5cHRvO1xuICAvLyBHbG9iYWwga2V5cyBzdG9yZS4gT3RoZXJ3aXNlLCBlYWNoIGNhbGwgdG8gYXNLZXkgY3JlYXRlcyBhIG5ldyBrZXlTdG9yZS5cbiAgLy8gPEFaPiBEaWQgbm90IHNlZW0gdG8gaW1wcm92ZSBzcGVlZC5cbiAgLy8gcHVibGljIHN0YXRpYyBrZXlTdG9yZSA9IEpXSy5jcmVhdGVLZXlTdG9yZSgpO1xuXG4gIC8vIEFaOiBUaGlzIGNhbid0IGJlIGNoYW5nZSBlYXNpbHkuIEl0J3MgYmFzaWNhbGx5IGEgUGFzc0sgb3IgUGFzc0lkcCByb3RhdGlvbi5cbiAgLy8gdG9kbzogd2Ugc2hvdWxkIGV2ZW50dWFsbHkgaW5jcmVhc2UgdGhpcyBwZXJpb2RpY2FsbHkgdG8gbWF0Y2ggd2l0aCBNb29yZSdzIGxhdy5cbiAgLy8gVGhlIGl0ZXJhdGlvbnMgZm9yIGVhY2gga2V5IGFyZSBrZXB0IGJ5IHRoZSBzZXJ2ZXIgYXMgd2VsbCBidXQgd2UgYXNzdW1lIHRoZSB2YWx1ZVxuICAvLyBmcm9tIHRoZSBzZXJ2ZXIgaXMgbm90IHRydXN0d29ydGh5LCBzbyBuZWVkIHRvIGhhdmUgbWluaW11bSB0aHJlc2hvbGRzIGhlcmUuXG4gIC8vIElmIGNyZWF0aW5nIG5ldyBrZXlzLCB0aGVzZSBtaW5pbXVtIGFyZSB1c2VkLlxuICBwdWJsaWMgcmVhZG9ubHkgTUlOX1BBU1NfSURQX1BCS0RGX0lURVIgPSAxMDAwMDA7XG4gIHB1YmxpYyByZWFkb25seSBNSU5fUEFTU19LRVlfUEJLREZfSVRFUiA9IDEwMDAwMDtcbiAgcHVibGljIHJlYWRvbmx5IE1JTl9MQk9QX0tFWV9QQktERl9JVEVSID0gMTAwMDAwO1xuXG4gIC8vIFRoZXNlIGFyZSB1c2VkIGFzIHRoZSBkZWZhdWx0IHZhbHVlcy4gVGhleSBtdXN0IGJlIGxhcmdlciB0aGFuIHRoZSBtaW5pbXVtIHZhbHVlcy5cbiAgcHVibGljIHJlYWRvbmx5IERFRkFVTFRfUEFTU19JRFBfUEJLREZfSVRFUiA9IHRoaXMuTUlOX1BBU1NfSURQX1BCS0RGX0lURVI7XG4gIHB1YmxpYyByZWFkb25seSBERUZBVUxUX1BBU1NfS0VZX1BCS0RGX0lURVIgPSB0aGlzLk1JTl9QQVNTX0tFWV9QQktERl9JVEVSO1xuICBwdWJsaWMgcmVhZG9ubHkgREVGQVVMVF9MQk9QX0tFWV9QQktERl9JVEVSID0gdGhpcy5NSU5fTEJPUF9LRVlfUEJLREZfSVRFUjtcblxuICBzdGF0aWMgYXNLZXkoXG4gICAga2V5OiBzdHJpbmcgfCBCdWZmZXIgfCBvYmplY3QgfCBKV0suUmF3S2V5LFxuICAgIGZvcm0/OlxuICAgICAgfCAnanNvbidcbiAgICAgIHwgJ3ByaXZhdGUnXG4gICAgICB8ICdwa2NzOCdcbiAgICAgIHwgJ3B1YmxpYydcbiAgICAgIHwgJ3Nwa2knXG4gICAgICB8ICdwa2l4J1xuICAgICAgfCAneDUwOSdcbiAgICAgIHwgJ3BlbScsXG4gICAgZXh0cmFzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgKTogUHJvbWlzZTxKV0suS2V5PiB7XG4gICAgLy8gPEFaPiBVc2luZyBhIHNpbmdsZSBnbG9iYWwga2V5IHN0b3JlIGRpZCBub3Qgc2VlbSB0byBpbXByb3ZlIHNwZWVkLlxuICAgIC8vIHJldHVybiBLZXlGYWN0b3J5U2VydmljZS5rZXlTdG9yZS5hZGQoa2V5LCBmb3JtLCBleHRyYXMpO1xuICAgIHJldHVybiBKV0suYXNLZXkoa2V5LCBmb3JtLCBleHRyYXMpO1xuICB9XG5cbiAgcmFuZG9tU3RyaW5nKGRpZ2l0czogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBpZiAoZGlnaXRzIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBMckJhZEFyZ3VtZW50RXhjZXB0aW9uKCdkaWdpdHMgPD0gMCcpO1xuICAgIH1cbiAgICBjb25zdCB2YWxpZENoYXJzID1cbiAgICAgICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XG4gICAgbGV0IGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KGRpZ2l0cyk7XG4gICAgdGhpcy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KTtcbiAgICBhcnJheSA9IGFycmF5Lm1hcCgoeCkgPT4gdmFsaWRDaGFycy5jaGFyQ29kZUF0KHggJSB2YWxpZENoYXJzLmxlbmd0aCkpO1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHJhbmRvbURpZ2l0c05vWmVyb3MoZGlnaXRzOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJhbmRvbUNob2ljZXMoWzEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDldLCBkaWdpdHMpLmpvaW4oJycpO1xuICB9XG5cbiAgcmFuZG9tQ2hvaWNlczxUPihhcnJheTogVFtdLCBjaG9vc2VOOiBudW1iZXIpOiBUW10ge1xuICAgIGlmIChhcnJheS5sZW5ndGggPD0gMSkge1xuICAgICAgdGhyb3cgbmV3IExyQmFkQXJndW1lbnRFeGNlcHRpb24oJ2FycmF5Lmxlbmd0aCA8PSAwJyk7XG4gICAgfVxuICAgIGlmIChjaG9vc2VOIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBMckJhZEFyZ3VtZW50RXhjZXB0aW9uKCdjaG9vc2VOIDw9IDAnKTtcbiAgICB9XG4gICAgY29uc3QgdmFsdWVzID0gbmV3IFVpbnQzMkFycmF5KGNob29zZU4pO1xuICAgIHRoaXMuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyh2YWx1ZXMpO1xuICAgIGNvbnN0IHJldDogVFtdID0gW107XG4gICAgdmFsdWVzLmZvckVhY2goKHYpID0+IHJldC5wdXNoKGFycmF5W3YgJSBhcnJheS5sZW5ndGhdKSk7XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIGNyZWF0ZVNhbHQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5yYW5kb21TdHJpbmcoMTYpO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlS2V5KCk6IFByb21pc2U8SldLLktleT4ge1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHRoaXMuY3J5cHRvLnN1YnRsZS5nZW5lcmF0ZUtleShcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ0FFUy1HQ00nLFxuICAgICAgICBsZW5ndGg6IDI1NiwgLy8gY2FuIGJlICAxMjgsIDE5Miwgb3IgMjU2XG4gICAgICB9LFxuICAgICAgdHJ1ZSwgLy8gd2hldGhlciB0aGUga2V5IGlzIGV4dHJhY3RhYmxlIChpLmUuIGNhbiBiZSB1c2VkIGluIGV4cG9ydEtleSlcbiAgICAgIFsnZW5jcnlwdCcsICdkZWNyeXB0J10gLy8gbXVzdCBiZSBbXCJlbmNyeXB0XCIsIFwiZGVjcnlwdFwiXSBvciBbXCJ3cmFwS2V5XCIsIFwidW53cmFwS2V5XCJdXG4gICAgKTtcblxuICAgIGNvbnN0IGp3ayA9IGF3YWl0IHRoaXMuY3J5cHRvLnN1YnRsZS5leHBvcnRLZXkoJ2p3aycsIGtleSk7XG5cbiAgICAvLyBSZW1vdmluZyB0aGUgZmllbGRzIG5vdCBuZWVkZWQgYnkgbm9kZS1qb3NlXG4gICAgZGVsZXRlIGp3ay5leHQ7XG4gICAgZGVsZXRlIGp3ay5rZXlfb3BzO1xuXG4gICAgcmV0dXJuIEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KGp3ayk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVTaWduS2V5KCk6IFByb21pc2U8SldLLktleT4ge1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHRoaXMuY3J5cHRvLnN1YnRsZS5nZW5lcmF0ZUtleShcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ0hNQUMnLFxuICAgICAgICBoYXNoOiB7IG5hbWU6ICdTSEEtNTEyJyB9LFxuICAgICAgfSxcbiAgICAgIHRydWUsXG4gICAgICBbJ3NpZ24nLCAndmVyaWZ5J11cbiAgICApO1xuXG4gICAgY29uc3QgandrID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmV4cG9ydEtleSgnandrJywga2V5KTtcblxuICAgIC8vIFJlbW92aW5nIHRoZSBmaWVsZHMgbm90IG5lZWRlZCBieSBub2RlLWpvc2VcbiAgICBkZWxldGUgandrLmtleV9vcHM7XG4gICAgZGVsZXRlIGp3ay5leHQ7XG5cbiAgICByZXR1cm4gS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoandrKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVBrY0tleSgpOiBQcm9taXNlPEpXSy5LZXk+IHtcbiAgICAvLyBub2RlLWpvc2UgaXMgbm90IHVzaW5nIEZvcmdlIHByb3Blcmx5LiBJdCBzaG91bGQgYmUgY2FsbGluZyB0aGUgYXN5bmMgdmVyc2lvbiBvZlxuICAgIC8vIHBraS5yc2EuZ2VuZXJhdGVLZXlQYWlyKCkgd2l0aCBhIGNhbGxiYWNrLiBJbnN0ZWFkIGl0IGNhbGxzIHRoZSBzeW5jIHZlcnNpb24uIFdlYmNyeXB0b1xuICAgIC8vIGRvZXMgbm90IHN1cHBvcnQgc3luYyB2ZXJzaW9uLCBzbyBpdCB1c2VzIHRoZSBqYXZhc2NyaXB0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyB3YXkgdG9vIHNsb3cuXG4gICAgLy8gU28gd2UgZ2VuZXJhdGUgdXNpbmcgd2ViY3J5cHRvIGFuZCBpbXBvcnQgdGhlIGtleS5cbiAgICAvLyBVbmZvcnR1bmF0ZWx5IEVsbGlwdGljYWwgQ3VydmUgaXMgbm90IHN1cHBvcnRlZCBieSBXZWJjcnlwdG8uIFNvIHdlIGhhdmUgdG8gc2V0dGxlIGZvciBSU0EuXG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmdlbmVyYXRlS2V5KFxuICAgICAge1xuICAgICAgICBuYW1lOiAnUlNBLU9BRVAnLFxuICAgICAgICBtb2R1bHVzTGVuZ3RoOiAyMDQ4LCAvLyBjYW4gYmUgMTAyNCwgMjA0OCwgMzA3MiwgNDA5NiAuLi4gMTYzODRcbiAgICAgICAgLy8gQXMgcGVyIHN1Z2dlc3Rpb246IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Sc2FIYXNoZWRLZXlHZW5QYXJhbXNcbiAgICAgICAgcHVibGljRXhwb25lbnQ6IG5ldyBVaW50OEFycmF5KFsweDAxLCAweDAwLCAweDAxXSksXG4gICAgICAgIGhhc2g6IHsgbmFtZTogJ1NIQS0yNTYnIH0sIC8vIGNhbiBiZSBcIlNIQS0xXCIsIFwiU0hBLTI1NlwiLCBcIlNIQS0zODRcIiwgb3IgXCJTSEEtNTEyXCJcbiAgICAgIH0sXG4gICAgICB0cnVlLCAvLyB3aGV0aGVyIHRoZSBrZXkgaXMgZXh0cmFjdGFibGUgKGkuZS4gY2FuIGJlIHVzZWQgaW4gZXhwb3J0S2V5KVxuICAgICAgWydlbmNyeXB0JywgJ2RlY3J5cHQnXSAvLyBtdXN0IGJlIFtcImVuY3J5cHRcIiwgXCJkZWNyeXB0XCJdIG9yIFtcIndyYXBLZXlcIiwgXCJ1bndyYXBLZXlcIl1cbiAgICApO1xuXG4gICAgY29uc3QgandrID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmV4cG9ydEtleSgnandrJywga2V5LnByaXZhdGVLZXkpO1xuICAgIC8vIFJlbW92aW5nIHRoZSBmaWVsZHMgbm90IG5lZWRlZCBieSBub2RlLWpvc2VcbiAgICBkZWxldGUgandrLmtleV9vcHM7XG4gICAgZGVsZXRlIGp3ay5leHQ7XG5cbiAgICByZXR1cm4gS2V5RmFjdG9yeVNlcnZpY2UuYXNLZXkoandrKTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVBrY1NpZ25LZXkoKTogUHJvbWlzZTxKV0suS2V5PiB7XG4gICAgY29uc3Qga2V5ID0gYXdhaXQgdGhpcy5jcnlwdG8uc3VidGxlLmdlbmVyYXRlS2V5KFxuICAgICAge1xuICAgICAgICBuYW1lOiAnUlNBU1NBLVBLQ1MxLXYxXzUnLFxuICAgICAgICBtb2R1bHVzTGVuZ3RoOiAyMDQ4LCAvLyBjYW4gYmUgMTAyNCwgMjA0OCwgb3IgNDA5NlxuICAgICAgICAvLyBBcyBwZXIgc3VnZ2VzdGlvbjogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JzYUhhc2hlZEtleUdlblBhcmFtc1xuICAgICAgICBwdWJsaWNFeHBvbmVudDogbmV3IFVpbnQ4QXJyYXkoWzB4MDEsIDB4MDAsIDB4MDFdKSxcbiAgICAgICAgaGFzaDogeyBuYW1lOiAnU0hBLTI1NicgfSwgLy8gY2FuIGJlIFwiU0hBLTFcIiwgXCJTSEEtMjU2XCIsIFwiU0hBLTM4NFwiLCBvciBcIlNIQS01MTJcIlxuICAgICAgfSxcbiAgICAgIHRydWUsIC8vIHdoZXRoZXIgdGhlIGtleSBpcyBleHRyYWN0YWJsZSAoaS5lLiBjYW4gYmUgdXNlZCBpbiBleHBvcnRLZXkpXG4gICAgICBbJ3NpZ24nLCAndmVyaWZ5J10gLy8gY2FuIGJlIGFueSBjb21iaW5hdGlvbiBvZiBcInNpZ25cIiBhbmQgXCJ2ZXJpZnlcIlxuICAgICk7XG5cbiAgICBjb25zdCBqd2sgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuZXhwb3J0S2V5KCdqd2snLCBrZXkucHJpdmF0ZUtleSk7XG5cbiAgICAvLyBSZW1vdmluZyB0aGUgZmllbGRzIG5vdCBuZWVkZWQgYnkgbm9kZS1qb3NlXG4gICAgZGVsZXRlIGp3ay5rZXlfb3BzO1xuICAgIGRlbGV0ZSBqd2suZXh0O1xuXG4gICAgcmV0dXJuIEtleUZhY3RvcnlTZXJ2aWNlLmFzS2V5KGp3ayk7XG4gIH1cblxuICBhc3luYyBkZXJpdmVLZXkoe1xuICAgIHBhc3N3b3JkLFxuICAgIHNhbHQsXG4gICAgaXRlcmF0aW9ucyxcbiAgICBraWQsXG4gIH06IHtcbiAgICBwYXNzd29yZDogc3RyaW5nO1xuICAgIHNhbHQ6IHN0cmluZztcbiAgICBpdGVyYXRpb25zOiBudW1iZXI7XG4gICAga2lkPzogc3RyaW5nO1xuICB9KTogUHJvbWlzZTxEZXJpdmVLZXlSZXN1bHQ+IHtcbiAgICBjb25zdCBlbmMgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICBjb25zdCByYXdLZXkgPSBhd2FpdCB0aGlzLmNyeXB0by5zdWJ0bGUuaW1wb3J0S2V5KFxuICAgICAgJ3JhdycsXG4gICAgICBlbmMuZW5jb2RlKHBhc3N3b3JkKSxcbiAgICAgICdQQktERjInLFxuICAgICAgZmFsc2UsXG4gICAgICBbJ2Rlcml2ZUJpdHMnLCAnZGVyaXZlS2V5J11cbiAgICApO1xuXG4gICAgY29uc3QgcGFzc0tleSA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGVyaXZlS2V5KFxuICAgICAge1xuICAgICAgICBuYW1lOiAnUEJLREYyJyxcbiAgICAgICAgc2FsdDogbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNhbHQpLFxuICAgICAgICBpdGVyYXRpb25zLFxuICAgICAgICBoYXNoOiAnU0hBLTI1NicsXG4gICAgICB9LFxuICAgICAgcmF3S2V5LFxuICAgICAgeyBuYW1lOiAnQUVTLUdDTScsIGxlbmd0aDogMjU2IH0sXG4gICAgICB0cnVlLFxuICAgICAgWydlbmNyeXB0JywgJ2RlY3J5cHQnXVxuICAgICk7XG5cbiAgICBjb25zdCBwYXNzS2V5SnNvbjogYW55ID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5leHBvcnRLZXkoJ2p3aycsIHBhc3NLZXkpO1xuICAgIGlmIChraWQpIHtcbiAgICAgIHBhc3NLZXlKc29uLmtpZCA9IGtpZDtcbiAgICB9XG5cbiAgICBjb25zdCBqd2sgPSBhd2FpdCBLZXlGYWN0b3J5U2VydmljZS5hc0tleShwYXNzS2V5SnNvbik7XG5cbiAgICByZXR1cm4geyBqd2sgfTtcbiAgfVxuXG4gIGFzeW5jIGRlcml2ZVBhc3NJZHAocGFyYW1zOiBEZXJpdmVQYXNzSWRwUGFyYW1zKTogUHJvbWlzZTxEZXJpdmVLZXlSZXN1bHQ+IHtcbiAgICBpZiAocGFyYW1zLml0ZXJhdGlvbnMgPCB0aGlzLk1JTl9QQVNTX0lEUF9QQktERl9JVEVSKSB7XG4gICAgICB0aHJvdyBuZXcgTHJTdXNwaWNpb3VzRXhjZXB0aW9uKFxuICAgICAgICBgVGhlIG51bWJlciBvZiBQYXNzSWRwIGtleSBkZXJpdmF0aW9uIGl0ZXJhdGlvbnMgc2VudCBmcm9tIHRoZSBzZXJ2ZXIgKCR7cGFyYW1zLml0ZXJhdGlvbnN9KSBpcyBsb3dlciB0aGFuIHRoZSBtaW5pbXVtICgke3RoaXMuTUlOX1BBU1NfSURQX1BCS0RGX0lURVJ9KWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmRlcml2ZUtleShwYXJhbXMpO1xuICB9XG5cbiAgYXN5bmMgZGVyaXZlUGFzc0tleShwYXJhbXM6IERlcml2ZVBhc3NLZXlQYXJhbXMpOiBQcm9taXNlPERlcml2ZUtleVJlc3VsdD4ge1xuICAgIGlmIChwYXJhbXMuaXRlcmF0aW9ucyA8IHRoaXMuTUlOX1BBU1NfS0VZX1BCS0RGX0lURVIpIHtcbiAgICAgIHRocm93IG5ldyBMclN1c3BpY2lvdXNFeGNlcHRpb24oXG4gICAgICAgIGBUaGUgbnVtYmVyIG9mIFBhc3NLZXkga2V5IGRlcml2YXRpb24gaXRlcmF0aW9ucyBzZW50IGZyb20gdGhlIHNlcnZlcigke3BhcmFtcy5pdGVyYXRpb25zfSkgaXMgbG93ZXIgdGhhbiB0aGUgbWluaW11bSgke3RoaXMuTUlOX1BBU1NfS0VZX1BCS0RGX0lURVJ9KWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmRlcml2ZUtleShwYXJhbXMpO1xuICB9XG5cbiAgYXN5bmMgZGVyaXZlTGJvcEtleShwYXJhbXM6IERlcml2ZUxib3BLZXlQYXJhbXMpOiBQcm9taXNlPERlcml2ZUtleVJlc3VsdD4ge1xuICAgIGlmIChwYXJhbXMuaXRlcmF0aW9ucyA8IHRoaXMuTUlOX0xCT1BfS0VZX1BCS0RGX0lURVIpIHtcbiAgICAgIHRocm93IG5ldyBMclN1c3BpY2lvdXNFeGNlcHRpb24oXG4gICAgICAgIGBUaGUgbnVtYmVyIG9mIExib3BLZXkga2V5IGRlcml2YXRpb24gaXRlcmF0aW9ucyBzZW50IGZyb20gdGhlIHNlcnZlcigke3BhcmFtcy5pdGVyYXRpb25zfSkgaXMgbG93ZXIgdGhhbiB0aGUgbWluaW11bSgke3RoaXMuTUlOX0xCT1BfS0VZX1BCS0RGX0lURVJ9KWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmRlcml2ZUtleShwYXJhbXMpO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlS2lkKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgLy8gdG9kbzogQVo6IG5vZGUtam9zZSBzb3VyY2UgdXNlcyBub2RlJ3MgZGVmYXVsdCBVVUlEKCkgZnVuY3Rpb24gZm9yIGtpZCwgc28ganVzdCBjaGFuZ2UgdG8gdXNlIHRoYXQuXG4gICAgLy8gZm9yIG5vdywgd2UgYXJlIGp1c3QgY3JlYXRpbmcgYSBuZXcga2V5IHRvIHVzZSBpdCdzIGtpZC5cbiAgICAvLyBUaGUga2lkIGlzIGEgcGFydCBvZiB0aGUgSldLIHN5c3RlbS4gTFIgYmFja2VuZCBtYWludGFpbnMgdGhlIGtleSBoaWVyYXJjaHkgc2VwYXJhdGVseSB3aXRoIGl0J3Mgb3duXG4gICAgLy8ga2V5IGlkLiBCdXQgd2UganVzdCB1c2UgaXQgaGVyZSBhcyBhIGRvdWJsZSBjaGVjay5cbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuY3JlYXRlS2V5KCkpLmtpZDtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVBhc3NJZHBQYXJhbXMoKTogUHJvbWlzZTxQYXNzSWRwUGFyYW1zPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNhbHQ6IHRoaXMuY3JlYXRlU2FsdCgpLFxuICAgICAgaXRlcmF0aW9uczogdGhpcy5ERUZBVUxUX1BBU1NfSURQX1BCS0RGX0lURVIsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZVBhc3NLZXlQYXJhbXMoKTogUHJvbWlzZTxQYXNzS2V5UGFyYW1zPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNhbHQ6IHRoaXMuY3JlYXRlU2FsdCgpLFxuICAgICAga2lkOiBhd2FpdCB0aGlzLmNyZWF0ZUtpZCgpLFxuICAgICAgaXRlcmF0aW9uczogdGhpcy5ERUZBVUxUX1BBU1NfS0VZX1BCS0RGX0lURVIsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZUxib3BLZXlQYXJhbXMoKTogUHJvbWlzZTxMYm9wS2V5UGFyYW1zPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNhbHQ6IHRoaXMuY3JlYXRlU2FsdCgpLFxuICAgICAgLy8gdG9kbzogQVo6IG5vZGUtam9zZSBzb3VyY2UgdXNlcyBub2RlJ3MgZGVmYXVsdCBVVUlEKCkgZnVuY3Rpb24gZm9yIGtpZCwgc28ganVzdCBjaGFuZ2UgdG8gdXNlIHRoYXQuXG4gICAgICAvLyBmb3Igbm93LCB3ZSBhcmUganVzdCBjcmVhdGluZyBhIG5ldyBrZXkgdG8gdXNlIGl0J3Mga2lkLlxuICAgICAgLy8gVGhlIGtpZCBpcyBhIHBhcnQgb2YgdGhlIEpXSyBzeXN0ZW0uIExSIGJhY2tlbmQgbWFpbnRhaW5zIHRoZSBrZXkgaGllcmFyY2h5IHNlcGFyYXRlbHkgd2l0aCBpdCdzIG93blxuICAgICAgLy8ga2V5IGlkLiBCdXQgd2UganVzdCB1c2UgaXQgaGVyZSBhcyBhIGRvdWJsZSBjaGVjay5cbiAgICAgIGtpZDogYXdhaXQgdGhpcy5jcmVhdGVLaWQoKSxcbiAgICAgIGl0ZXJhdGlvbnM6IHRoaXMuREVGQVVMVF9QQVNTX0tFWV9QQktERl9JVEVSLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==