UNPKG

71.6 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.Key = exports.KeyUsage = exports.KeySpec = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const iam = require("@aws-cdk/aws-iam");
8const cxschema = require("@aws-cdk/cloud-assembly-schema");
9const core_1 = require("@aws-cdk/core");
10const cxapi = require("@aws-cdk/cx-api");
11const constructs_1 = require("constructs");
12const alias_1 = require("./alias");
13const kms_generated_1 = require("./kms.generated");
14const perms = require("./private/perms");
15class KeyBase extends core_1.Resource {
16 constructor() {
17 super(...arguments);
18 /**
19 * Collection of aliases added to the key
20 *
21 * Tracked to determine whether or not the aliasName should be added to the end of its ID
22 */
23 this.aliases = [];
24 }
25 /**
26 * Defines a new alias for the key.
27 */
28 addAlias(aliasName) {
29 const aliasId = this.aliases.length > 0 ? `Alias${aliasName}` : 'Alias';
30 const alias = new alias_1.Alias(this, aliasId, { aliasName, targetKey: this });
31 this.aliases.push(alias);
32 return alias;
33 }
34 /**
35 * Adds a statement to the KMS key resource policy.
36 * @param statement The policy statement to add
37 * @param allowNoOp If this is set to `false` and there is no policy
38 * defined (i.e. external key), the operation will fail. Otherwise, it will
39 * no-op.
40 */
41 addToResourcePolicy(statement, allowNoOp = true) {
42 const stack = core_1.Stack.of(this);
43 if (!this.policy) {
44 if (allowNoOp) {
45 return { statementAdded: false };
46 }
47 throw new Error(`Unable to add statement to IAM resource policy for KMS key: ${JSON.stringify(stack.resolve(this.keyArn))}`);
48 }
49 this.policy.addStatements(statement);
50 return { statementAdded: true, policyDependable: this.policy };
51 }
52 validate() {
53 const errors = super.validate();
54 errors.push(...this.policy?.validateForResourcePolicy() || []);
55 return errors;
56 }
57 /**
58 * Grant the indicated permissions on this key to the given principal
59 *
60 * This modifies both the principal's policy as well as the resource policy,
61 * since the default CloudFormation setup for KMS keys is that the policy
62 * must not be empty and so default grants won't work.
63 */
64 grant(grantee, ...actions) {
65 // KMS verifies whether the principals included in its key policy actually exist.
66 // This is a problem if the stack the grantee is part of depends on the key stack
67 // (as it won't exist before the key policy is attempted to be created).
68 // In that case, make the account the resource policy principal
69 const granteeStackDependsOnKeyStack = this.granteeStackDependsOnKeyStack(grantee);
70 const principal = granteeStackDependsOnKeyStack
71 ? new iam.AccountPrincipal(granteeStackDependsOnKeyStack)
72 : grantee.grantPrincipal;
73 const crossAccountAccess = this.isGranteeFromAnotherAccount(grantee);
74 const crossRegionAccess = this.isGranteeFromAnotherRegion(grantee);
75 const crossEnvironment = crossAccountAccess || crossRegionAccess;
76 const grantOptions = {
77 grantee,
78 actions,
79 resource: this,
80 resourceArns: [this.keyArn],
81 resourceSelfArns: crossEnvironment ? undefined : ['*'],
82 };
83 if (this.trustAccountIdentities && !crossEnvironment) {
84 return iam.Grant.addToPrincipalOrResource(grantOptions);
85 }
86 else {
87 return iam.Grant.addToPrincipalAndResource({
88 ...grantOptions,
89 // if the key is used in a cross-environment matter,
90 // we can't access the Key ARN (they don't have physical names),
91 // so fall back to using '*'. ToDo we need to make this better... somehow
92 resourceArns: crossEnvironment ? ['*'] : [this.keyArn],
93 resourcePolicyPrincipal: principal,
94 });
95 }
96 }
97 /**
98 * Grant decryption permissions using this key to the given principal
99 */
100 grantDecrypt(grantee) {
101 return this.grant(grantee, ...perms.DECRYPT_ACTIONS);
102 }
103 /**
104 * Grant encryption permissions using this key to the given principal
105 */
106 grantEncrypt(grantee) {
107 return this.grant(grantee, ...perms.ENCRYPT_ACTIONS);
108 }
109 /**
110 * Grant encryption and decryption permissions using this key to the given principal
111 */
112 grantEncryptDecrypt(grantee) {
113 return this.grant(grantee, ...[...perms.DECRYPT_ACTIONS, ...perms.ENCRYPT_ACTIONS]);
114 }
115 /**
116 * Checks whether the grantee belongs to a stack that will be deployed
117 * after the stack containing this key.
118 *
119 * @param grantee the grantee to give permissions to
120 * @returns the account ID of the grantee stack if its stack does depend on this stack,
121 * undefined otherwise
122 */
123 granteeStackDependsOnKeyStack(grantee) {
124 const grantPrincipal = grantee.grantPrincipal;
125 if (!isConstruct(grantPrincipal)) {
126 return undefined;
127 }
128 // this logic should only apply to newly created
129 // (= not imported) resources
130 if (!this.principalIsANewlyCreatedResource(grantPrincipal)) {
131 return undefined;
132 }
133 // return undefined;
134 const keyStack = core_1.Stack.of(this);
135 const granteeStack = core_1.Stack.of(grantPrincipal);
136 if (keyStack === granteeStack) {
137 return undefined;
138 }
139 return granteeStack.dependencies.includes(keyStack)
140 ? granteeStack.account
141 : undefined;
142 }
143 principalIsANewlyCreatedResource(principal) {
144 // yes, this sucks
145 // this is just a temporary stopgap to stem the bleeding while we work on a proper fix
146 return principal instanceof iam.Role ||
147 principal instanceof iam.User ||
148 principal instanceof iam.Group;
149 }
150 isGranteeFromAnotherRegion(grantee) {
151 if (!isConstruct(grantee)) {
152 return false;
153 }
154 const bucketStack = core_1.Stack.of(this);
155 const identityStack = core_1.Stack.of(grantee);
156 return bucketStack.region !== identityStack.region;
157 }
158 isGranteeFromAnotherAccount(grantee) {
159 if (!isConstruct(grantee)) {
160 return false;
161 }
162 const bucketStack = core_1.Stack.of(this);
163 const identityStack = core_1.Stack.of(grantee);
164 return bucketStack.account !== identityStack.account;
165 }
166}
167/**
168 * The key spec, represents the cryptographic configuration of keys.
169 */
170var KeySpec;
171(function (KeySpec) {
172 /**
173 * The default key spec.
174 *
175 * Valid usage: ENCRYPT_DECRYPT
176 */
177 KeySpec["SYMMETRIC_DEFAULT"] = "SYMMETRIC_DEFAULT";
178 /**
179 * RSA with 2048 bits of key.
180 *
181 * Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
182 */
183 KeySpec["RSA_2048"] = "RSA_2048";
184 /**
185 * RSA with 3072 bits of key.
186 *
187 * Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
188 */
189 KeySpec["RSA_3072"] = "RSA_3072";
190 /**
191 * RSA with 4096 bits of key.
192 *
193 * Valid usage: ENCRYPT_DECRYPT and SIGN_VERIFY
194 */
195 KeySpec["RSA_4096"] = "RSA_4096";
196 /**
197 * NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
198 * SHA-256 for the message digest.
199 *
200 * Valid usage: SIGN_VERIFY
201 */
202 KeySpec["ECC_NIST_P256"] = "ECC_NIST_P256";
203 /**
204 * NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
205 * SHA-384 for the message digest.
206 *
207 * Valid usage: SIGN_VERIFY
208 */
209 KeySpec["ECC_NIST_P384"] = "ECC_NIST_P384";
210 /**
211 * NIST FIPS 186-4, Section 6.4, ECDSA signature using the curve specified by the key and
212 * SHA-512 for the message digest.
213 *
214 * Valid usage: SIGN_VERIFY
215 */
216 KeySpec["ECC_NIST_P521"] = "ECC_NIST_P521";
217 /**
218 * Standards for Efficient Cryptography 2, Section 2.4.1, ECDSA signature on the Koblitz curve.
219 *
220 * Valid usage: SIGN_VERIFY
221 */
222 KeySpec["ECC_SECG_P256K1"] = "ECC_SECG_P256K1";
223})(KeySpec = exports.KeySpec || (exports.KeySpec = {}));
224/**
225 * The key usage, represents the cryptographic operations of keys.
226 */
227var KeyUsage;
228(function (KeyUsage) {
229 /**
230 * Encryption and decryption.
231 */
232 KeyUsage["ENCRYPT_DECRYPT"] = "ENCRYPT_DECRYPT";
233 /**
234 * Signing and verification
235 */
236 KeyUsage["SIGN_VERIFY"] = "SIGN_VERIFY";
237})(KeyUsage = exports.KeyUsage || (exports.KeyUsage = {}));
238/**
239 * Defines a KMS key.
240 *
241 * @resource AWS::KMS::Key
242 */
243class Key extends KeyBase {
244 constructor(scope, id, props = {}) {
245 super(scope, id);
246 try {
247 jsiiDeprecationWarnings._aws_cdk_aws_kms_KeyProps(props);
248 }
249 catch (error) {
250 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
251 Error.captureStackTrace(error, Key);
252 }
253 throw error;
254 }
255 const denyLists = {
256 [KeyUsage.ENCRYPT_DECRYPT]: [
257 KeySpec.ECC_NIST_P256,
258 KeySpec.ECC_NIST_P384,
259 KeySpec.ECC_NIST_P521,
260 KeySpec.ECC_SECG_P256K1,
261 ],
262 [KeyUsage.SIGN_VERIFY]: [
263 KeySpec.SYMMETRIC_DEFAULT,
264 ],
265 };
266 const keySpec = props.keySpec ?? KeySpec.SYMMETRIC_DEFAULT;
267 const keyUsage = props.keyUsage ?? KeyUsage.ENCRYPT_DECRYPT;
268 if (denyLists[keyUsage].includes(keySpec)) {
269 throw new Error(`key spec '${keySpec}' is not valid with usage '${keyUsage}'`);
270 }
271 if (keySpec !== KeySpec.SYMMETRIC_DEFAULT && props.enableKeyRotation) {
272 throw new Error('key rotation cannot be enabled on asymmetric keys');
273 }
274 const defaultKeyPoliciesFeatureEnabled = core_1.FeatureFlags.of(this).isEnabled(cxapi.KMS_DEFAULT_KEY_POLICIES);
275 this.policy = props.policy ?? new iam.PolicyDocument();
276 if (defaultKeyPoliciesFeatureEnabled) {
277 if (props.trustAccountIdentities === false) {
278 throw new Error('`trustAccountIdentities` cannot be false if the @aws-cdk/aws-kms:defaultKeyPolicies feature flag is set');
279 }
280 this.trustAccountIdentities = true;
281 // Set the default key policy if one hasn't been provided by the user.
282 if (!props.policy) {
283 this.addDefaultAdminPolicy();
284 }
285 }
286 else {
287 this.trustAccountIdentities = props.trustAccountIdentities ?? false;
288 if (this.trustAccountIdentities) {
289 this.addDefaultAdminPolicy();
290 }
291 else {
292 this.addLegacyAdminPolicy();
293 }
294 }
295 let pendingWindowInDays;
296 if (props.pendingWindow) {
297 pendingWindowInDays = props.pendingWindow.toDays();
298 if (pendingWindowInDays < 7 || pendingWindowInDays > 30) {
299 throw new Error(`'pendingWindow' value must between 7 and 30 days. Received: ${pendingWindowInDays}`);
300 }
301 }
302 const resource = new kms_generated_1.CfnKey(this, 'Resource', {
303 description: props.description,
304 enableKeyRotation: props.enableKeyRotation,
305 enabled: props.enabled,
306 keySpec: props.keySpec,
307 keyUsage: props.keyUsage,
308 keyPolicy: this.policy,
309 pendingWindowInDays: pendingWindowInDays,
310 });
311 this.keyArn = resource.attrArn;
312 this.keyId = resource.ref;
313 resource.applyRemovalPolicy(props.removalPolicy);
314 (props.admins ?? []).forEach((p) => this.grantAdmin(p));
315 if (props.alias !== undefined) {
316 this.addAlias(props.alias);
317 }
318 }
319 /**
320 * Import an externally defined KMS Key using its ARN.
321 *
322 * @param scope the construct that will "own" the imported key.
323 * @param id the id of the imported key in the construct tree.
324 * @param keyArn the ARN of an existing KMS key.
325 */
326 static fromKeyArn(scope, id, keyArn) {
327 class Import extends KeyBase {
328 constructor(keyId) {
329 super(scope, id);
330 this.keyArn = keyArn;
331 this.policy = undefined;
332 // defaulting true: if we are importing the key the key policy is
333 // undefined and impossible to change here; this means updating identity
334 // policies is really the only option
335 this.trustAccountIdentities = true;
336 this.keyId = keyId;
337 }
338 }
339 const keyResourceName = core_1.Stack.of(scope).splitArn(keyArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
340 if (!keyResourceName) {
341 throw new Error(`KMS key ARN must be in the format 'arn:aws:kms:<region>:<account>:key/<keyId>', got: '${keyArn}'`);
342 }
343 return new Import(keyResourceName);
344 }
345 /**
346 * Create a mutable {@link IKey} based on a low-level {@link CfnKey}.
347 * This is most useful when combined with the cloudformation-include module.
348 * This method is different than {@link fromKeyArn()} because the {@link IKey}
349 * returned from this method is mutable;
350 * meaning, calling any mutating methods on it,
351 * like {@link IKey.addToResourcePolicy()},
352 * will actually be reflected in the resulting template,
353 * as opposed to the object returned from {@link fromKeyArn()},
354 * on which calling those methods would have no effect.
355 */
356 static fromCfnKey(cfnKey) {
357 try {
358 jsiiDeprecationWarnings._aws_cdk_aws_kms_CfnKey(cfnKey);
359 }
360 catch (error) {
361 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
362 Error.captureStackTrace(error, this.fromCfnKey);
363 }
364 throw error;
365 }
366 // use a "weird" id that has a higher chance of being unique
367 const id = '@FromCfnKey';
368 // if fromCfnKey() was already called on this cfnKey,
369 // return the same L2
370 // (as different L2s would conflict, because of the mutation of the keyPolicy property of the L1 below)
371 const existing = cfnKey.node.tryFindChild(id);
372 if (existing) {
373 return existing;
374 }
375 let keyPolicy;
376 try {
377 keyPolicy = iam.PolicyDocument.fromJson(cfnKey.keyPolicy);
378 }
379 catch (e) {
380 // If the KeyPolicy contains any CloudFormation functions,
381 // PolicyDocument.fromJson() throws an exception.
382 // In that case, because we would have to effectively make the returned IKey immutable,
383 // throw an exception suggesting to use the other importing methods instead.
384 // We might make this parsing logic smarter later,
385 // but let's start by erroring out.
386 throw new Error('Could not parse the PolicyDocument of the passed AWS::KMS::Key resource because it contains CloudFormation functions. ' +
387 'This makes it impossible to create a mutable IKey from that Policy. ' +
388 'You have to use fromKeyArn instead, passing it the ARN attribute property of the low-level CfnKey');
389 }
390 // change the key policy of the L1, so that all changes done in the L2 are reflected in the resulting template
391 cfnKey.keyPolicy = core_1.Lazy.any({ produce: () => keyPolicy.toJSON() });
392 return new class extends KeyBase {
393 constructor() {
394 super(...arguments);
395 this.keyArn = cfnKey.attrArn;
396 this.keyId = cfnKey.ref;
397 this.policy = keyPolicy;
398 this.trustAccountIdentities = false;
399 }
400 }(cfnKey, id);
401 }
402 /**
403 * Import an existing Key by querying the AWS environment this stack is deployed to.
404 *
405 * This function only needs to be used to use Keys not defined in your CDK
406 * application. If you are looking to share a Key between stacks, you can
407 * pass the `Key` object between stacks and use it as normal. In addition,
408 * it's not necessary to use this method if an interface accepts an `IKey`.
409 * In this case, `Alias.fromAliasName()` can be used which returns an alias
410 * that extends `IKey`.
411 *
412 * Calling this method will lead to a lookup when the CDK CLI is executed.
413 * You can therefore not use any values that will only be available at
414 * CloudFormation execution time (i.e., Tokens).
415 *
416 * The Key information will be cached in `cdk.context.json` and the same Key
417 * will be used on future runs. To refresh the lookup, you will have to
418 * evict the value from the cache using the `cdk context` command. See
419 * https://docs.aws.amazon.com/cdk/latest/guide/context.html for more information.
420 */
421 static fromLookup(scope, id, options) {
422 try {
423 jsiiDeprecationWarnings._aws_cdk_aws_kms_KeyLookupOptions(options);
424 }
425 catch (error) {
426 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
427 Error.captureStackTrace(error, this.fromLookup);
428 }
429 throw error;
430 }
431 class Import extends KeyBase {
432 constructor(keyId, keyArn) {
433 super(scope, id);
434 this.policy = undefined;
435 // defaulting true: if we are importing the key the key policy is
436 // undefined and impossible to change here; this means updating identity
437 // policies is really the only option
438 this.trustAccountIdentities = true;
439 this.keyId = keyId;
440 this.keyArn = keyArn;
441 }
442 }
443 if (core_1.Token.isUnresolved(options.aliasName)) {
444 throw new Error('All arguments to Key.fromLookup() must be concrete (no Tokens)');
445 }
446 const attributes = core_1.ContextProvider.getValue(scope, {
447 provider: cxschema.ContextProvider.KEY_PROVIDER,
448 props: {
449 aliasName: options.aliasName,
450 },
451 dummyValue: {
452 keyId: '1234abcd-12ab-34cd-56ef-1234567890ab',
453 },
454 }).value;
455 return new Import(attributes.keyId, core_1.Arn.format({ resource: 'key', service: 'kms', resourceName: attributes.keyId }, core_1.Stack.of(scope)));
456 }
457 /**
458 * Grant admins permissions using this key to the given principal
459 *
460 * Key administrators have permissions to manage the key (e.g., change permissions, revoke), but do not have permissions
461 * to use the key in cryptographic operations (e.g., encrypt, decrypt).
462 */
463 grantAdmin(grantee) {
464 return this.grant(grantee, ...perms.ADMIN_ACTIONS);
465 }
466 /**
467 * Adds the default key policy to the key. This policy gives the AWS account (root user) full access to the CMK,
468 * which reduces the risk of the CMK becoming unmanageable and enables IAM policies to allow access to the CMK.
469 * This is the same policy that is default when creating a Key via the KMS API or Console.
470 * @see https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default
471 */
472 addDefaultAdminPolicy() {
473 this.addToResourcePolicy(new iam.PolicyStatement({
474 resources: ['*'],
475 actions: ['kms:*'],
476 principals: [new iam.AccountRootPrincipal()],
477 }));
478 }
479 /**
480 * Grants the account admin privileges -- not full account access -- plus the GenerateDataKey action.
481 * The GenerateDataKey action was added for interop with S3 in https://github.com/aws/aws-cdk/issues/3458.
482 *
483 * This policy is discouraged and deprecated by the `@aws-cdk/aws-kms:defaultKeyPolicies` feature flag.
484 *
485 * @link https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default
486 * @deprecated
487 */
488 addLegacyAdminPolicy() {
489 // This is equivalent to `[...perms.ADMIN_ACTIONS, 'kms:GenerateDataKey']`,
490 // but keeping this explicit ordering for backwards-compatibility (changing the ordering causes resource updates)
491 const actions = [
492 'kms:Create*',
493 'kms:Describe*',
494 'kms:Enable*',
495 'kms:List*',
496 'kms:Put*',
497 'kms:Update*',
498 'kms:Revoke*',
499 'kms:Disable*',
500 'kms:Get*',
501 'kms:Delete*',
502 'kms:ScheduleKeyDeletion',
503 'kms:CancelKeyDeletion',
504 'kms:GenerateDataKey',
505 'kms:TagResource',
506 'kms:UntagResource',
507 ];
508 this.addToResourcePolicy(new iam.PolicyStatement({
509 resources: ['*'],
510 actions,
511 principals: [new iam.AccountRootPrincipal()],
512 }));
513 }
514}
515exports.Key = Key;
516_a = JSII_RTTI_SYMBOL_1;
517Key[_a] = { fqn: "@aws-cdk/aws-kms.Key", version: "1.191.0" };
518/**
519 * Whether the given object is a Construct
520 *
521 * Normally we'd do `x instanceof Construct`, but that is not robust against
522 * multiple copies of the `constructs` library on disk. This can happen
523 * when upgrading and downgrading between v2 and v1, and in the use of CDK
524 * Pipelines is going to an error that says "Can't use Pipeline/Pipeline/Role in
525 * a cross-environment fashion", which is very confusing.
526 */
527function isConstruct(x) {
528 const sym = Symbol.for('constructs.Construct.node');
529 return (typeof x === 'object' && x &&
530 (x instanceof constructs_1.Construct // happy fast case
531 || !!x.node // constructs v10
532 || !!x[sym])); // constructs v3
533}
534//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsia2V5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4QywyREFBMkQ7QUFDM0Qsd0NBQWdKO0FBQ2hKLHlDQUF5QztBQUN6QywyQ0FBbUQ7QUFDbkQsbUNBQWdDO0FBRWhDLG1EQUF5QztBQUN6Qyx5Q0FBeUM7QUF3RHpDLE1BQWUsT0FBUSxTQUFRLGVBQVE7SUFBdkM7O1FBeUJFOzs7O1dBSUc7UUFDYyxZQUFPLEdBQVksRUFBRSxDQUFDO0lBMkp6QyxDQUFDO0lBekpDOztPQUVHO0lBQ0ksUUFBUSxDQUFDLFNBQWlCO1FBQy9CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBRXhFLE1BQU0sS0FBSyxHQUFHLElBQUksYUFBSyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDdkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFekIsT0FBTyxLQUFLLENBQUM7S0FDZDtJQUVEOzs7Ozs7T0FNRztJQUNJLG1CQUFtQixDQUFDLFNBQThCLEVBQUUsU0FBUyxHQUFHLElBQUk7UUFDekUsTUFBTSxLQUFLLEdBQUcsWUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU3QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixJQUFJLFNBQVMsRUFBRTtnQkFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLEtBQUssRUFBRSxDQUFDO2FBQUU7WUFDcEQsTUFBTSxJQUFJLEtBQUssQ0FBQywrREFBK0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUks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QVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0I7QUFDNUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGN4c2NoZW1hIGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBGZWF0dXJlRmxhZ3MsIElSZXNvdXJjZSwgTGF6eSwgUmVtb3ZhbFBvbGljeSwgUmVzb3VyY2UsIFN0YWNrLCBEdXJhdGlvbiwgVG9rZW4sIENvbnRleHRQcm92aWRlciwgQXJuLCBBcm5Gb3JtYXQgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBJQ29uc3RydWN0LCBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFsaWFzIH0gZnJvbSAnLi9hbGlhcyc7XG5pbXBvcnQgeyBLZXlMb29rdXBPcHRpb25zIH0gZnJvbSAnLi9rZXktbG9va3VwJztcbmltcG9ydCB7IENmbktleSB9IGZyb20gJy4va21zLmdlbmVyYXRlZCc7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tICcuL3ByaXZhdGUvcGVybXMnO1xuXG4vKipcbiAqIEEgS01TIEtleSwgZWl0aGVyIG1hbmFnZWQgYnkgdGhpcyBDREsgYXBwLCBvciBpbXBvcnRlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJS2V5IGV4dGVuZHMgSVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGtleS5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkga2V5QXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBJRCBvZiB0aGUga2V5XG4gICAqICh0aGUgcGFydCB0aGF0IGxvb2tzIHNvbWV0aGluZyBsaWtlOiAxMjM0YWJjZC0xMmFiLTM0Y2QtNTZlZi0xMjM0NTY3ODkwYWIpLlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBrZXlJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgbmV3IGFsaWFzIGZvciB0aGUga2V5LlxuICAgKi9cbiAgYWRkQWxpYXMoYWxpYXM6IHN0cmluZyk6IEFsaWFzO1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgc3RhdGVtZW50IHRvIHRoZSBLTVMga2V5IHJlc291cmNlIHBvbGljeS5cbiAgICogQHBhcmFtIHN0YXRlbWVudCBUaGUgcG9saWN5IHN0YXRlbWVudCB0byBhZGRcbiAgICogQHBhcmFtIGFsbG93Tm9PcCBJZiB0aGlzIGlzIHNldCB0byBgZmFsc2VgIGFuZCB0aGVyZSBpcyBubyBwb2xpY3lcbiAgICogZGVmaW5lZCAoaS5lLiBleHRlcm5hbCBrZXkpLCB0aGUgb3BlcmF0aW9uIHdpbGwgZmFpbC4gT3RoZXJ3aXNlLCBpdCB3aWxsXG4gICAqIG5vLW9wLlxuICAgKi9cbiAgYWRkVG9SZXNvdXJjZVBvbGljeShzdGF0ZW1lbnQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQsIGFsbG93Tm9PcD86IGJvb2xlYW4pOiBpYW0uQWRkVG9SZXNvdXJjZVBvbGljeVJlc3VsdDtcblxuICAvKipcbiAgICogR3JhbnQgdGhlIGluZGljYXRlZCBwZXJtaXNzaW9ucyBvbiB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIEdyYW50IGRlY3J5cHRpb24gcGVybWlzc2lvbnMgdXNpbmcgdGhpcyBrZXkgdG8gdGhlIGdpdmVuIHByaW5jaXBhbFxuICAgKi9cbiAgZ3JhbnREZWNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBHcmFudCBlbmNyeXB0aW9uIHBlcm1pc3Npb25zIHVzaW5nIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICovXG4gIGdyYW50RW5jcnlwdChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogR3JhbnQgZW5jcnlwdGlvbiBhbmQgZGVjcnlwdGlvbiBwZXJtaXNzaW9ucyB1c2luZyB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBncmFudEVuY3J5cHREZWNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xufVxuXG5hYnN0cmFjdCBjbGFzcyBLZXlCYXNlIGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJS2V5IHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGtleS5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBrZXlBcm46IHN0cmluZztcblxuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkga2V5SWQ6IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgcG9saWN5IGRvY3VtZW50IHRoYXQgcmVwcmVzZW50cyB0aGUgcmVzb3VyY2UgcG9saWN5IG9mIHRoaXMga2V5LlxuICAgKlxuICAgKiBJZiBzcGVjaWZpZWQsIGFkZFRvUmVzb3VyY2VQb2xpY3kgY2FuIGJlIHVzZWQgdG8gZWRpdCB0aGlzIHBvbGljeS5cbiAgICogT3RoZXJ3aXNlIHRoaXMgbWV0aG9kIHdpbGwgbm8tb3AuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgcG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCBwcm9wZXJ0eSB0byBjb250cm9sIHRydXN0aW5nIGFjY291bnQgaWRlbnRpdGllcy5cbiAgICpcbiAgICogSWYgc3BlY2lmaWVkLCBncmFudHMgd2lsbCBkZWZhdWx0IGlkZW50aXR5IHBvbGljaWVzIGluc3RlYWQgb2YgdG8gYm90aFxuICAgKiByZXNvdXJjZSBhbmQgaWRlbnRpdHkgcG9saWNpZXMuIFRoaXMgbWF0Y2hlcyB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGNyZWF0aW5nXG4gICAqIEtNUyBrZXlzIHZpYSB0aGUgQVBJIG9yIGNvbnNvbGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgdHJ1c3RBY2NvdW50SWRlbnRpdGllczogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29sbGVjdGlvbiBvZiBhbGlhc2VzIGFkZGVkIHRvIHRoZSBrZXlcbiAgICpcbiAgICogVHJhY2tlZCB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgdGhlIGFsaWFzTmFtZSBzaG91bGQgYmUgYWRkZWQgdG8gdGhlIGVuZCBvZiBpdHMgSURcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgYWxpYXNlczogQWxpYXNbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgbmV3IGFsaWFzIGZvciB0aGUga2V5LlxuICAgKi9cbiAgcHVibGljIGFkZEFsaWFzKGFsaWFzTmFtZTogc3RyaW5nKTogQWxpYXMge1xuICAgIGNvbnN0IGFsaWFzSWQgPSB0aGlzLmFsaWFzZXMubGVuZ3RoID4gMCA/IGBBbGlhcyR7YWxpYXNOYW1lfWAgOiAnQWxpYXMnO1xuXG4gICAgY29uc3QgYWxpYXMgPSBuZXcgQWxpYXModGhpcywgYWxpYXNJZCwgeyBhbGlhc05hbWUsIHRhcmdldEtleTogdGhpcyB9KTtcbiAgICB0aGlzLmFsaWFzZXMucHVzaChhbGlhcyk7XG5cbiAgICByZXR1cm4gYWxpYXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgS01TIGtleSByZXNvdXJjZSBwb2xpY3kuXG4gICAqIEBwYXJhbSBzdGF0ZW1lbnQgVGhlIHBvbGljeSBzdGF0ZW1lbnQgdG8gYWRkXG4gICAqIEBwYXJhbSBhbGxvd05vT3AgSWYgdGhpcyBpcyBzZXQgdG8gYGZhbHNlYCBhbmQgdGhlcmUgaXMgbm8gcG9saWN5XG4gICAqIGRlZmluZWQgKGkuZS4gZXh0ZXJuYWwga2V5KSwgdGhlIG9wZXJhdGlvbiB3aWxsIGZhaWwuIE90aGVyd2lzZSwgaXQgd2lsbFxuICAgKiBuby1vcC5cbiAgICovXG4gIHB1YmxpYyBhZGRUb1Jlc291cmNlUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCwgYWxsb3dOb09wID0gdHJ1ZSk6IGlhbS5BZGRUb1Jlc291cmNlUG9saWN5UmVzdWx0IHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKCF0aGlzLnBvbGljeSkge1xuICAgICAgaWYgKGFsbG93Tm9PcCkgeyByZXR1cm4geyBzdGF0ZW1lbnRBZGRlZDogZmFsc2UgfTsgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gYWRkIHN0YXRlbWVudCB0byBJQU0gcmVzb3VyY2UgcG9saWN5IGZvciBLTVMga2V5OiAke0pTT04uc3RyaW5naWZ5KHN0YWNrLnJlc29sdmUodGhpcy5rZXlBcm4pKX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLnBvbGljeS5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgcmV0dXJuIHsgc3RhdGVtZW50QWRkZWQ6IHRydWUsIHBvbGljeURlcGVuZGFibGU6IHRoaXMucG9saWN5IH07XG4gIH1cblxuICBwcm90ZWN0ZWQgdmFsaWRhdGUoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IHN1cGVyLnZhbGlkYXRlKCk7XG4gICAgZXJyb3JzLnB1c2goLi4udGhpcy5wb2xpY3k/LnZhbGlkYXRlRm9yUmVzb3VyY2VQb2xpY3koKSB8fCBbXSk7XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudCB0aGUgaW5kaWNhdGVkIHBlcm1pc3Npb25zIG9uIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICpcbiAgICogVGhpcyBtb2RpZmllcyBib3RoIHRoZSBwcmluY2lwYWwncyBwb2xpY3kgYXMgd2VsbCBhcyB0aGUgcmVzb3VyY2UgcG9saWN5LFxuICAgKiBzaW5jZSB0aGUgZGVmYXVsdCBDbG91ZEZvcm1hdGlvbiBzZXR1cCBmb3IgS01TIGtleXMgaXMgdGhhdCB0aGUgcG9saWN5XG4gICAqIG11c3Qgbm90IGJlIGVtcHR5IGFuZCBzbyBkZWZhdWx0IGdyYW50cyB3b24ndCB3b3JrLlxuICAgKi9cbiAgcHVibGljIGdyYW50KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlLCAuLi5hY3Rpb25zOiBzdHJpbmdbXSk6IGlhbS5HcmFudCB7XG4gICAgLy8gS01TIHZlcmlmaWVzIHdoZXRoZXIgdGhlIHByaW5jaXBhbHMgaW5jbHVkZWQgaW4gaXRzIGtleSBwb2xpY3kgYWN0dWFsbHkgZXhpc3QuXG4gICAgLy8gVGhpcyBpcyBhIHByb2JsZW0gaWYgdGhlIHN0YWNrIHRoZSBncmFudGVlIGlzIHBhcnQgb2YgZGVwZW5kcyBvbiB0aGUga2V5IHN0YWNrXG4gICAgLy8gKGFzIGl0IHdvbid0IGV4aXN0IGJlZm9yZSB0aGUga2V5IHBvbGljeSBpcyBhdHRlbXB0ZWQgdG8gYmUgY3JlYXRlZCkuXG4gICAgLy8gSW4gdGhhdCBjYXNlLCBtYWtlIHRoZSBhY2NvdW50IHRoZSByZXNvdXJjZSBwb2xpY3kgcHJpbmNpcGFsXG4gICAgY29uc3QgZ3JhbnRlZVN0YWNrRGVwZW5kc09uS2V5U3RhY2sgPSB0aGlzLmdyYW50ZWVTdGFja0RlcGVuZHNPbktleVN0YWNrKGdyYW50ZWUpO1xuICAgIGNvbnN0IHByaW5jaXBhbCA9IGdyYW50ZWVTdGFja0RlcGVuZHNPbktleVN0YWNrXG4gICAgICA/IG5ldyBpYW0uQWNjb3VudFByaW5jaXBhbChncmFudGVlU3RhY2tEZXBlbmRzT25LZXlTdGFjaylcbiAgICAgIDogZ3JhbnRlZS5ncmFudFByaW5jaXBhbDtcblxuICAgIGNvbnN0IGNyb3NzQWNjb3VudEFjY2VzcyA9IHRoaXMuaXNHcmFudGVlRnJvbUFub3RoZXJBY2NvdW50KGdyYW50ZWUpO1xuICAgIGNvbnN0IGNyb3NzUmVnaW9uQWNjZXNzID0gdGhpcy5pc0dyYW50ZWVGcm9tQW5vdGhlclJlZ2lvbihncmFudGVlKTtcbiAgICBjb25zdCBjcm9zc0Vudmlyb25tZW50ID0gY3Jvc3NBY2NvdW50QWNjZXNzIHx8IGNyb3NzUmVnaW9uQWNjZXNzO1xuICAgIGNvbnN0IGdyYW50T3B0aW9uczogaWFtLkdyYW50V2l0aFJlc291cmNlT3B0aW9ucyA9IHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2U6IHRoaXMsXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLmtleUFybl0sXG4gICAgICByZXNvdXJjZVNlbGZBcm5zOiBjcm9zc0Vudmlyb25tZW50ID8gdW5kZWZpbmVkIDogWycqJ10sXG4gICAgfTtcbiAgICBpZiAodGhpcy50cnVzdEFjY291bnRJZGVudGl0aWVzICYmICFjcm9zc0Vudmlyb25tZW50KSB7XG4gICAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsT3JSZXNvdXJjZShncmFudE9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsQW5kUmVzb3VyY2Uoe1xuICAgICAgICAuLi5ncmFudE9wdGlvbnMsXG4gICAgICAgIC8vIGlmIHRoZSBrZXkgaXMgdXNlZCBpbiBhIGNyb3NzLWVudmlyb25tZW50IG1hdHRlcixcbiAgICAgICAgLy8gd2UgY2FuJ3QgYWNjZXNzIHRoZSBLZXkgQVJOICh0aGV5IGRvbid0IGhhdmUgcGh5c2ljYWwgbmFtZXMpLFxuICAgICAgICAvLyBzbyBmYWxsIGJhY2sgdG8gdXNpbmcgJyonLiBUb0RvIHdlIG5lZWQgdG8gbWFrZSB0aGlzIGJldHRlci4uLiBzb21laG93XG4gICAgICAgIHJlc291cmNlQXJuczogY3Jvc3NFbnZpcm9ubWVudCA/IFsnKiddIDogW3RoaXMua2V5QXJuXSxcbiAgICAgICAgcmVzb3VyY2VQb2xpY3lQcmluY2lwYWw6IHByaW5jaXBhbCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudCBkZWNyeXB0aW9uIHBlcm1pc3Npb25zIHVzaW5nIHRoaXMga2V5IHRvIHRoZSBnaXZlbiBwcmluY2lwYWxcbiAgICovXG4gIHB1YmxpYyBncmFudERlY3J5cHQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiB0aGlzLmdyYW50KGdyYW50ZWUsIC4uLnBlcm1zLkRFQ1JZUFRfQUNUSU9OUyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgZW5jcnlwdGlvbiBwZXJtaXNzaW9ucyB1c2luZyB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRFbmNyeXB0KGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gdGhpcy5ncmFudChncmFudGVlLCAuLi5wZXJtcy5FTkNSWVBUX0FDVElPTlMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IGVuY3J5cHRpb24gYW5kIGRlY3J5cHRpb24gcGVybWlzc2lvbnMgdXNpbmcgdGhpcyBrZXkgdG8gdGhlIGdpdmVuIHByaW5jaXBhbFxuICAgKi9cbiAgcHVibGljIGdyYW50RW5jcnlwdERlY3J5cHQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiB0aGlzLmdyYW50KGdyYW50ZWUsIC4uLlsuLi5wZXJtcy5ERUNSWVBUX0FDVElPTlMsIC4uLnBlcm1zLkVOQ1JZUFRfQUNUSU9OU10pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3aGV0aGVyIHRoZSBncmFudGVlIGJlbG9uZ3MgdG8gYSBzdGFjayB0aGF0IHdpbGwgYmUgZGVwbG95ZWRcbiAgICogYWZ0ZXIgdGhlIHN0YWNrIGNvbnRhaW5pbmcgdGhpcyBrZXkuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIHRoZSBncmFudGVlIHRvIGdpdmUgcGVybWlzc2lvbnMgdG9cbiAgICogQHJldHVybnMgdGhlIGFjY291bnQgSUQgb2YgdGhlIGdyYW50ZWUgc3RhY2sgaWYgaXRzIHN0YWNrIGRvZXMgZGVwZW5kIG9uIHRoaXMgc3RhY2ssXG4gICAqICAgdW5kZWZpbmVkIG90aGVyd2lzZVxuICAgKi9cbiAgcHJpdmF0ZSBncmFudGVlU3RhY2tEZXBlbmRzT25LZXlTdGFjayhncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZ3JhbnRQcmluY2lwYWwgPSBncmFudGVlLmdyYW50UHJpbmNpcGFsO1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRQcmluY2lwYWwpKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvLyB0aGlzIGxvZ2ljIHNob3VsZCBvbmx5IGFwcGx5IHRvIG5ld2x5IGNyZWF0ZWRcbiAgICAvLyAoPSBub3QgaW1wb3J0ZWQpIHJlc291cmNlc1xuICAgIGlmICghdGhpcy5wcmluY2lwYWxJc0FOZXdseUNyZWF0ZWRSZXNvdXJjZShncmFudFByaW5jaXBhbCkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3Qga2V5U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBncmFudGVlU3RhY2sgPSBTdGFjay5vZihncmFudFByaW5jaXBhbCk7XG4gICAgaWYgKGtleVN0YWNrID09PSBncmFudGVlU3RhY2spIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBncmFudGVlU3RhY2suZGVwZW5kZW5jaWVzLmluY2x1ZGVzKGtleVN0YWNrKVxuICAgICAgPyBncmFudGVlU3RhY2suYWNjb3VudFxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIHByaW5jaXBhbElzQU5ld2x5Q3JlYXRlZFJlc291cmNlKHByaW5jaXBhbDogSUNvbnN0cnVjdCk6IGJvb2xlYW4ge1xuICAgIC8vIHllcywgdGhpcyBzdWNrc1xuICAgIC8vIHRoaXMgaXMganVzdCBhIHRlbXBvcmFyeSBzdG9wZ2FwIHRvIHN0ZW0gdGhlIGJsZWVkaW5nIHdoaWxlIHdlIHdvcmsgb24gYSBwcm9wZXIgZml4XG4gICAgcmV0dXJuIHByaW5jaXBhbCBpbnN0YW5jZW9mIGlhbS5Sb2xlIHx8XG4gICAgICBwcmluY2lwYWwgaW5zdGFuY2VvZiBpYW0uVXNlciB8fFxuICAgICAgcHJpbmNpcGFsIGluc3RhbmNlb2YgaWFtLkdyb3VwO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0dyYW50ZWVGcm9tQW5vdGhlclJlZ2lvbihncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGJvb2xlYW4ge1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRlZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgYnVja2V0U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBpZGVudGl0eVN0YWNrID0gU3RhY2sub2YoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIGJ1Y2tldFN0YWNrLnJlZ2lvbiAhPT0gaWRlbnRpdHlTdGFjay5yZWdpb247XG4gIH1cblxuICBwcml2YXRlIGlzR3JhbnRlZUZyb21Bbm90aGVyQWNjb3VudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGJvb2xlYW4ge1xuICAgIGlmICghaXNDb25zdHJ1Y3QoZ3JhbnRlZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgYnVja2V0U3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBjb25zdCBpZGVudGl0eVN0YWNrID0gU3RhY2sub2YoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIGJ1Y2tldFN0YWNrLmFjY291bnQgIT09IGlkZW50aXR5U3RhY2suYWNjb3VudDtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBrZXkgc3BlYywgcmVwcmVzZW50cyB0aGUgY3J5cHRvZ3JhcGhpYyBjb25maWd1cmF0aW9uIG9mIGtleXMuXG4gKi9cbmV4cG9ydCBlbnVtIEtleVNwZWMge1xuICAvKipcbiAgICogVGhlIGRlZmF1bHQga2V5IHNwZWMuXG4gICAqXG4gICAqIFZhbGlkIHVzYWdlOiBFTkNSWVBUX0RFQ1JZUFRcbiAgICovXG4gIFNZTU1FVFJJQ19ERUZBVUxUID0gJ1NZTU1FVFJJQ19ERUZBVUxUJyxcblxuICAvKipcbiAgICogUlNBIHdpdGggMjA0OCBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV8yMDQ4ID0gJ1JTQV8yMDQ4JyxcblxuICAvKipcbiAgICogUlNBIHdpdGggMzA3MiBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV8zMDcyID0gJ1JTQV8zMDcyJyxcblxuICAvKipcbiAgICogUlNBIHdpdGggNDA5NiBiaXRzIG9mIGtleS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IEVOQ1JZUFRfREVDUllQVCBhbmQgU0lHTl9WRVJJRllcbiAgICovXG4gIFJTQV80MDk2ID0gJ1JTQV80MDk2JyxcblxuICAvKipcbiAgICogTklTVCBGSVBTIDE4Ni00LCBTZWN0aW9uIDYuNCwgRUNEU0Egc2lnbmF0dXJlIHVzaW5nIHRoZSBjdXJ2ZSBzcGVjaWZpZWQgYnkgdGhlIGtleSBhbmRcbiAgICogU0hBLTI1NiBmb3IgdGhlIG1lc3NhZ2UgZGlnZXN0LlxuICAgKlxuICAgKiBWYWxpZCB1c2FnZTogU0lHTl9WRVJJRllcbiAgICovXG4gIEVDQ19OSVNUX1AyNTYgPSAnRUNDX05JU1RfUDI1NicsXG5cbiAgLyoqXG4gICAqIE5JU1QgRklQUyAxODYtNCwgU2VjdGlvbiA2LjQsIEVDRFNBIHNpZ25hdHVyZSB1c2luZyB0aGUgY3VydmUgc3BlY2lmaWVkIGJ5IHRoZSBrZXkgYW5kXG4gICAqIFNIQS0zODQgZm9yIHRoZSBtZXNzYWdlIGRpZ2VzdC5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IFNJR05fVkVSSUZZXG4gICAqL1xuICBFQ0NfTklTVF9QMzg0ID0gJ0VDQ19OSVNUX1AzODQnLFxuXG4gIC8qKlxuICAgKiBOSVNUIEZJUFMgMTg2LTQsIFNlY3Rpb24gNi40LCBFQ0RTQSBzaWduYXR1cmUgdXNpbmcgdGhlIGN1cnZlIHNwZWNpZmllZCBieSB0aGUga2V5IGFuZFxuICAgKiBTSEEtNTEyIGZvciB0aGUgbWVzc2FnZSBkaWdlc3QuXG4gICAqXG4gICAqIFZhbGlkIHVzYWdlOiBTSUdOX1ZFUklGWVxuICAgKi9cbiAgRUNDX05JU1RfUDUyMSA9ICdFQ0NfTklTVF9QNTIxJyxcblxuICAvKipcbiAgICogU3RhbmRhcmRzIGZvciBFZmZpY2llbnQgQ3J5cHRvZ3JhcGh5IDIsIFNlY3Rpb24gMi40LjEsIEVDRFNBIHNpZ25hdHVyZSBvbiB0aGUgS29ibGl0eiBjdXJ2ZS5cbiAgICpcbiAgICogVmFsaWQgdXNhZ2U6IFNJR05fVkVSSUZZXG4gICAqL1xuICBFQ0NfU0VDR19QMjU2SzEgPSAnRUNDX1NFQ0dfUDI1NksxJyxcbn1cblxuLyoqXG4gKiBUaGUga2V5IHVzYWdlLCByZXByZXNlbnRzIHRoZSBjcnlwdG9ncmFwaGljIG9wZXJhdGlvbnMgb2Yga2V5cy5cbiAqL1xuZXhwb3J0IGVudW0gS2V5VXNhZ2Uge1xuICAvKipcbiAgICogRW5jcnlwdGlvbiBhbmQgZGVjcnlwdGlvbi5cbiAgICovXG4gIEVOQ1JZUFRfREVDUllQVCA9ICdFTkNSWVBUX0RFQ1JZUFQnLFxuXG4gIC8qKlxuICAgKiBTaWduaW5nIGFuZCB2ZXJpZmljYXRpb25cbiAgICovXG4gIFNJR05fVkVSSUZZID0gJ1NJR05fVkVSSUZZJyxcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBmb3IgYSBLTVMgS2V5IG9iamVjdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEtleVByb3BzIHtcbiAgLyoqXG4gICAqIEEgZGVzY3JpcHRpb24gb2YgdGhlIGtleS4gVXNlIGEgZGVzY3JpcHRpb24gdGhhdCBoZWxwcyB5b3VyIHVzZXJzIGRlY2lkZVxuICAgKiB3aGV0aGVyIHRoZSBrZXkgaXMgYXBwcm9wcmlhdGUgZm9yIGEgcGFydGljdWxhciB0YXNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGRlc2NyaXB0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgYWxpYXMgdG8gYWRkIHRvIHRoZSBrZXlcbiAgICpcbiAgICogTW9yZSBhbGlhc2VzIGNhbiBiZSBhZGRlZCBsYXRlciBieSBjYWxsaW5nIGBhZGRBbGlhc2AuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gYWxpYXMgaXMgYWRkZWQgZm9yIHRoZSBrZXkuXG4gICAqL1xuICByZWFkb25seSBhbGlhcz86IHN0cmluZztcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgQVdTIEtNUyByb3RhdGVzIHRoZSBrZXkuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVLZXlSb3RhdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBrZXkgaXMgYXZhaWxhYmxlIGZvciB1c2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gS2V5IGlzIGVuYWJsZWQuXG4gICAqL1xuICByZWFkb25seSBlbmFibGVkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGNyeXB0b2dyYXBoaWMgY29uZmlndXJhdGlvbiBvZiB0aGUga2V5LiBUaGUgdmFsaWQgdmFsdWUgZGVwZW5kcyBvbiB1c2FnZSBvZiB0aGUga2V5LlxuICAgKlxuICAgKiBJTVBPUlRBTlQ6IElmIHlvdSBjaGFuZ2UgdGhpcyBwcm9wZXJ0eSBvZiBhbiBleGlzdGluZyBrZXksIHRoZSBleGlzdGluZyBrZXkgaXMgc2NoZWR1bGVkIGZvciBkZWxldGlvblxuICAgKiBhbmQgYSBuZXcga2V5IGlzIGNyZWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIHZhbHVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBLZXlTcGVjLlNZTU1FVFJJQ19ERUZBVUxUXG4gICAqL1xuICByZWFkb25seSBrZXlTcGVjPzogS2V5U3BlYztcblxuICAvKipcbiAgICogVGhlIGNyeXB0b2dyYXBoaWMgb3BlcmF0aW9ucyBmb3Igd2hpY2ggdGhlIGtleSBjYW4gYmUgdXNlZC5cbiAgICpcbiAgICogSU1QT1JUQU5UOiBJZiB5b3UgY2hhbmdlIHRoaXMgcHJvcGVydHkgb2YgYW4gZXhpc3Rpbmcga2V5LCB0aGUgZXhpc3Rpbmcga2V5IGlzIHNjaGVkdWxlZCBmb3IgZGVsZXRpb25cbiAgICogYW5kIGEgbmV3IGtleSBpcyBjcmVhdGVkIHdpdGggdGhlIHNwZWNpZmllZCB2YWx1ZS5cbiAgICpcbiAgICogQGRlZmF1bHQgS2V5VXNhZ2UuRU5DUllQVF9ERUNSWVBUXG4gICAqL1xuICByZWFkb25seSBrZXlVc2FnZT86IEtleVVzYWdlO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gcG9saWN5IGRvY3VtZW50IHRvIGF0dGFjaCB0byB0aGUgS01TIGtleS5cbiAgICpcbiAgICogTk9URSAtIElmIHRoZSBgQGF3cy1jZGsvYXdzLWttczpkZWZhdWx0S2V5UG9saWNpZXNgIGZlYXR1cmUgZmxhZyBpcyBzZXQgKHRoZSBkZWZhdWx0IGZvciBuZXcgcHJvamVjdHMpLFxuICAgKiB0aGlzIHBvbGljeSB3aWxsICpvdmVycmlkZSogdGhlIGRlZmF1bHQga2V5IHBvbGljeSBhbmQgYmVjb21lIHRoZSBvbmx5IGtleSBwb2xpY3kgZm9yIHRoZSBrZXkuIElmIHRoZVxuICAgKiBmZWF0dXJlIGZsYWcgaXMgbm90IHNldCwgdGhpcyBwb2xpY3kgd2lsbCBiZSBhcHBlbmRlZCB0byB0aGUgZGVmYXVsdCBrZXkgcG9saWN5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgcG9saWN5IGRvY3VtZW50IHdpdGggcGVybWlzc2lvbnMgZm9yIHRoZSBhY2NvdW50IHJvb3QgdG9cbiAgICogYWRtaW5pc3RlciB0aGUga2V5IHdpbGwgYmUgY3JlYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHBvbGljeT86IGlhbS5Qb2xpY3lEb2N1bWVudDtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIHByaW5jaXBhbHMgdG8gYWRkIGFzIGtleSBhZG1pbmlzdHJhdG9ycyB0byB0aGUga2V5IHBvbGljeS5cbiAgICpcbiAgICogS2V5IGFkbWluaXN0cmF0b3JzIGhhdmUgcGVybWlzc2lvbnMgdG8gbWFuYWdlIHRoZSBrZXkgKGUuZy4sIGNoYW5nZSBwZXJtaXNzaW9ucywgcmV2b2tlKSwgYnV0IGRvIG5vdCBoYXZlIHBlcm1pc3Npb25zXG4gICAqIHRvIHVzZSB0aGUga2V5IGluIGNyeXB0b2dyYXBoaWMgb3BlcmF0aW9ucyAoZS5nLiwgZW5jcnlwdCwgZGVjcnlwdCkuXG4gICAqXG4gICAqIFRoZXNlIHByaW5jaXBhbHMgd2lsbCBiZSBhZGRlZCB0byB0aGUgZGVmYXVsdCBrZXkgcG9saWN5IChpZiBub25lIHNwZWNpZmllZCksIG9yIHRvIHRoZSBzcGVjaWZpZWQgcG9saWN5IChpZiBwcm92aWRlZCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBhZG1pbnM/OiBpYW0uSVByaW5jaXBhbFtdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBlbmNyeXB0aW9uIGtleSBzaG91bGQgYmUgcmV0YWluZWQgd2hlbiBpdCBpcyByZW1vdmVkIGZyb20gdGhlIFN0YWNrLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIG9uZSB3YW50cyB0b1xuICAgKiByZXRhaW4gYWNjZXNzIHRvIGRhdGEgdGhhdCB3YXMgZW5jcnlwdGVkIHdpdGggYSBrZXkgdGhhdCBpcyBiZWluZyByZXRpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBSZW1vdmFsUG9saWN5LlJldGFpblxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGtleSB1c2FnZSBjYW4gYmUgZ3JhbnRlZCBieSBJQU0gcG9saWNpZXNcbiAgICpcbiAgICogU2V0dGluZyB0aGlzIHRvIHRydWUgYWRkcyBhIGRlZmF1bHQgc3RhdGVtZW50IHdoaWNoIGRlbGVnYXRlcyBrZXlcbiAgICogYWNjZXNzIGNvbnRyb2wgY29tcGxldGVseSB0byB0aGUgaWRlbnRpdHkncyBJQU0gcG9saWN5IChzaW1pbGFyXG4gICAqIHRvIGhvdyBpdCB3b3JrcyBmb3Igb3RoZXIgQVdTIHJlc291cmNlcykuIFRoaXMgbWF0Y2hlcyB0aGUgZGVmYXVsdCBiZWhhdmlvclxuICAgKiB3aGVuIGNyZWF0aW5nIEtNUyBrZXlzIHZpYSB0aGUgQVBJIG9yIGNvbnNvbGUuXG4gICAqXG4gICAqIElmIHRoZSBgQGF3cy1jZGsvYXdzLWttczpkZWZhdWx0S2V5UG9saWNpZXNgIGZlYXR1cmUgZmxhZyBpcyBzZXQgKHRoZSBkZWZhdWx0IGZvciBuZXcgcHJvamVjdHMpLFxuICAgKiB0aGlzIGZsYWcgd2lsbCBhbHdheXMgYmUgdHJlYXRlZCBhcyAndHJ1ZScgYW5kIGRvZXMgbm90IG5lZWQgdG8gYmUgZXhwbGljaXRseSBzZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZmFsc2UsIHVubGVzcyB0aGUgYEBhd3MtY2RrL2F3cy1rbXM6ZGVmYXVsdEtleVBvbGljaWVzYCBmZWF0dXJlIGZsYWcgaXMgc2V0LlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9rbXMvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2tleS1wb2xpY2llcy5odG1sI2tleS1wb2xpY3ktZGVmYXVsdC1hbGxvdy1yb290LWVuYWJsZS1pYW1cbiAgICogQGRlcHJlY2F0ZWQgcmVkdW5kYW50IHdpdGggdGhlIGBAYXdzLWNkay9hd3Mta21zOmRlZmF1bHRLZXlQb2xpY2llc2AgZmVhdHVyZSBmbGFnXG4gICAqL1xuICByZWFkb25seSB0cnVzdEFjY291bnRJZGVudGl0aWVzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgd2FpdGluZyBwZXJpb2QgYmVmb3JlXG4gICAqIEFXUyBLTVMgZGVsZXRlcyBhIENNSyB0aGF0IGhhcyBiZWVuIHJlbW92ZWQgZnJvbSBhIENsb3VkRm9ybWF0aW9uIHN0YWNrLlxuICAgKlxuICAgKiBXaGVuIHlvdSByZW1vdmUgYSBjdXN0b21lciBtYXN0ZXIga2V5IChDTUspIGZyb20gYSBDbG91ZEZvcm1hdGlvbiBzdGFjaywgQVdTIEtNUyBzY2hlZHVsZXMgdGhlIENNSyBmb3IgZGVsZXRpb25cbiAgICogYW5kIHN0YXJ0cyB0aGUgbWFuZGF0b3J5IHdhaXRpbmcgcGVyaW9kLiBUaGUgUGVuZGluZ1dpbmRvd0luRGF5cyBwcm9wZXJ0eSBkZXRlcm1pbmVzIHRoZSBsZW5ndGggb2Ygd2FpdGluZyBwZXJpb2QuXG4gICAqIER1cmluZyB0aGUgd2FpdGluZyBwZXJpb2QsIHRoZSBrZXkgc3RhdGUgb2YgQ01LIGlzIFBlbmRpbmcgRGVsZXRpb24sIHdoaWNoIHByZXZlbnRzIHRoZSBDTUsgZnJvbSBiZWluZyB1c2VkIGluXG4gICAqIGNyeXB0b2dyYXBoaWMgb3BlcmF0aW9ucy4gV2hlbiB0aGUgd2FpdGluZyBwZXJpb2QgZXhwaXJlcywgQVdTIEtNUyBwZXJtYW5lbnRseSBkZWxldGVzIHRoZSBDTUsuXG4gICAqXG4gICAqIEVudGVyIGEgdmFsdWUgYmV0d2VlbiA3IGFuZCAzMCBkYXlzLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1yZXNvdXJjZS1rbXMta2V5Lmh0bWwjY2ZuLWttcy1rZXktcGVuZGluZ3dpbmRvd2luZGF5c1xuICAgKiBAZGVmYXVsdCAtIDMwIGRheXNcbiAgICovXG4gIHJlYWRvbmx5IHBlbmRpbmdXaW5kb3c/OiBEdXJhdGlvbjtcbn1cblxuLyoqXG4gKiBEZWZpbmVzIGEgS01TIGtleS5cbiAqXG4gKiBAcmVzb3VyY2UgQVdTOjpLTVM6OktleVxuICovXG5leHBvcnQgY2xhc3MgS2V5IGV4dGVuZHMgS2V5QmFzZSB7XG4gIC8qKlxuICAgKiBJbXBvcnQgYW4gZXh0ZXJuYWxseSBkZWZpbmVkIEtNUyBLZXkgdXNpbmcgaXRzIEFSTi5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlICB0aGUgY29uc3RydWN0IHRoYXQgd2lsbCBcIm93blwiIHRoZSBpbXBvcnRlZCBrZXkuXG4gICAqIEBwYXJhbSBpZCAgICAgdGhlIGlkIG9mIHRoZSBpbXBvcnRlZCBrZXkgaW4gdGhlIGNvbnN0cnVjdCB0cmVlLlxuICAgKiBAcGFyYW0ga2V5QXJuIHRoZSBBUk4gb2YgYW4gZXhpc3RpbmcgS01TIGtleS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUtleUFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBrZXlBcm46IHN0cmluZyk6IElLZXkge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIEtleUJhc2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGtleUFybiA9IGtleUFybjtcbiAgICAgIHB1YmxpYyByZWFkb25seSBrZXlJZDogc3RyaW5nO1xuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHBvbGljeT86IGlhbS5Qb2xpY3lEb2N1bWVudCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgIC8vIGRlZmF1bHRpbmcgdHJ1ZTogaWYgd2UgYXJlIGltcG9ydGluZyB0aGUga2V5IHRoZSBrZXkgcG9saWN5IGlzXG4gICAgICAvLyB1bmRlZmluZWQgYW5kIGltcG9zc2libGUgdG8gY2hhbmdlIGhlcmU7IHRoaXMgbWVhbnMgdXBkYXRpbmcgaWRlbnRpdHlcbiAgICAgIC8vIHBvbGljaWVzIGlzIHJlYWxseSB0aGUgb25seSBvcHRpb25cbiAgICAgIHByb3RlY3RlZCByZWFkb25seSB0cnVzdEFjY291bnRJZGVudGl0aWVzOiBib29sZWFuID0gdHJ1ZTtcblxuICAgICAgY29uc3RydWN0b3Ioa2V5SWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgICAgIHRoaXMua2V5SWQgPSBrZXlJZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBrZXlSZXNvdXJjZU5hbWUgPSBTdGFjay5vZihzY29wZSkuc3BsaXRBcm4oa2V5QXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lO1xuICAgIGlmICgha2V5UmVzb3VyY2VOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEtNUyBrZXkgQVJOIG11c3QgYmUgaW4gdGhlIGZvcm1hdCAnYXJuOmF3czprbXM6PHJlZ2lvbj46PGFjY291bnQ+OmtleS88a2V5SWQ+JywgZ290OiAnJHtrZXlBcm59J2ApO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgSW1wb3J0KGtleVJlc291cmNlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbXV0YWJsZSB7QGxpbmsgSUtleX0gYmFzZWQgb24gYSBsb3ctbGV2ZWwge0BsaW5rIENmbktleX0uXG4gICAqIFRoaXMgaXMgbW9zdCB1c2VmdWwgd2hlbiBjb21iaW5lZCB3aXRoIHRoZSBjbG91ZGZvcm1hdGlvbi1pbmNsdWRlIG1vZHVsZS5cbiAgICogVGhpcyBtZXRob2QgaXMgZGlmZmVyZW50IHRoYW4ge0BsaW5rIGZyb21LZXlBcm4oKX0gYmVjYXVzZSB0aGUge0BsaW5rIElLZXl9XG4gICAqIHJldHVybmVkIGZyb20gdGhpcyBtZXRob2QgaXMgbXV0YWJsZTtcbiAgICogbWVhbmluZywgY2FsbGluZyBhbnkgbXV0YXRpbmcgbWV0aG9kcyBvbiBpdCxcbiAgICogbGlrZSB7QGxpbmsgSUtleS5hZGRUb1Jlc291cmNlUG9saWN5KCl9LFxuICAgKiB3aWxsIGFjdHVhbGx5IGJlIHJlZmxlY3RlZCBpbiB0aGUgcmVzdWx0aW5nIHRlbXBsYXRlLFxuICAgKiBhcyBvcHBvc2VkIHRvIHRoZSBvYmplY3QgcmV0dXJuZWQgZnJvbSB7QGxpbmsgZnJvbUtleUFybigpfSxcbiAgICogb24gd2hpY2ggY2FsbGluZyB0aG9zZSBtZXRob2RzIHdvdWxkIGhhdmUgbm8gZWZmZWN0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tQ2ZuS2V5KGNmbktleTogQ2ZuS2V5KTogSUtleSB7XG4gICAgLy8gdXNlIGEgXCJ3ZWlyZFwiIGlkIHRoYXQgaGFzIGEgaGlnaGVyIGNoYW5jZSBvZiBiZWluZyB1bmlxdWVcbiAgICBjb25zdCBpZCA9ICdARnJvbUNmbktleSc7XG5cbiAgICAvLyBpZiBmcm9tQ2ZuS2V5KCkgd2FzIGFscmVhZHkgY2FsbGVkIG9uIHRoaXMgY2ZuS2V5LFxuICAgIC8vIHJldHVybiB0aGUgc2FtZSBMMlxuICAgIC8vIChhcyBkaWZmZXJlbnQgTDJzIHdvdWxkIGNvbmZsaWN0LCBiZWNhdXNlIG9mIHRoZSBtdXRhdGlvbiBvZiB0aGUga2V5UG9saWN5IHByb3BlcnR5IG9mIHRoZSBMMSBiZWxvdylcbiAgICBjb25zdCBleGlzdGluZyA9IGNmbktleS5ub2RlLnRyeUZpbmRDaGlsZChpZCk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gPElLZXk+ZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgbGV0IGtleVBvbGljeTogaWFtLlBvbGljeURvY3VtZW50O1xuICAgIHRyeSB7XG4gICAgICBrZXlQb2xpY3kgPSBpYW0uUG9saWN5RG9jdW1lbnQuZnJvbUpzb24oY2ZuS2V5LmtleVBvbGljeSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gSWYgdGhlIEtleVBvbGljeSBjb250YWlucyBhbnkgQ2xvdWRGb3JtYXRpb24gZnVuY3Rpb25zLFxuICAgICAgLy8gUG9saWN5RG9jdW1lbnQuZnJvbUpzb24oKSB0aHJvd3MgYW4gZXhjZXB0aW9uLlxuICAgICAgLy8gSW4gdGhhdCBjYXNlLCBiZWNhdXNlIHdlIHdvdWxkIGhhdmUgdG8gZWZmZWN0aXZlbHkgbWFrZSB0aGUgcmV0dXJuZWQgSUtleSBpbW11dGFibGUsXG4gICAgICAvLyB0aHJvdyBhbiBleGNlcHRpb24gc3VnZ2VzdGluZyB0byB1c2UgdGhlIG90aGVyIGltcG9ydGluZyBtZXRob2RzIGluc3RlYWQuXG4gICAgICAvLyBXZSBtaWdodCBtYWtlIHRoaXMgcGFyc2luZyBsb2dpYyBzbWFydGVyIGxhdGVyLFxuICAgICAgLy8gYnV0IGxldCdzIHN0YXJ0IGJ5IGVycm9yaW5nIG91dC5cbiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IHBhcnNlIHRoZSBQb2xpY3lEb2N1bWVudCBvZiB0aGUgcGFzc2VkIEFXUzo6S01TOjpLZXkgcmVzb3VyY2UgYmVjYXVzZSBpdCBjb250YWlucyBDbG91ZEZvcm1hdGlvbiBmdW5jdGlvbnMuICcgK1xuICAgICAgICAnVGhpcyBtYWtlcyBpdCBpbXBvc3NpYmxlIHRvIGNyZWF0ZSBhIG11dGFibGUgSUtleSBmcm9tIHRoYXQgUG9saWN5LiAnICtcbiAgICAgICAgJ1lvdSBoYXZlIHRvIHVzZSBmcm9tS2V5QXJuIGluc3RlYWQsIHBhc3NpbmcgaXQgdGhlIEFSTiBhdHRyaWJ1dGUgcHJvcGVydHkgb2YgdGhlIGxvdy1sZXZlbCBDZm5LZXknKTtcbiAgICB9XG5cbiAgICAvLyBjaGFuZ2UgdGhlIGtleSBwb2xpY3kgb2YgdGhlIEwxLCBzbyB0aGF0IGFsbCBjaGFuZ2VzIGRvbmUgaW4gdGhlIEwyIGFyZSByZWZsZWN0ZWQgaW4gdGhlIHJlc3VsdGluZyB0ZW1wbGF0ZVxuICAgIGNmbktleS5rZXlQb2xpY3kgPSBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IGtleVBvbGljeS50b0pTT04oKSB9KTtcblxuICAgIHJldHVybiBuZXcgY2xhc3MgZXh0ZW5kcyBLZXlCYXNlIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBrZXlBcm4gPSBjZm5LZXkuYXR0ckFybjtcbiAgICAgIHB1YmxpYyByZWFkb25seSBrZXlJZCA9IGNmbktleS5yZWY7XG4gICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcG9saWN5ID0ga2V5UG9saWN5O1xuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHRydXN0QWNjb3VudElkZW50aXRpZXMgPSBmYWxzZTtcbiAgICB9KGNmbktleSwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhbiBleGlzdGluZyBLZXkgYnkgcXVlcnlpbmcgdGhlIEFXUyBlbnZpcm9ubWVudCB0aGlzIHN0YWNrIGlzIGRlcGxveWVkIHRvLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIG9ubHkgbmVlZHMgdG8gYmUgdXNlZCB0byB1c2UgS2V5cyBub3QgZGVmaW5lZCBpbiB5b3VyIENES1xuICAgKiBhcHBsaWNhdGlvbi4gSWYgeW91IGFyZSBsb29raW5nIHRvIHNoYXJlIGEgS2V5IGJldHdlZW4gc3RhY2tzLCB5b3UgY2FuXG4gICAqIHBhc3MgdGhlIGBLZXlgIG9iamVjdCBiZXR3ZWVuIHN0YWNrcyBhbmQgdXNlIGl0IGFzIG5vcm1hbC4gSW4gYWRkaXRpb24sXG4gICAqIGl0J3Mgbm90IG5lY2Vzc2FyeSB0byB1c2UgdGhpcyBtZXRob2QgaWYgYW4gaW50ZXJmYWNlIGFjY2VwdHMgYW4gYElLZXlgLlxuICAgKiBJbiB0aGlzIGNhc2UsIGBBbGlhcy5mcm9tQWxpYXNOYW1lKClgIGNhbiBiZSB1c2VkIHdoaWNoIHJldHVybnMgYW4gYWxpYXNcbiAgICogdGhhdCBleHRlbmRzIGBJS2V5YC5cbiAgICpcbiAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aWxsIGxlYWQgdG8gYSBsb29rdXAgd2hlbiB0aGUgQ0RLIENMSSBpcyBleGVjdXRlZC5cbiAgICogWW91IGNhbiB0aGVyZWZvcmUgbm90IHVzZSBhbnkgdmFsdWVzIHRoYXQgd2lsbCBvbmx5IGJlIGF2YWlsYWJsZSBhdFxuICAgKiBDbG91ZEZvcm1hdGlvbiBleGVjdXRpb24gdGltZSAoaS5lLiwgVG9rZW5zKS5cbiAgICpcbiAgICogVGhlIEtleSBpbmZvcm1hdGlvbiB3aWxsIGJlIGNhY2hlZCBpbiBgY2RrLmNvbnRleHQuanNvbmAgYW5kIHRoZSBzYW1lIEtleVxuICAgKiB3aWxsIGJlIHVzZWQgb24gZnV0dXJlIHJ1bnMuIFRvIHJlZnJlc2ggdGhlIGxvb2t1cCwgeW91IHdpbGwgaGF2ZSB0b1xuICAgKiBldmljdCB0aGUgdmFsdWUgZnJvbSB0aGUgY2FjaGUgdXNpbmcgdGhlIGBjZGsgY29udGV4dGAgY29tbWFuZC4gU2VlXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jZGsvbGF0ZXN0L2d1aWRlL2NvbnRleHQuaHRtbCBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUxvb2t1cChzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBvcHRpb25zOiBLZXlMb29rdXBPcHRpb25zKTogSUtleSB7XG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgS2V5QmFzZSB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkga2V5QXJuOiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkga2V5SWQ6IHN0cmluZztcbiAgICAgIHByb3RlY3RlZCByZWFkb25seSBwb2xpY3k/OiBpYW0uUG9saWN5RG9jdW1lbnQgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICAvLyBkZWZhdWx0aW5nIHRydWU6IGlmIHdlIGFyZSBpbXBvcnRpbmcgdGhlIGtleSB0aGUga2V5IHBvbGljeSBpc1xuICAgICAgLy8gdW5kZWZpbmVkIGFuZCBpbXBvc3NpYmxlIHRvIGNoYW5nZSBoZXJlOyB0aGlzIG1lYW5zIHVwZGF0aW5nIGlkZW50aXR5XG4gICAgICAvLyBwb2xpY2llcyBpcyByZWFsbHkgdGhlIG9ubHkgb3B0aW9uXG4gICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdHJ1c3RBY2NvdW50SWRlbnRpdGllczogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAgIGNvbnN0cnVjdG9yKGtleUlkOiBzdHJpbmcsIGtleUFybjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICAgICAgdGhpcy5rZXlJZCA9IGtleUlkO1xuICAgICAgICB0aGlzLmtleUFybiA9IGtleUFybjtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChvcHRpb25zLmFsaWFzTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWxsIGFyZ3VtZW50cyB0byBLZXkuZnJvbUxvb2t1cCgpIG11c3QgYmUgY29uY3JldGUgKG5vIFRva2VucyknKTtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRyaWJ1dGVzOiBjeGFwaS5LZXlDb250ZXh0UmVzcG9uc2UgPSBDb250ZXh0UHJvdmlkZXIuZ2V0VmFsdWUoc2NvcGUsIHtcbiAgICAgIHByb3ZpZGVyOiBjeHNjaGVtYS5Db250ZXh0UHJvdmlkZXIuS0VZX1BST1ZJREVSLFxuICAgICAgcHJvcHM6IHtcbiAgICAgICAgYWxpYXNOYW1lOiBvcHRpb25zLmFsaWFzTmFtZSxcbiAgICAgIH0gYXMgY3hzY2hlbWEuS2V5Q29udGV4dFF1ZXJ5LFxuICAgICAgZHVtbXlWYWx1ZToge1xuICAgICAgICBrZXlJZDogJzEyMzRhYmNkLTEyYWItMzRjZC01NmVmLTEyMzQ1Njc4OTBhYicsXG4gICAgICB9LFxuICAgIH0pLnZhbHVlO1xuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoYXR0cmlidXRlcy5rZXlJZCxcbiAgICAgIEFybi5mb3JtYXQoeyByZXNvdXJjZTogJ2tleScsIHNlcnZpY2U6ICdrbXMnLCByZXNvdXJjZU5hbWU6IGF0dHJpYnV0ZXMua2V5SWQgfSwgU3RhY2sub2Yoc2NvcGUpKSk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkga2V5QXJuOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBrZXlJZDogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdHJ1c3RBY2NvdW50SWRlbnRpdGllczogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogS2V5UHJvcHMgPSB7fSkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCBkZW55TGlzdHMgPSB7XG4gICAgICBbS2V5VXNhZ2UuRU5DUllQVF9ERUNSWVBUXTogW1xuICAgICAgICBLZXlTcGVjLkVDQ19OSVNUX1AyNTYsXG4gICAgICAgIEtleVNwZWMuRUNDX05JU1RfUDM4NCxcbiAgICAgICAgS2V5U3BlYy5FQ0NfTklTVF9QNTIxLFxuICAgICAgICBLZXlTcGVjLkVDQ19TRUNHX1AyNTZLMSxcbiAgICAgIF0sXG4gICAgICBbS2V5VXNhZ2UuU0lHTl9WRVJJRlldOiBbXG4gICAgICAgIEtleVNwZWMuU1lNTUVUUklDX0RFRkFVTFQsXG4gICAgICBdLFxuICAgIH07XG4gICAgY29uc3Qga2V5U3BlYyA9IHByb3BzLmtleVNwZWMgPz8gS2V5U3BlYy5TWU1NRVRSSUNfREVGQVVMVDtcbiAgICBjb25zdCBrZXlVc2FnZSA9IHByb3BzLmtleVVzYWdlID8/IEtleVVzYWdlLkVOQ1JZUFRfREVDUllQVDtcbiAgICBpZiAoZGVueUxpc3RzW2tleVVzYWdlXS5pbmNsdWRlcyhrZXlTcGVjKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXkgc3BlYyAnJHtrZXlTcGVjfScgaXMgbm90IHZhbGlkIHdpdGggdXNhZ2UgJyR7a2V5VXNhZ2V9J2ApO1xuICAgIH1cblxuICAgIGlmIChrZXlTcGVjICE9PSBLZXlTcGVjLlNZTU1FVFJJQ19ERUZBVUxUICYmIHByb3BzLmVuYWJsZUtleVJvdGF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tleSByb3RhdGlvbiBjYW5ub3QgYmUgZW5hYmxlZCBvbiBhc3ltbWV0cmljIGtleXMnKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZWZhdWx0S2V5UG9saWNpZXNGZWF0dXJlRW5hYmxlZCA9IEZlYXR1cmVGbGFncy5vZih0aGlzKS5pc0VuYWJsZWQoY3hhcGkuS01TX0RFRkFVTFRfS0VZX1BPTElDSUVTKTtcblxuICAgIHRoaXMucG9saWN5ID0gcHJvcHMucG9saWN5ID8/IG5ldyBpYW0uUG9saWN5RG9jdW1lbnQoKTtcbiAgICBpZiAoZGVmYXVsdEtleVBvbGljaWVzRmVhdHVyZUVuYWJsZWQpIHtcbiAgICAgIGlmIChwcm9wcy50cnVzdEFjY291bnRJZGVudGl0aWVzID09PSBmYWxzZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2B0cnVzdEFjY291bnRJZGVudGl0aWVzYCBjYW5ub3QgYmUgZmFsc2UgaWYgdGhlIEBhd3MtY2RrL2F3cy1rbXM6ZGVmYXVsdEtleVBvbGljaWVzIGZlYXR1cmUgZmxhZyBpcyBzZXQnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy50cnVzdEFjY291bnRJZGVudGl0aWVzID0gdHJ1ZTtcbiAgICAgIC8vIFNldCB0aGUgZGVmYXVsdCBrZXkgcG9saWN5IGlmIG9uZSBoYXNuJ3QgYmVlbiBwcm92aWRlZCBieSB0aGUgdXNlci5cbiAgICAgIGlmICghcHJvcHMucG9saWN5KSB7XG4gICAgICAgIHRoaXMuYWRkRGVmYXVsdEFkbWluUG9saWN5KCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudHJ1c3RBY2NvdW50SWRlbnRpdGllcyA9IHByb3BzLnRydXN0QWNjb3VudElkZW50aXRpZXMgPz8gZmFsc2U7XG4gICAgICBpZiAodGhpcy50cnVzdEFjY291bnRJZGVudGl0aWVzKSB7XG4gICAgICAgIHRoaXMuYWRkRGVmYXVsdEFkbWluUG9saWN5KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZExlZ2FjeUFkbWluUG9saWN5KCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHBlbmRpbmdXaW5kb3dJbkRheXM7XG4gICAgaWYgKHByb3BzLnBlbmRpbmdXaW5kb3cpIHtcbiAgICAgIHBlbmRpbmdXaW5kb3dJbkRheXMgPSBwcm9wcy5wZW5kaW5nV2luZG93LnRvRGF5cygpO1xuICAgICAgaWYgKHBlbmRpbmdXaW5kb3dJbkRheXMgPCA3IHx8IHBlbmRpbmdXaW5kb3dJbkRheXMgPiAzMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCdwZW5kaW5nV2luZG93JyB2YWx1ZSBtdXN0IGJldHdlZW4gNyBhbmQgMzAgZGF5cy4gUmVjZWl2ZWQ6ICR7cGVuZGluZ1dpbmRvd0luRGF5c31gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBDZm5LZXkodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgZGVzY3JpcHRpb246IHByb3BzLmRlc2NyaXB0aW9uLFxuICAgICAgZW5hYmxlS2V5Um90YXRpb246IHByb3BzLmVuYWJsZUtleVJvdGF0aW9uLFxuICAgICAgZW5hYmxlZDogcHJvcHMuZW5hYmxlZCxcbiAgICAgIGtleVNwZWM6IHByb3BzLmtleVNwZWMsXG4gICAgICBrZXlVc2FnZTogcHJvcHMua2V5VXNhZ2UsXG4gICAgICBrZXlQb2xpY3k6IHRoaXMucG9saWN5LFxuICAgICAgcGVuZGluZ1dpbmRvd0luRGF5czogcGVuZGluZ1dpbmRvd0luRGF5cyxcbiAgICB9KTtcblxuICAgIHRoaXMua2V5QXJuID0gcmVzb3VyY2UuYXR0ckFybjtcbiAgICB0aGlzLmtleUlkID0gcmVzb3VyY2UucmVmO1xuICAgIHJlc291cmNlLmFwcGx5UmVtb3ZhbFBvbGljeShwcm9wcy5yZW1vdmFsUG9saWN5KTtcblxuICAgIChwcm9wcy5hZG1pbnMgPz8gW10pLmZvckVhY2goKHApID0+IHRoaXMuZ3JhbnRBZG1pbihwKSk7XG5cbiAgICBpZiAocHJvcHMuYWxpYXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5hZGRBbGlhcyhwcm9wcy5hbGlhcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IGFkbWlucyBwZXJtaXNzaW9ucyB1c2luZyB0aGlzIGtleSB0byB0aGUgZ2l2ZW4gcHJpbmNpcGFsXG4gICAqXG4gICAqIEtleSBhZG1pbmlzdHJhdG9ycyBoYXZlIHBlcm1pc3Npb25zIHRvIG1hbmFnZSB0aGUga2V5IChlLmcuLCBjaGFuZ2UgcGVybWlzc2lvbnMsIHJldm9rZSksIGJ1dCBkbyBub3QgaGF2ZSBwZXJtaXNzaW9uc1xuICAgKiB0byB1c2UgdGhlIGtleSBpbiBjcnlwdG9ncmFwaGljIG9wZXJhdGlvbnMgKGUuZy4sIGVuY3J5cHQsIGRlY3J5cHQpLlxuICAgKi9cbiAgcHVibGljIGdyYW50QWRtaW4oZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiB0aGlzLmdyYW50KGdyYW50ZWUsIC4uLnBlcm1zLkFETUlOX0FDVElPTlMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgdGhlIGRlZmF1bHQga2V5IHBvbGljeSB0byB0aGUga2V5LiBUaGlzIHBvbGljeSBnaXZlcyB0aGUgQVdTIGFjY291bnQgKHJvb3QgdXNlcikgZnVsbCBhY2Nlc3MgdG8gdGhlIENNSyxcbiAgICogd2hpY2ggcmVkdWNlcyB0aGUgcmlzayBvZiB0aGUgQ01LIGJlY29taW5nIHVubWFuYWdlYWJsZSBhbmQgZW5hYmxlcyBJQU0gcG9saWNpZXMgdG8gYWxsb3cgYWNjZXNzIHRvIHRoZSBDTUsuXG4gICAqIFRoaXMgaXMgdGhlIHNhbWUgcG9saWN5IHRoYXQgaXMgZGVmYXVsdCB3aGVuIGNyZWF0aW5nIGEgS2V5IHZpYSB0aGUgS01TIEFQSSBvciBDb25zb2xlLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9rbXMvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2tleS1wb2xpY2llcy5odG1sI2tleS1wb2xpY3ktZGVmYXVsdFxuICAgKi9cbiAgcHJpdmF0ZSBhZGREZWZhdWx0QWRtaW5Qb2xpY3koKSB7XG4gICAgdGhpcy5hZGRUb1Jlc291cmNlUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICBhY3Rpb25zOiBbJ2ttczoqJ10sXG4gICAgICBwcmluY2lwYWxzOiBbbmV3IGlhbS5BY2NvdW50Um9vdFByaW5jaXBhbCgpXSxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHRoZSBhY2NvdW50IGFkbWluIHByaXZpbGVnZXMgLS0gbm90IGZ1bGwgYWNjb3VudCBhY2Nlc3MgLS0gcGx1cyB0aGUgR2VuZXJhdGVEYXRhS2V5IGFjdGlvbi5cbiAgICogVGhlIEdlbmVyYXRlRGF0YUtleSBhY3Rpb24gd2FzIGFkZGVkIGZvciBpbnRlcm9wIHdpdGggUzMgaW4gaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8zNDU4LlxuICAgKlxuICAgKiBUaGlzIHBvbGljeSBpcyBkaXNjb3VyYWdlZCBhbmQgZGVwcmVjYXRlZCBieSB0aGUgYEBhd3MtY2RrL2F3cy1rbXM6ZGVmYXVsdEtleVBvbGljaWVzYCBmZWF0dXJlIGZsYWcuXG4gICAqXG4gICAqIEBsaW5rIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9rbXMvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2tleS1wb2xpY2llcy5odG1sI2tleS1wb2xpY3ktZGVmYXVsdFxuICAgKiBAZGVwcmVjYXRlZFxuICAgKi9cbiAgcHJpdmF0ZSBhZGRMZWdhY3lBZG1pblBvbGljeSgpIHtcbiAgICAvLyBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gYFsuLi5wZXJtcy5BRE1JTl9BQ1RJT05TLCAna21zOkdlbmVyYXRlRGF0YUtleSddYCxcbiAgICAvLyBidXQga2VlcGluZyB0aGlzIGV4cGxpY2l0IG9yZGVyaW5nIGZvciBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSAoY2hhbmdpbmcgdGhlIG9yZGVyaW5nIGNhdXNlcyByZXNvdXJjZSB1cGRhdGVzKVxuICAgIGNvbnN0IGFjdGlvbnMgPSBbXG4gICAgICAna21zOkNyZWF0ZSonLFxuICAgICAgJ2ttczpEZXNjcmliZSonLFxuICAgICAgJ2ttczpFbmFibGUqJyxcbiAgICAgICdrbXM6TGlzdConLFxuICAgICAgJ2ttczpQdXQqJyxcbiAgICAgICdrbXM6VXBkYXRlKicsXG4gICAgICAna21zOlJldm9rZSonLFxuICAgICAgJ2ttczpEaXNhYmxlKicsXG4gICAgICAna21zOkdldConLFxuICAgICAgJ2ttczpEZWxldGUqJyxcbiAgICAgICdrbXM6U2NoZWR1bGVLZXlEZWxldGlvbicsXG4gICAgICAna21zOkNhbmNlbEtleURlbGV0aW9uJyxcbiAgICAgICdrbXM6R2VuZXJhdGVEYXRhS2V5JyxcbiAgICAgICdrbXM6VGFnUmVzb3VyY2UnLFxuICAgICAgJ2ttczpVbnRhZ1Jlc291cmNlJyxcbiAgICBdO1xuXG4gICAgdGhpcy5hZGRUb1Jlc291cmNlUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICBhY3Rpb25zLFxuICAgICAgcHJpbmNpcGFsczogW25ldyBpYW0uQWNjb3VudFJvb3RQcmluY2lwYWwoKV0sXG4gICAgfSkpO1xuICB9XG59XG5cbi8qKlxuICogV2hldGhlciB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGEgQ29uc3RydWN0XG4gKlxuICogTm9ybWFsbHkgd2UnZCBkbyBgeCBpbnN0YW5jZW9mIENvbnN0cnVjdGAsIGJ1dCB0aGF0IGlzIG5vdCByb2J1c3QgYWdhaW5zdFxuICogbXVsdGlwbGUgY29waWVzIG9mIHRoZSBgY29uc3RydWN0c2AgbGlicmFyeSBvbiBkaXNrLiBUaGlzIGNhbiBoYXBwZW5cbiAqIHdoZW4gdXBncmFkaW5nIGFuZCBkb3duZ3JhZGluZyBiZXR3ZWVuIHYyIGFuZCB2MSwgYW5kIGluIHRoZSB1c2Ugb2YgQ0RLXG4gKiBQaXBlbGluZXMgaXMgZ29pbmcgdG8gYW4gZXJyb3IgdGhhdCBzYXlzIFwiQ2FuJ3QgdXNlIFBpcGVsaW5lL1BpcGVsaW5lL1JvbGUgaW5cbiAqIGEgY3Jvc3MtZW52aXJvbm1lbnQgZmFzaGlvblwiLCB3aGljaCBpcyB2ZXJ5IGNvbmZ1c2luZy5cbiAqL1xuZnVuY3Rpb24gaXNDb25zdHJ1Y3QoeDogYW55KTogeCBpcyBDb25zdHJ1Y3Qge1xuICBjb25zdCBzeW0gPSBTeW1ib2wuZm9yKCdjb25zdHJ1Y3RzLkNvbnN0cnVjdC5ub2RlJyk7XG4gIHJldHVybiAodHlwZW9mIHggPT09ICdvYmplY3QnICYmIHggJiZcbiAgICAoeCBpbnN0YW5jZW9mIENvbnN0cnVjdCAvLyBoYXBweSBmYXN0IGNhc2VcbiAgICB8fCAhISh4IGFzIGFueSkubm9kZSAvLyBjb25zdHJ1Y3RzIHYxMFxuICAgIHx8ICEhKHggYXMgYW55KVtzeW1dKSk7IC8vIGNvbnN0cnVjdHMgdjNcbn0iXX0=
\No newline at end of file