summary refs log tree commit diff
path: root/crypto/test/src/pqc/crypto/test/SphincsPlusTest.cs
blob: efeab54bd52ff75c35c6712a631781ed5e68c459 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using NUnit.Framework;

using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pqc.Crypto.SphincsPlus;
using Org.BouncyCastle.Pqc.Crypto.Utilities;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;

using PqcPrivateKeyFactory = Org.BouncyCastle.Pqc.Crypto.Utilities.PqcPrivateKeyFactory;
using PqcPublicKeyFactory = Org.BouncyCastle.Pqc.Crypto.Utilities.PqcPublicKeyFactory;

namespace Org.BouncyCastle.Pqc.Crypto.Tests
{
    [TestFixture]
    public class SphincsPlusTest
    {
        private static readonly string[] TestVectorFilesRobustFast =
        {
            "sha2-128f-robust.rsp",
            "sha2-192f-robust.rsp",
            "sha2-256f-robust.rsp",
            "shake-128f-robust.rsp",
            "shake-192f-robust.rsp",
            "shake-256f-robust.rsp",
            "haraka-128f-robust.rsp",
            "haraka-192f-robust.rsp",
            "haraka-256f-robust.rsp",
        };

        private static readonly string[] TestVectorFilesRobustSlow =
        {
            "sha2-128s-robust.rsp",
            "sha2-192s-robust.rsp",
            "sha2-256s-robust.rsp",
            "shake-128s-robust.rsp",
            "shake-192s-robust.rsp",
            "shake-256s-robust.rsp",
            "haraka-128s-robust.rsp",
            "haraka-192s-robust.rsp",
            "haraka-256s-robust.rsp",
        };

        private static readonly string[] TestVectorFilesSimpleFast =
        {
            "sha2-128f-simple.rsp",
            "sha2-192f-simple.rsp",
            "sha2-256f-simple.rsp",
            "shake-128f-simple.rsp",
            "shake-192f-simple.rsp",
            "shake-256f-simple.rsp",
            "haraka-128f-simple.rsp",
            "haraka-192f-simple.rsp",
            "haraka-256f-simple.rsp",
        };

        private static readonly string[] TestVectorFilesSimpleSlow =
        {
            "sha2-128s-simple.rsp",
            "sha2-192s-simple.rsp",
            "sha2-256s-simple.rsp",
            "shake-128s-simple.rsp",
            "shake-192s-simple.rsp",
            "shake-256s-simple.rsp",
            "haraka-128s-simple.rsp",
            "haraka-192s-simple.rsp",
            "haraka-256s-simple.rsp",
        };

        [TestCaseSource(nameof(TestVectorFilesRobustFast))]
        [Parallelizable(ParallelScope.All)]
        public void TVRobustFast(string testVectorFile)
        {
            RunTestVectorFile(testVectorFile);
        }

        [Explicit, TestCaseSource(nameof(TestVectorFilesRobustSlow))]
        [Parallelizable(ParallelScope.All)]
        public void TVRobustSlow(string testVectorFile)
        {
            RunTestVectorFile(testVectorFile);
        }

        [TestCaseSource(nameof(TestVectorFilesSimpleFast))]
        [Parallelizable(ParallelScope.All)]
        public void TVSimpleFast(string testVectorFile)
        {
            RunTestVectorFile(testVectorFile);
        }

        [Explicit, TestCaseSource(nameof(TestVectorFilesSimpleSlow))]
        [Parallelizable(ParallelScope.All)]
        public void TVSimpleSlow(string testVectorFile)
        {
            RunTestVectorFile(testVectorFile);
        }

        [Test]
        public void TestBasicKeyGeneration()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();
            FixedSecureRandom.Source[] source = { new FixedSecureRandom.Source(Hex.Decode("7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A3E784CCB7EBCDCFD45542B7F6AF778742E0F4479175084AA488B3B74340678AAD111491E7E52F6F1D726DAF2A4E75CAFB60D034B6E912B26BE68464B0095D60D")) };

            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.shake_256f));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), Hex.Decode("3e784ccb7ebcdcfd45542b7f6af778742e0f4479175084aa488b3b74340678aa6ba9430051e61cb676e8449087b938a79575b3a16736ce68a3655a28001155f5")), pubParams.GetEncoded()));
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e4792f267aafa3f87ca60d01cb54f29202a3e784ccb7ebcdcfd45542b7f6af778742e0f4479175084aa488b3b74340678aa6ba9430051e61cb676e8449087b938a79575b3a16736ce68a3655a28001155f5")), privParams.GetEncoded()));

            SubjectPublicKeyInfo pubInfo = PqcSubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubParams);
            PrivateKeyInfo privInfo = PqcPrivateKeyInfoFactory.CreatePrivateKeyInfo(privParams);

            pubParams = (SphincsPlusPublicKeyParameters)PqcPublicKeyFactory.CreateKey(pubInfo.GetEncoded());
            privParams = (SphincsPlusPrivateKeyParameters)PqcPrivateKeyFactory.CreateKey(privInfo.GetEncoded());

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), Hex.Decode("3e784ccb7ebcdcfd45542b7f6af778742e0f4479175084aa488b3b74340678aa6ba9430051e61cb676e8449087b938a79575b3a16736ce68a3655a28001155f5")), pubParams.GetEncoded()));
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e4792f267aafa3f87ca60d01cb54f29202a3e784ccb7ebcdcfd45542b7f6af778742e0f4479175084aa488b3b74340678aa6ba9430051e61cb676e8449087b938a79575b3a16736ce68a3655a28001155f5")), privParams.GetEncoded()));
        }

        [Test]
        public void TestBasicKeyImportSimpleSign()
        {
            SphincsPlusPublicKeyParameters pubParams = new SphincsPlusPublicKeyParameters(SphincsPlusParameters.sha2_128f, Hex.Decode("b505d7cfad1b497499323c8686325e473985e5a31e5b9a0457916c84320c2ea8"));
            SphincsPlusPrivateKeyParameters privParams = new SphincsPlusPrivateKeyParameters(SphincsPlusParameters.sha2_128f, Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e473985e5a31e5b9a0457916c84320c2ea8"));

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), Hex.Decode("b505d7cfad1b497499323c8686325e473985e5a31e5b9a0457916c84320c2ea8")), pubParams.GetEncoded()));
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e473985e5a31e5b9a0457916c84320c2ea8")), privParams.GetEncoded()));

            byte[] msg = Hex.Decode("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8");

            SphincsPlusSigner signer = new SphincsPlusSigner();

            FixedSecureRandom.Source[] source1 =
                {new FixedSecureRandom.Source(Hex.Decode("33b3c07507e4201748494d832b6ee2a6"))};
            FixedSecureRandom fr = new FixedSecureRandom(source1);
            signer.Init(true, new ParametersWithRandom(privParams, fr));

            byte[] sig = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sig, msg);

            byte[] expected = Hex.Decode(
                "b77b5397031e67eb585dba86b10b710b9729f44d1c00335014a674bed98b2569712954fc906b9ea4a9b2bffc37157e4973b56bc31f42619e38d67e37057da076b694ffe6c973ddda2526d5cb9056ec5b0d15901d3cc712f659f19113281a7dfc88a202189a2a770e79233bd3c89fa28cdd45e68b90f23a6f50a31da75590e3b4cb38baba4415235517099b467d0fcd54954b0653a995b035ffe418c1e7ba589380899556d1c9b3125d1f95e5827cfccf27aab6c28c990ca63292f465ccb268b16bb4440edbeaf88b4441fefb233921c87a06efbd2555e18abcaf0698261dd38c9b8ce8e06fb685388d1efdeed30b4f89248f953b168d909a58cba1f6cd879d548b5ed0c99c2273c31307d85666a7aaa5220ec159024ba387b9a0d49a6fec92c345db70cf5e2f387dbfbd20a92846db29c718140eee861c57f7354a1b9f837b714e95801e1f9ec57b805078aa0007d13773ceeb5ae4a5d2033ce802e05743990c71953838e960022cbcc1a117db4d74c70f68600926f6678b7c413e4074870ab6594078f2235ccc77f5bb4261daae596d0cc949528ebb1d05a30e200bb10627038d7ecec177eca4d98d3744d78c0027deeff398a3ee55d25cb03d49340c2f8b9313e74733b8affc7a332472f71131f598701bf2d152a2c5ebe294235fd17c6deca8cf749f675ba246561c2e65594113a69920da467988b9cf9f5039d9dba8044ac5b32ebf6d40887743d5fd8fb40b14777c9542da410d0a1288a25399192932ff83d2eb754bb7de80f9a3f81e0656ec2029f933e5f317cf695af96d900d20ec6ce8cae703084b326ba133c170f502f5cef25b11f2336b37db164992c2aac51a6877f440eb92c30dfd359cad0c1b8d412d8669a1e89f361713c1c7fb0af32888cf536d25314c90bf84e18fb6794e7ece3579d5faa9b001484f867445abf841365638c0616436102800e4762ba2d770386f35d0465b9f951fec7ee0a9e71f2fde1b13fab4ede6a66598cc4f01db107afbb361f9030d25424326708804159089f5135ff7431f4b7ef1644c0162f136dabfd3f4d66cbfaa474da07dd75dedfeb8639e3dc8260973d27f940286053ee1cf8c014013c56d4792c0126062086812d22dafa38ec0076cae11f8280af11e1c3a5b51e6e82bbe1df2c6c06fc03b77e0d47a91c4959acafdeaa4466b5f19f6b13af4c8de4cda8dada9cd8bb1eb8aceb911841c6a4808553f906312fd63c1a54945e2fb2683c20ee47dd98f4638f9c60e0bbcb9f352dff272f6e292c18598d3279089ada457f93850d7d5024023fb8db95b7a3ab994a80dcbfa1120cfca74bcf16bc6b68693b093af58f4df469b96a1c16cdd2feefe0cfbd0b8de6695dde07b1dff288fd314a469f55db6b8e997757e391bfe4eaa88deda15b01688c4aad9af5aea2fed0e09a11b048d04188327bd49e0f33046fe5d8383f6c639d5c852936cdb20e7616cecbde2984d6119a9eec0c8532a39fde133739e1790434002cb57d6657456be6110d0289c06f1b5960269b6fea99a2ff67cb5f0dabc55dab8f72402759754c80c82825c639dd4c6c47e7529c7128c26cc908680583800cd6b7263e0baca09eafaad078339e4ed2fd5b91d13c01ba168254687adc787438e72d5249dd3816fe572bbcdccdce4b259b93b1a59ba4ded18eb4bce856de66e7867b7bc7bba3dee1af7d752b33bdc9cd61b41abea88fd415a81b3f4fde9435a5588d43376aa34a7a5c654248567bf045c4fe2c5ee4f713e070a4b4b7f7caa0ef31d0b3de5c81ba893c3efd197dd83ed5c92529383fc7d4d2f2cbdee3cfeddb939ec200e8ba37a2d74a3ce6948df5c2a09c3d668ae56835210532669fa824f6183d3daf1be6c6de9b8b0dcb83c6db66f00e421145d0d0887a167408ed86d5ba25cae25f0b95305ae718b7c203985c67c6529c6e9bff744abbf3da6b0188c808ec24b3e3301ea2b5c191b97d37c1c92ef94560549a2a7a7e8a7b00ca03a7eee4ff7b1e01e39eeb1897304b22f5e2e05b277e8b9a387ddbea2b759ea738b12d0a3ddd5a8026e7baa58701e2fe41a9ead6eddeacf0f7b543367dfd86e8be30e2053b5e336a850dbeb62ca85a254f9f564d551cae6bd2b8ef5b8255f650c015110ad3a01d2d3414032b6d6b3e3ad4b0ec542bd615ade98f06dddb732ba6f76cb4597c35069b2cb689e965609671ff629278806983c92b2d206f7cb139eb8e9c0c219ddf758d5b58e1a0ce27475fdc246d744e3b238ddbcf35fe965f97f7559d6c34f137e08d8b737f564fc04e00146483306408caa1e42c566a4106c13d5dbefea3d901b94ffd2cf14d30885d47144e6b63d58685904db1d18faadac0eb80f3d8403fe1b78807c4f6fe4b677a61812533a59e34de32655e78ce8c3cc2e8e01100ab04511738fbaa9e1bd26b3a4443d352ddebd5dbf3bd15bab146b20936b5b5ce4c3032a2d89a20daa9596451798cdb70bdd539bc9c3c396efba34a3c2cc276b4dd9763633393be3c4c76cd54a4b88d2f93f220d70f1f252223fba93a97f560935e0a5388b643796e65c2c360faed55ac20ebe59fdaf3c84652ace1abe52ef4dca01fd737a3d1cf345b14d6e12e7151dcdb85c83c902925d3e2a643b9d9a9ec4ad4f6a905491612394edbd8e3d0e159a5980b4237b450c71e1d068d6162b28eddee2c9b8a9d43f8ffaee9dd4b12df4998b8b9f4bff94f7aa2d1380fa27c8de29fad5b128cc0cde45222cdcd9d6468907ff2a49418cee5d535a85dcbf2171cfd99fbf7ff253f5d0c442b0bb99d638f3cb0aa455c2c948ee99197fd3231c20c917c9816057507acf5e25d5ffa8b518e50c8246f5fd57cf3bc918efa39ebc8a85139f887e396a2b69a39c3c3b60a6225ddfbbdafdce824be479f3fee0dd74ee751726e1490c37802e1208d4398a20ca3f9474e0b7e88fdaee462fa56a49f2b5912a6c6c31e0d49a70a75f6a7fd125600885745cce6bcb97955d7d71f62258318202afc4ef0cb3575b7d5fc85036fc8c05a1c41a9e95bfd86094a25a1c7150e1b7b3cf04efac3c4754c7d385061ad92eb88f722a4b422efb86bdc73e8d580b7d034c73dc0cd627d5698ce3ab3d5d26564325b6607dc3d3225045d75276fee30709e3a3556aaf104894c00e4622209e5ea290d119ef6abe807fbed1c75e0a28514138d346d891e364f8b66aae317885edd7a6267dbf0bd24355f3783c3a630391c4992a53d1fd7a9a3d6917f81c2eae5ad51dbb580e109c93b3f6ef521d921b9c6dc9a23a1f3707a81e777d5c4eefa00ed05e520333088c7236ca47e8a3c26874fdf28e46b0a6243c19efeb9ca8db26fcb5b23753974c0337efd22cd1d7cd4f565fff0c2c202ae92876c679514a3ad6e635219e24df04e683a6663ee01d8e5484f13a1bae303285cb5fef0e216a786e2cf2de22463000bd2ea0610692b0867fc99dac92e30e6419590e0ec1ba9e019a9adc764a634cc644f0eef532b562a6441fb38af94269bc3dbcf21ebc934217d7578edaccc69f096fb1317586e1879761593b0f5ecb6c9ccdcbaf3225284e228ed65e9bed58a1155d9314c0f59bd0a81fdb275fc435b5315e27721b3bb010bfb79426ec630bbc2e6c86c78bc929dafbcc99aa68428b692b3ba27361127ca3f767b022d69eae04dcb0749e83654f4e38b5fcfbee6cc85d44dbf7322bc3c948b4b2d8e243f47b987d4936c6c7b04b68c272e9572db02d21be567fb92775562bafe686c5d27c84344f777206252695a6269b67265a9d8e9efbc4f1c6e142062c5addbd1d7f0684e69d00cf76d397beede5e1289b35cd933f0c73544d3053f28c6bd69a35d66f252ff0dd5093c51b415affd9dc12f123405e388a8a8e7bf623b487d21c4d61bc19a01d3aaefc0b0f2a058ce3df837111d3ddd1c6b671761d38faf282f4ac19c51e31ea9b4845e7ff92d072f8fcbfcc71dcb3373ebb8998ed88804a82ce4df08a16efdc8daf107247a8c29abb1de728f2f169230e562e149514b170b556414bb5a57a97867eb2275b742f72bd7e99765a4fa4b4ec3d4f144e7eb064acd664dfaefa50a42c6eeb454644fb2c58c19e43c8cc3bc63f73f9dbb54aea2f1af54a82326a0b5d7dcc0a1f5fd4427579ee9a8fd11abec77a99641f6306750211cd270b68049e18630c9a8de7f1b81495720459b0544a0f7557635873ccd0739176296ba2ac88638b39506ef0abab8e609e5f2d3fae18fad79d63ffce20ec18de5b7a20e29555381e71c7d78c2a23e26e60bb89736ac0f487529dbba530166a283c3d6b809bb253c4bae2fe1573a95c54202b3a3cfd508de5946748f31b9bd93127d56cb59b30508d4c6af98a68c6a0960bc34bc100444973141cbc304d22022c78c936d23c29f978c05ef52671a2e0399ab2818a72699e1c227ecb9fa8082cae430172bbed14bc4d4325eac06c3dba1d9a9631f85b93405f8f1819df155935d20d910702decd638c56a1a0eaa09eba95fd7ccef463b8670a365baff0b1b49a9c344de385d7acfbf2d972f35a1efc5338c3690a287f504b86f53e1646d936375708554f835afe2e66849c128ba0fa6fa240d98faa293fb7375de3fa898334eb98bd4e6bc7a08e45a70b26710d92f544af27b6c9bed3ed748994fe26b7a1365f13e18740a4acefbbeff6bddb8fafa3261c27c2298f4e9a77d5d19cb5b9ebb371cb89cb37ee12fd39480f85072c3ce24487aa8f638233ab1b17aeb89fc3e0e6efc9a47db1e5c01ad9d66f030e2681f7d6b08f1ccb164ab091ee57d5626700d26ef813c807d399383d569bb274d01c02540ceb3a02b503ec68f62bc06f50e5f1505bbad87bb4edd84e193b957f8f7d1f75a71fda2e9426a395d444acb30e5d8bfac5484518c5db31fc05e82b05e8de4fbba4aa8d8fe090a5070d44d0eba0b18555eb2c30888a18921cc4236b6c0727e89bdefe15ba5b4fac9842625977151a677c84841f10e66af5d90c69bee4b7cbafb7591a048b1a406a384dde6dee737a3a65d1cbc78a8c58adf429cbb7928580a92b747d22e75fca419ad7f15a6efb5b61d19364e93171870189a2f60db90b12fa8452740eaf3dd6841e50ed3187e0cbd721139dc11aac761c9d2697c190fb78fbc6bbb45009afc75f42806d1007c3de9a4012e1d265921953502f6f1a3be76bc01e1653506fbeae79bfc666a2ce36da259834c5632fff3f72b7bec63554caaed996a4d4b0342ffc82ffd39de68bd942210dde2f6fce548b52e56781810749f284418ac13f44cb2c75c797547d26e138317761ad932adfa45c65775247b7ee83607bae60d8cc7d8e4bbfd63c58cbcb4f2a1fecbe2f01ae589a2a4a04b85b49004b47fc20d146db3cf3f785b70bf7c9fff8a23b250143cbe74c5eedb3d3339e5f5afffe4ea77539611ac9cd470026652554a0819f6db9a9b90b42996ef848f59ddefe5eb20e86afb56753e23468bea8387027bc0b4b88fe1becd59b7b9b86a47270fe44cc9275c35330b95aeab0b2ef0ce967c9fac24a54178a8560c8bfd389f8919733001767c1372264af30fb9aeed6cd2eb0355fb59edde9f31a29b72f45291cbab6e664d25b7ec07c0eab272c8f2de139b94b7888244f8df510404476dba4b746b9f4156b50176b814d21f5f921b77238ef9f24a3e8914a8c1bf6c3f62053a2ba97b3657cb3f1d773f97202a4be9e2e6b429ff5e313ba23f56db04efd47e0ec8d4e94d08d775df14967bbbcfe135d9812826e359384a5a2ae5b5ebb1975ac68e8c62e7c2de394fd5e7c3ee3cb81096be684485701172f0bc1e4af21e6a2beef267de52be8cd3bebe7eeb22a120f7e6028b481f6ed64624d106f6347c095099c86e95a8c4592cbe7da9bf7accb43ffa79f93a9e27859026f4e2e13677996834c29005680fb3c705edb5a9364586ee3886557c41cbbf2153edbe62e7ade7e769cab65f98502934b07e86e4972522e4891d937a9db2ce6143505bddd414b9e5c70e2e064cbb4f5db9428845aca240916e0f3974dc858c9157a1ef2382e2d297984aceb5512567ea5b7eb9048fa7053d5f2de4e7c6a505199a1f3eb1f2f679e966fb0c2f981b24f602850d372b18eef6414c0eed50954abcb91269495dbe7b4c3580c3e7fd0b0e4743f2fb52c4c8e13cf0cf1e2094685adfcb59367d3b686c03642d998f483f5ead7ffddfec18122b5348fd561ee8b665f93bba3837f106fdeefcff03d90ae167664583bd0970495d2c5c698aeb6ca934a4a8635fc27ecf605483f7463b2b64085cd0369ae3293df986c9f78c8e441cd800fbabc21d17a2252c70ef82d4f305278b159acdf0a62d1d1c32bca8fb3198ab01798a2aed8569db05d721eaed4776d024044270cc8957f01abea7d37617ff9c6eacaf7d5457ecc4f5c0d2baaa2b698b382aab9f5ee5c06164ffa4e4364d56f7baf44689fd3b99b0196db4eed4cc6e46ad8f3bcdbf40233eb75e019659a032f09540088e3edc95b02b780751bd314d6e5a9e3a10b3cedc4381ac1d601e3d2e715c402eb3487a474cfe3cad055c1a5593a978c928728270e5193b11fa3442f149086487a263e6612719d5dae60e49cbcb16bccc43e12d0df2bb5d08dd53e3d73d7bb3f774863c36e03409b8b585e20d8cd09bf38c6b0f5900d4d2aa93569b87a8fa9fe81addd9a094d5dd24c7479f8b4e13d68975731190670af02e5ee060fdcad842ac73519b8d9572cc4383c2e28a42d0d63394a4b88cf6d382b050f21efb1dbc9ee710d09feb464faa673ba2f319a5644e8aa37bd883ce1b1d62771df8c52b928f58ae0142a7db22436247e2ba9e1e257d952eb2884586a0b8c78af43a2ba928ee8e9a57de5e9a3c622c0993d5f8b35103d332ed84f3c856d8d289a4501fc0ea2023fcea1d0a5c945af886a5d8eed2c182d3f559a4788d1387d7417b37e5767a1070041570043ea99fd026f7cb6148cc261c1368e4cc1da9a180aea3e4b49ad2ccaf75007f42d381ab345d52c75e8c3e237f938c90ecaf4a57af3bc3b990c071bf4a9c4464cde801c4fdb9f667a8fe4196d13b1677db3e273a4519b5abb965aade5cfd42b28e8379ada1636105cf6a7b6e3ec276f2d4ad1c1abee7f084e7098b6535028e5b6e58f5b90f13a9e52d6101fe50b58e2d95e9287a8a4595521780ed2c29dd873537243ea0020eeddb775a9ec334260821f44ce10c22fb12dd95cbd228e0991069345cd4670c72a48e908b75e84da8a44c2899f9462cc932943058dcd0b23b0ef0c1e5f07059ea7deb4ed5dc3a39196c75a4acdfa04184d237f852a0f2129e1dc20d59653e78b4758338e85398d47850fabca5ca7271724ad65064160c61cd3c8df00c9ebefbfae455af427deaa339a2b8973ec47f8f640bb2edc2ef7bc7783ce05cb008d525251bf80fc262a80dc27abe0e80675b3b2afc69a31378324ccc8a8aaf3faf8007971cf8caffd066f487ad44f78acc4aa17c20112144f94a7418a692f3dde011badafd6d5b96e7bdadde3506d95e866b9f74a3f1a9238df900566b44f06d07dee7d4f2a813c2a441eaf27d2a2e3687d85ce447ef2bfa577a537f5353fca51511fcda1c18e3bcda9726258120a0bf30673f3b6d5bf1b2bde36d2a3d9598da0ad6cf2a0cf90205f6decb514604e8001cae824ab75c9cf637e66434e7afecf5f497bc3fa78e6478e7120185af82e675c651c68eb48c5b29b6cb983261b9e2a53def469210a9186fb469ad80c720079bae746042116e0dacd94774306dd764e83ce6b387bbfeab6d9392f2f3bda9a5f565b873861bea8f1771cef6dec27fed9a9a34a7a87765f1d937ca048c3250f5cbba5946420cdf4f2ec69dda96f10bad7b1dbcd68876724086d3fc1f030e71e077de6dc4c0ca92a535e344ec33076aae12a63175f80e1ef95af19ec88f8cffb527422d6ef3e67e3b3178fad746076e68dee1bfc10d95b33b73bdf1fb486104cfcc80aadec620cc438338bdbb93a2bd48eedc92e3562ba4b9bd67bdff768d78c83934ca3ce49c2439c1ee38144d42ff6d0e77fa54d0c684c0f5d2f05a976a7fbebf5241d04b37e4d4040fde9693a34daab9a3e22a375c6c2eb2f5296cb4b1d6f220991a5e68b777445889b9e762ccf6e3809ef5e8ec49f7c7e2f8f7cecaf833bce3004bf98693de2de64fb070aaf958d282348ff980a5879beb9f1bedc137e2478c0f68a75cb20d0689b26cc2f6640100d76fc25f5f0edd410ba3d9a4fa4cf92fabb3ddb00c4b66718ea99159087d1d9e2820e87213526d64fd22b3e2d6749e4a988fb76a1bc290706e882493d858de6f4efadd487d377e6f6f4267a2cb5a42a388065e76517346314c67769a57d850c0f7eebb7eb274fa3b5612c3bafdbbe1536626e7d06913e6251f12b0387d82640a40a86f140b870fec3385950a69d6fc91bc9fb77de6578aa4635a9857004eb50aad28925606d585d20ad74862ae386934f905c47c1c2d044af45ceb15be4fa1ce2df00bbe16768bfbb2236ec62ba2d6f546f5273a2797a20bbe55b266b8b79872e73df7113f9aefbf0cb6caeae02e3b587a5b7d6bc55279b566985676a6ab0bafa36038872371fb7678fce0db6792b76ac08e5f598196c30c8749b2ffbae466d90faf0dc24ba7e29eb783ca57a2bf5c8fe7c8ee4478b6acd3c2f96e15a62722dd4d96dbd598bacfae505f422c2e32e24684cbf6e5d0829001c89c2ec32d9e2fea38faf0a6fbb6afa43f066f7f48c50e8301ba4bc6e1c71ec0669d27b746118e5e40a0cdf8e2f71aa81a1c75c323ec8b7d047841a20c7b92fe759942c79fcd3ae7fbafc97fd0d9f3320ca7849f631a196644e75bf560a72ea1cc08ea6a5a70487320f9b89ed1dca36487196fc88dc4f3c98d2f501a0b8e2161abfbe89400b523f202d1bb0b022eac2481dcb3efb987aa536195371048125f807c90bae718a3f73fdce794bf671e3df3c779d5f95b830d27325744d60085451b090551cd846c8e028366adf212dbd85b7cecdf854dad81121e7ace0f1b0dfe89d22ec49324700d5db66ccf0b8ee398dfd70b86cc315833e2a7db3936b1e276efa033155bfb2f8e64e4cfba8a5d5b956a03e2543796fe4b3476920fd3613c1e056eb299a02d3aba3ba2ef66948bccd530abf5bb37e8da9725de25896184635d7f1f4af44f073d124e2fe7988af57861b9ae0a90015395c429dc18f5ee90c0765d3995487178b71b427f152c37da2cfe14036d6137d97937746352cfb481a913b25c106d4fde9f614074af05626487f61d349d6fd0712a24fe9c56b5f5ab1b8386365237b3c864d4e017424940251eb2d54bfc58e0106a06999f3ef4b88a845f99b44ad5cc967456481048ce71f7bb08902de93b358cfcfa3f0ca9333c6c83aa77ba8b8762013f5cae34e7b2676990c01fdc5f619f1975ecbd40b6a6371ec3a4af3842794a093ac1c9b73355cbc5933ebba0aad104a6798eb6dad32425629fafc0db8bccd2b1f84db338f8828ff1783b633239c589eaa9fa1f045126a5c816cac8414c19d177d7a0b3da01815f9962ea0a0841cd1b428ac38050061a879fbda1345649f66703b7c7dc05c4c6941a72fe5a81379efabef69ef1f6473717c870dad980a4f5a2751eefc71a17dfd6728e7f0c293ba9f855d0bfa33e8c1fdca2b22898fcbae89bcf1038de58533c183bdaab094d537275b92ee0f38b46f01818ef4fb9156ae6485e11103e7cc4c21bbcbd2720fb61147c8fc739d323a25d1309b336cee39be4a354f93a4275b6fe153ab6f5f44b6caa7197039e23b6ba2c83660e7de0f73f939450c15f18ee31f8c095a0d9445a39912bdcfe95380cc39b483a6613c5f0bddb5ba6d56410eeff4d0d96d5d39202d1b789f33aa84e39b6d93b12f8aaf7836aa1ec792fa3178dd61dcd421e55b587451564d14ea3fec931b4198af45d66c98885c84376817ebe1ee08fc4c5cc7054409ac4e9745445c2a3fc8083f1c00c94b3ee2ce606c54373905e90fbc67ffaaa37c32b2df6d0758e2f0e661f40a21c939296d4ed4b1562742d00d4129cfef64862a1fc3c1eb910dcff20b08eda8ae77a4d8a8fd74ef5307de90d6fedecd89d11953ec718081f447446568e5e963e4f41f4b8311373205918e0d88fff9de755a59cf04b2d860146aac7d49ed9878d8756e4c86f1eeb83e15d4de9ba4a619a9c51e770b433c4519cb8ab6ad562da2f448ea4561e13eae4371e71b0cec593f69f3114323f30c7a74cee253bad994ac3610c557963ef49e64fe725e98a006e71d59b1ee395319e7e8ed414067440a457e90d2ec467c432e24012e74ea74a3652819909da7036bfba4a138eed2fa312b5f1eb6de40d5ed2d74266c220542fe4d85556220fb74c8d9510327faf768a047c3083482ad95ab1f47f09aa7391be806f6dc2016bf039f60815cb8b9e1469552020ff775c7c4ff246780fb5904835fcd02c8e902fa66b85cb2375228e4d24b208836399807aab7159f3f1976f28bd9f3e10a90caebdf8e63312b00fef5999d3e185067c56fa4ae4d607ed425d55337d95388cdef8cbf9881b07d431b423c41c9628948ffedb17e36ebb929bc5ba7af780518461ac6749d97247a253e343efdbf390f29acd98ac87ab83436fdbdc3dfc2a385f1ecc3ddffb206962525cb42c8154b19196ef7918b2e664edffb3a90f8c1da300a3b03850fd3451affb0f70a022abf7ee6212855bcda138c79aafa54f2ddbb54580f0b209feeb17ef20ca0fc9af2be68a9b0b67e8df93da7aeaadbb602c7fe9ae1ef1083b03ba089feda1dd797e9d4e7ebce47b6e49e584e3d36f1330809d4eb5ecd255c9af74c618ab061b4a8748714bc3c82386c53ff675a7e91fa0bb1b118a22fd31f88a2b3e4121b39d029261a93e3de1f0abb800cede0d4ee338a31e469a853ac338ec7a3ede7b5337a261ab470717587cc1d82595d1d29feb5810b405613dd396be3594df9fcf52c7f463e10bf2daf9e6c1a391a25884a05ee6a2ccc9813caecfdc82711efae4b860df67b8ac62bc6da2d521313b8c62d40e570befe2742a5fabe714a18b792cb73af258b5d57e0d74be479ff99f12a5308a7e4fcc3014a82980d47bf34b889d40ac2155310f8587c8a6c7308573cae57d8145be9fe7c6ccbe902c56f2ccb5428a6ac05493385e5e80e549b08ca310ba64c60ae359e19a8c2528faf15daa0501c1e784c37d8c77f19247e7742592aeb8f58c1281e75cc659d15f73c3d594da7c1f3d4894281fc0a364c84e7bc48c967e13dae8d636b392da1af132ea10aa6f792ec138ba67a530f498d365d5fdc0a5de1875b5c09d0ebbd53b315de4c1d8e90645327162f3bf15aff817da2f7d2f3bde107edbfb92466814c6d68fbce140914c16aa2a98a9a368f2c4be38cb26baa64e736ed3661dda53cf843fd6634526b8a69f1ec4e3c67de5004d80ff5cdb2dd05f69e9eca5912f03e094a60fb58b307abd439a1fcbf69d574d3e81c0057effc725c8807ffff4a37f087d85be48a28c158fe8c7f6c483cbed13e7aef1e1f2b579d5bf49469147eb9d764c14b04a305c39d754de5b933b7553f2d3e2c02786f6db6a251e1505e0ef5f8345c5411e9038b61aea75a4179b68e4b1bcb3b914dfb671adb00864dfdfded512b3a146cd11f8f586576bcae37f8f36fdd45c698252fbad57da2baba8153d442926a5225b94c3a680e3c0f162d1f37491a15d6cc7dff1795aced01679142418911ea0eeac548d844ce52210900a181099ad554f8357cb2581f83e94b343c90d2623c8ad36b8dc245a0356c041009826b0a5ff9f75e58800d0386039814279dd2ad9fc79bfa6214512a6ca21768c0138c2f6341c52d2bd13a6598bb0ece7f11055f4f3f9eba5d8de596c275f995371211a6ba1a6d02981c1ae2de3f9726044c56ca74c711f30a956777555b4b98a70555271b20ca1ffbc58ecd43162a24e75ca29ccc272fb1c6bcc9247ea23242d056268b0335d53b707ea48b8fe8eb6a2ca77cba6189ea6747fdd4dd99d572502b2a3dc5fad6e913901a51b9e466a9a043edc69f8f773147954c757200b538753e6d2ee0c63496a8827c8b9e051e2bbf092171bd508e9eb88f68f2076dc1c7a34c1539ce9bb5a9b9604bdff7806393edf44fa21a42cf9735643d2a4fae46363da61f899899c1a8a9a8e0d6fcacf0c0f016dfc491f0350bf3bffd8a0ff8c226b2427bc161a661fe4721081c74d0b71699dd858d2da2c896f5fe51ec432ca5ee396d6e7aeceb6309d30fd79dbf2831e75c7e6f20e9b0287b25644436b62003f812218a6ef02f3c49a0896a1cb286922494f29c1f58de65fdf8e32bd5e972311065ad45479b640e494d9e0874db53b4e08f8e478dd919479f6aa3eca43863f31836c879c763087642bcb231c88ecde7fba0ac3a6fd803256cccd4d29f581734570cd48d3468dd31e9e51695e2e21b224da3fe63c34b8ae52efd8076a81bdf3fcea4bb5b1afcb280c5004d71fb181bec19f1776e94591856973bb31d3b79a8b0976213e876ef9383707da61302f5c835ddd4353e30645602b66fdd495fffa64eedcc181a0f8ee950dc83555089d6d6950253ba083d7156f7ae07deb57a25164a68e076a798f1b0b3650843b4cc818fda3c98b38670cddc53c85c6f452edb99f3811b774fb09f8e258f0b5b09a0f753873bbf0606f6f26f2acf9458fb76810dafa36e77fab8b75cde898e35bddfafaf9788a35f4034d31df099429b5d85a0f7dbbde40384c540ce99c7fdb4ae7b5d865d292bbfbb0ad2adc2ee48f0c551c14950edd97c2a3ddb047b813a3e3be52049956d37e9cbd8816e666ad3886f8700ae41f2fde041f706559e95d38ae5c9da47b1f570a809d0206d67562de3a1e8bfebb619d8394320f713b272988f41ac27b4f7f5483af72096544d42bbc81bd28eb55254b4eac3edf617f94c1a09a736ed086c8f1092df4a4e195a5e61660923963de43b1203d49bd1f27515950b17d858e97c2af537494267210548faa8713466064f61dff4b2408a87bf8ace61b870d7ed7bddf7284f4b0ab8d85e08ef42cb00725e969078a01e4483ea7bcc5f20992a015444367650975d64ff2093477efc3d7fa2de52c1eca53cf8986d7b81ef6807cb062172139fdc855d206c16d5795b6f75605e7bc0d59c63efba4252d008c732f1c1ebe58b37126a77192ec52fff6d3715c559f4e789fefa2772bcc917236e7cfdc1467f46ead4227e4f97f7c425e3129497c55e77375b682a4576f0fd2194ae4dcd4484d0f8f4ea974155163ce87627179eab5791e219320488bd2721585e3e96841802f66205f22094d9218c9bf347c8868af2e00e691741f65e8df5b75d2db2ceeb0813bf7a3ba5c5e974a7c40915081b5abb08832ae870dbbdb42f87feb970ba0269f65673be2bca56b585339db162606197f584823fb6e532499382b77c6b386f2de41b0a427f83194658a04d98cf2040bb9d66c7832e109a236aa8f2a22f9d2c5b2a2e0d35dfe764f346aa03816e2d3ba0b24cb63082eec815960c88c455f340d4082c0c413f80c266f7bba8183cb2e44f48c701c482e465a71632a0df36f1032807b074d481d2c3d5dd2695f29274e8d28cafb709550a38fc3f5b70b09623eac0c9afa78d988736f172fb35950f439397da60ab8297dc013d9b7f82272396d2e1c3ac25071d8174da48444fedb9406a2cad751d20d833e82b89bdc5e2a149c87b704c4d13b1360ce36661214d364ad83e6da6f514dd6fef42f4e077e6bb2d3525f058bcf390c6e353140dbb4143872973106a00e46a749aeaa153f5b8e3c81535282eb3ab589f683ffca562bd44069312754d7cab341e2619f3560753b9b113874863c5b010fcba02e96c13ca58a0e82c348fc0e2696b64db2c62a6a36d74c557c3ede7c483898ade2090483a8be28f19d654f3aa371ef60f8e4f0b9fd3febe37b3bce3dedb2aae0314b96e6c2b2a034c636d038b2de6c202386646140f6a06f2bb3ba77f5cc584cc81865143de4183fec60859d88e91bdfa9fff10401d854448813b9880c7d677bc68472488cc80ba534a5376b21f80cc46b6579722bfdb59258ca8f31383ffd10fbad0990549dc663c6cd18bae014b906835a34d0b22041e47bd0d955bed52c09219721532782f594504f125769e8f186567d60de6c99307144e41a36cfd46c8da4c3bcf5a9fd129db21d9d9ec80ef1cf67b1af813f3621751aed640eb2a0a2564759e05d444a9c92602fc7521e1efc8914f3b7826f848829fdc11c3e20f1e9d695b3447f823691c080df7fabb66cc06dc8976345e81a148a56b7d34f09b97f43e59bf5d1c8cda4082f54fc886fe92f674ee706a0ae1c8a0d4a0620686e3d287576f5d848ddda55376616dbc05e508c246d5643d2a97a0016dfd80611db1be4cd5b350be1846f974be25daf5555968bed5c93ea8a16217639197bbf9d50a7cc57bf5577e4e2604328df08ea48a7f2a44b47a6bbab43fde8e37fd5dec0427d373ec2408d782a8caa30f180343cddadd034000e159ce04499a2ae2efcf55a54d19420d87a5b03868fa48b19ff7a3ac81ffb7dfe3b9554b8ae4653a4bc51383df06079e95f6e553e5680a47b218801233219ff86120b472f133d89d3c1be40f53126892db21d8128d30d9a67ca4958d21265b8a3835f060f4f499146417425d322990807ce86476da924127fab38ab2ea7813ba54bd2737246714b4a0a17fc014a4084b73aafb935a6da065658cfe436eadfad99fa6b92246ea1ffc9c0e9743506aa05f5df68d43deb5265ce6d8c1f79a69657d1b52fd8ef0078fe77f2a26532ce84a5b5a22ad457ebbc953e17b2cb47feec209025f54049dbea1fd79bf39462c265f2f0c27d5b842dfcea1fd173c6883547c20883c74e6778abd2f1ef2df9c69aca084329c946b2ead40ee4f1708f439c5686fbac228dbef69d080b95e996a09b8180e756d67a1693c6b1cfa4ce7916ee4aafe7cea281d2c6bbfc756d476e2dd965fbcc924215daa33d5f284078dab0bf52353523f46f286081a098325793deeb5b86db938a8721399160a9f250ebec36e63237a041568130d8ae7f2f80bc433a6bb174852d171abb144d17e18aaeb74175be20d056570b632b0cf13c5da162acfde4b884ec7d7888823503e96cb5633048098431cc91f26f3d293d3b925b18fecac4f95b2f544966b95afe2f0451b6315ac4777944116bc3bb6342857c06719e1a0a698ba3c1d49ef4fe5d35e92fcba73a5940087ab4fe58c9b17db43362a061db31b4a14a1fb1020a717ef27ab424a1f65998dc5c221e39238dd993782e4a1654b34e4e66b485defcf4359d835c5f7d7c5477a57c556e2f6c7a18bf18a0dfde8f2acea81a47cfd1976328322ab0e71d6c0de2fa88430bc6d69e1eef8ed700ea578ca9d304c53475780940aa2192843a45dd60409c19d97a21897a1ff20003554936e3a76a173da88166060fbd3cf83aa562f0a7478e031072b8895a7cf5e1bef24989655033ba12362986e1e3f67483c7619028fe40edfdcc4c5444b6fd0ab26b8a87d51b88118f4ff73766ba7c3685c63b7bed819104f70cabbc29de5701c5cce446658773a0f3c8d530e9336f7c728ef9b600f2d1ba20cb545cfadf756c1d77d1d66641938e35ebdad460341ec1e466dcac0bcb6ddd6a462f77c328d982dafccb26a14f2698939f392d1d26558a4ca94353a32e1130a40fb73d43bea8cb9ab8b98cd393e24df88bc8659508c3f31b6a8d6930ad292478f581576260c2a9b4692f2e9d3381b9dc4ee04bfd5d80740e64260d5cc69b9e48a2995a1279256144e7356d553a8e1652110ed808d30fd4506de4f826b036cc265a22afb372fc63e4715d1b43179c5a56bdbe92c4e7b7a4315494721fddf4bdd06c9b491feb4e9999883ca4a42b8c7bd84a59c25e065fbe4c9e485a36459e9481a048970e3c38ac871e16d558978a3dcf1ce48641d20dba8137f684ba2b218cf1da4a983b593567b9699adc94e1ff6e4f0284b2b8512fb3d7f5e200f99ba3494bcb3568828d682de2b28cf7a72d8c71d3327ef00eecf006daaeeca5e25a87b4fefb5cb20a1dee822e498e2b8abd9012fddd063ce938d7779882f576509d2b4e73caa0c2ad571aaf8aecb794c35e39b634f937661db46ce2f82306cbe3641aafcaccc0dbb4612a98b47993008ce759c5f6b7db6151d67f33a37e031722999310b50143697e8babdbcab9e1621bfc5ee99bebe750758420b58da87f9e16bf37bacc9d038f0539c8530d60080322547c4bc043e3303a7f1a6f2d0f0f888641f47be539c5fd73954adee29b52713406a3ef8a384d7fcb5da4c54c44d8af5ed61b0f162160151b66104749b7b8ff3e37fb58a39defdde38948180a0bc12c79ca354b557556402df71b1f0785e2593caed9808bd392c7d452e4161427d6cee64ac772fa978f4c2e0bb73f51c37f39acbdd9453e766b2946300760c1194eb3440f509fd3fd389e3b4c4b78af2eee613e5aea840488548a70c736ca2fba306084ce708c1adba13e7ad303df3b4a8b371395bca34253d4ca3ef79a7f03c6feb203c99f13f8a760aa9f204f1aaad1ff3dbd2fd644fa94f1c63f9f39ec48a7099c5eb47a7994a60e01638a9ee78028c64182e1bb6bf71f669d76c185f66152f4bd4498ca85e40ae9f5367b66016beb65c2b0e8a89d47cb4587bda2590aa21cd69f3431eadaf4b660a2bf89b577821e17d194b2d37553c29ddcc2f5e39cf3c36506c2ad36875dd2d68825c57164fc25f9341e679d2d7ec0002e5c0a2cb4ecc861df2466e223681f3db199b7b1e11eb24c2edaac854d9b2929db74788f8be7d5d0697e0d8c9cd21cddc45db44e4c5c6379309f5685deeb060a2afd4f80d200c80e4ba1aabe06bf99f1ff2188fc6861a178d830f02a0aedb8c5b8d98319b80b4c91211be418eb7cda8ba7946b81cfd89d510192c56fe5af00f01eaec7554c7bcc7d7bd13cbef42ae195709f461af2006ad661baf251b4f2a5e69a4216814d853d348b3881c3609e3f16bb8653a4f5ae3d7f8af302ea35dabf794cb3c62b382b70fb4fff89f50f846d7d08c50c0690486abb3783a1505ac4b54258910d8c1562ddcb25c5692c938cceced62c0f03bea47f44c93eca3bd910eebb98b881e7412f01fc7ebaee7e6738b547ce8e9de2e9f024a91885f76a166ba0d30b56888a1ce202b12e4c09e084fe2b2412b0d86a2869cd8607328a0ed7fea478a551df672dd80fed385ce048782540ee0f387c8d32874d4fb2b38bed64c08a7761ba86c7ea0f2d496fedcad314553f29643c6d6f9722c3c4ec67937a482ebb68964a589b30180fbf3a60c7a89483673b3c5ff1568ac3ec468a233bf696e768789b8e3bb92dfa391baea1851898764e94d8e0591e7256c92e3b70012aaa4d76b6aa6792a8d266e3f0d8a07f90690bd0fbca3fe0b0c08aecdcaf1bf2157a0ba9c4cf9728991b2d0ae0e19abbf42951125486932630b5efeb6c9bbec6c3bd32811ac226d96c4676fd5d79dbb07e315bdad503b940a3afa963019f56cb8544964ca71c68d070897870bfd0b42e412c759dd764eeceb53d8786fe0a159c7f02ab4da1995d9396c0509a53e7d3e7dac99ffe577f57723020bdb673c0eef7db135aa84c8dfef8ed8cae4d62beba61121a5df71ceecd5d99f1ca80bece5e288c758eda15286a085cdb2f144c247bc600fa30909097693945651da0083f9ee9502f8292f9f738905ac0fd0d96463b6a43dea79f9a03680d26bc80effa139135e9d0b7ee981c91a25cda6095ab21f5ab97f07943646bed426251bd9fd62e2d1bd80371b979d2fb3ec9d63348f34b33ae16399c6094121d9cd241b217b6fe5241c01a53e2bf30fd9057b8dafc99cdf19960f62ebc89b1950be59ef98aa8981983c8d46bf538e2c01a8a54cce3b8fbd09fe137b63c100745f8ce5aaf97b8d162399750ac7ab7a813f2d489c5307000f108da926317f866e7c7b1c54322c3ef4aa2320a574b8978f6ab9de2f5624d04ea00e5bcbae5b69bd7f261e329c181e48f371ff718898c158c3eeec3770788a377f48bb0710969d01f47caf9c59f3cb4b1fdd38f945b832d837042f51afb22752e5fe4744a28a24b2f7c429c50c1fbdffd0aab23f8c30fb83df2d606c9b771cb27ed7abb18e36bd7eada3e04fff2c695462117541971431dca56a2afeddf92896a6d6e26c3ae5f1d7558dd7e16ebb60c6b0ef13897b6edae11daffbfc8216c40c13cee2a11c4035f3312bdd03ea975b3806f34150395153b32e1aacacdaac7f46a1f579b86d96cc0dd349de5d589e97ba808e264406606285586d680292b07f437cd758ad174e5b9df967b69c6f0a5db80c604d5399a7ae1820daf5b3173101430b88b22380ffde73bbb04cafa6a259698dfed1d4c896dab4f43a901e33515f892cc474cb7a4e337a3e446a986e2120800e53c726343106cc6fa65687c9831015d8be90065d518d02e52d20f7f5ad10763cb6edd3cb9534fc0cd8a5ad14e319b386261df741f39756f2a3ccd263271da46b1029b5e5ca753515024bb50a4727e0eb75b0c1d93719cfbf7c96b0c3fa3e07bbc4af3910e3b01b97434358d1c74c73058577b02a59316dd78e676a7d7019cc81aa4defab4195fd0f2289a191698f21a6b96f1b92a35339199e6ebcde89591c862173bb260892fbd8f0b179f91519a76aad1d5f50378c61e677adf69026f346ba83437e818960da9390f5c00fedb9b56fa9586900cf2657e13ebe3abc7e86b37e5314c6a759d1b021c89094c581a1edb7885036df6f45b29d314cda8b34c2dbed35f84cb885ec80dbd8058418642cf8a7274347934a3309b557fda7b49691c855f8fea36f2b7f38a03ce7cd4922341993debc889daa2456539ba973e98474d4ccb294b4d63d9c00fb5ec198fd5da439cccd89c6843830785a6ee1cb7397ad6e208b014841667e9ee9df47e94e217aa58cbc52b15906a1051a3a574330e28d83cd9986e20b68a49a40f8eb128f020c2df1a6448e66fb1c5216276cd42b371b400d4ae51f063d9fe42c3a93231ac8b50ad24744eb4b44ed11064bb35aa16da9caede48f56d3e8f648e67b84b2a19921999994c42a59973e844a33edd67c8bf494bdc8718137ea82e55164af30bd38f5c47a59601a91574ec612ac5a8fc56eaf96141784d8f8fe59133cc39b3c76771971dbd5cddcc6b63d20bcace1d56cf95734b32c7ceb77577395d87c9f884885c92db28b343cdec25675b7fbc93640d7b11d319730af1b4414e3c5697e83ef24f9563fb45553a0fdf5f6ef449585615f3af6394288827289b1b1901aca8b81502c5b5c4081ac914047158595a5694fd6fa4b0a832828d4d60fa8bcbf48be1f792e5f7588fa0ca41f204ede8c56c8f4191e2fbae744d0a7e4232d1c53a3644170f832efe82723b50e2a79bde332edaea3e425a4646004ba98f3cf9fc19fd23af7ff3e1c8cd23e0983acb22d9d11a6d882785a0b3bf238697ce14b231a2935af1f1e294d43bae6e8b1df1d038d99462fe53e61b79a3c1ec3ca8bb7b720c427047fc2d2e3426047975162252bad1d00425afa3d4c2d3460b0e36c335b8400493bfcf5be7f4ad773b1cdfd1f560e1d53a457f901c1a58a648dc972f34ed9fa18ae7375a0633a68407b2849eafac02df9c28f299923fd55d8974ff5070a5d1a31cb96104d89c909b510b9aede6c9a529a9f74acde2a5b7d8f73d5270bf6203beaa88e71840c3953b06b6b5fe6f43a13bc1520a2079db18e26c89018c394f8f3b1d4e6529744e889cfb5df5d9e81e4806aafe904d6b81accce5c1d2c6ba8f3b740bd080a496c94b4c50c61c4efd2d2e49b7e435529ab77b8cc974d49649135f3b94d6fd224b94a5315343bf162430fcfab5857adf2be6579ef5689a3470509e927cd716b90529c68776afdf3afeee316017e33a1e759abd7d4d4b05faa8066feca343e99db2d9db4236c094d77f9176b275e11306dfd7d306255ad4eef0b74aeec64ba1f5b96ea0e38dcca3a9f7776af5c3ab7903a301fba182cc969d3500980dea8c71dde6dbdde8cd06141ec8587b4b8cad2060927a910628bf9908da84b0e6b25a361d6ba8bc68d1bba60071175d6c257893e421914448f49cd299e5ac91cd86725115a500de7d7862bf7a5067e1b7c2dba9696029950a28b00b61e57fde02e6ca8bff3d0529e82f2cf203a047c0a163617c4a6556c35d71bfa86559647b6e38f158bb99af519f47a51a30843fdf06d287d05591aa392126af65074fb01f7778f8346d983287432002b98b6bf9a58f428ad02fe46289deaf8ae065ea8929e34f5ca42b0811847cd6750004604547636918b72bee8cd001a42908e3317addddbd46eb198d72ea3b5874553abc33bb2e1f733585b4a4dd1fa2cbe1d2eb70a9b7d137c90b5aed63db4f4e2e45fad81f865427134c3f482d358cef2c821e34d85aec90f45088eec523c174ae1e7e86311f0b7c6c9f27550a32d93e05ddd4f85aeee27a9b2cbce548321bc5afc25bf7a6ae3b5b6dc385e398f9baab593e9da0d3b7d7341bcc054d2b8dc67ac89c6f290357570f81226b2871456fe3ed29bd55b9db4e6e4077fe5bd58a6e3b846beccff6cb2fc57f66076aefdb9e72ad0daa7d3faea861a160de98d91b57c17fbe729bc3e213640edb54c7986e5bad11cd606f636c56fb2dd22d63cb931612844d0ddd68f4ac628d6aeb83d4a87c07729a3be8705cc0a5172ef93891fb7ab5be09f5df836003c5b9e1b599cf9514b51094e838230ae2701ed2f2230b0127932d260d2b010992a3e3121d7a3d50357febd311512d4debfeda8562219f10ece6d76b10f04b67d713122f790aa97d071baa6d1f6f2a4125a30cfd2963754a08c7d5ab4b747bc13ca503059e5c10d0c359e237fc582e750537d8ecb04318e6c4db35d727b29a37ce56e812de82778995df40d3ce628ca8fa8f78eebd71d48e47996a70fc8f2694c7b8a33f49a6dee3ec0974e6134ac2b514dcbc8c2603e90cc872d1fd6f86f61832e445856b0fe66cd822dc99a3dac666b7fd8f8ef0ec00347600ac01c4bcd6c786cc3ee075bc3e520dedf2a7c3b2d11bafdd77931aa6be5a736f40e16665925eafee386bb219f42cc3d130033d049c95c5830450028d36d97b56d577e3e4b115fecf29831dc47b547e3830799c787cdc3c49fe04c84da3a7f2d5a8143a0ae7bee6c15998288e14e11ee669a46e07014c827c3ad44f84c483b81d93b63f5ac2dab4500678789f71abfffd336f24a8ca8b5351cbf06b23a20545432725b8bbb178cfee7975c89f0ded3e9be159db624748632b72c98cab4dc3515db0e559ae2bdd5e11486e866ab388c40e7a34add6d4a9fcda95a1cbd944356fa81efb9bb7c7a88fe92cf7568d9d065956a8a75a190f9c1086956ed10ec63b6014b4855d789fa0b0fbd41794bc6c6904447bb45f10d1ccaed311aa8ec74f2338c494580f2a8197c72ec72be26dc98040ef046b6ba184a5f170f897c38061480bdb8f3b5f1d2d1da537215b0239591eeffca21786b93fc42590989dc478cfeb50c80471b1e1313448b59c81a06e46836c89a72463e09b956de8438211719a6490e7f1fcdd2bfe95e9d8fd76fc74965ec3605cc0133608f26c1d69d8e636c6f5bfd7824fcbca7124f07aa601d54e9250611e65aed2f69cb6ed9f6071daac0be1922b662aacfa7c22051b3953c97fdcc6fc400111aca97b19b28bb2614cc61d3d875d27b82d73c09fcf29ff936b46c8eecbaeaa6ccae08a23ec5330424087a2960e64c688e6a7f8b6ba6100e1605bba923c4dbd532bf6353cdae7e46d30299900c23581faab86ddd3e8ad57657fd8674deba30c6acb6b36332bca701774a86e11f227fc65f958de5ec2042bf5dcdcbfc5a184a163e9ec81e4d832fb42f0430b27a9bf7138f646e646be7a3ea1c8c188e470249166bd6620d1f02fbd0d27abbc357349b76ecb17dc128b59f11045706042af0ebf0c4322ab7c507bd65b80068315eb090d1281b7755cf571885046c6ac0bd9b3f3004f8eec8488227b7820b29a4283db93a3cc7c93750166d55e9eb979100d4702a53d7548dae7c0b06faaf1857186d19732531fad901b0eaef50064556d2c9d65d4b8917a895a2d86feee765b54e8734771b43ebaf59c561c8b4fbd2c763b01f7797a6fca91b362a2bd45249563dde1eec7b23d0093c63f08d86fa75f66f45a9a7623aec153960666749d1943691b6536a9ddee7f92dc2471a1abcd9532cce3e716b6439ac928abaf3f7b4883a68c817393844c25f33a41f27790b800e1106ed82b56b56cab1b308c2606e3fcd460510a13ee80f57a30095003c2417f6816f14dee17b2926ef1650a6faacdd3181937b8058ed76bf5e869bcc9c8b01e9a528d559f78cb574d5f4c4912e7a8c4d2157b23a82db0545728fe5f4f27e75886e710f83b607d9925c7461358fd1f5aafe598b1f0794a340bc4e232c55372b2913ede045e7c2250247ce05a6aa7b58e425f2ed9e66095cdb756a8b846e1c91c2f2f55b0ddce9cd637ccd8412753445d2eb21dbc6db4e6059ca022d7c21cf47f3b646bedd5f626f42ab1247372c0e248839cdcf44c3bdd3f824d33b0fee7d9f5a66ec001762692ef667c263f59aacb7f3dfdb44224ce0049008b2bffc9b26636a8c0d4ab48a95691b24a6e805d9285b5a25a3d5a623c2ee585672a4d86cea9baad531951294393757d8e3d6939baa3d075b38c511dfd8fa746f7b21da0f6a5d91126a983a5feafa19e3852c40c4c8ac37da8058bf8edd948f459bdfb6557de291e86d9e1a5dd080196c050b1909a1cfcb812aa6785313b40d3574c2d06001b802eaa4e191b1fb22ce5416b366947b8750758eea112139aab6335cf9e80c98622b012a6833b770fcd3f9a3d4ac32a6b7a33d2cbcb16e8bb8eb79f05a77f459bfb61895ee2f5f8d5f6570ae2b5fd14e576a45e1e0eae5035a5b635c2e55019f32f1dbb2c6a4fb06b3683620bc9a5cf96f6de27858f99a06f0059b274c8154ee11be53b514df8ce57084bfc7d1032d6d01a8046a96d6a46755b45be3984941c1c7ef945b33157c48f9ecf6615596561f3df29660f05e78c9f200ae4e4161d0297c9d5a19ffc791706c9a15fe8828afd456269913bca88201c2742adf928f4ba8c5bed78fce63675336c54016e4acadc2c40e8b60dd0ad9db3ea4d8d4346d68ef41290b7cf842e2c69c0c41f2d050589a04765910ac0c2fe13b711a9b5a3b372a2cb5d79ca54b98e6d2f8c085e53e29e0e4f0311f02719968a72c5cc98bb16a9686ea5d4bb991f91d7f01f5ca2a56fc0d5c40a5bbc1e6ff0fafe400d7e809671f865b19e07db280b155fef8fc04b79a0aa33ff79e422b9a7aafba3204e79020cedfc24b85252b4ef7d0fe1f8428bdfc29957851b44daa36120bbbfd4155a8b41ad9526c64d0ec6745d4fa691065f157a9e200a10148b9f4d47d8e35229a408113bf60f1b90f2ecf77474f63398fd631f3f1644728efc6c891d83f5cbad59019809b4f0ec7a54c119785b9ecf8c16346a643c96e12eabbcd67341705832e999668c26dbd28464ba7010bfbf1a51758c79c89f325c26075f3626f97ac6fa914d8871977ccd7846323cd687aefed6edbe2881d639b3bf9f14d195790b7f55304104f5a7dea1a5590ffe170acc395fd5cfa4f6e6f9b09312862f333614bdf81223378565d8c2e7421e23bc4e3c50a2cd7f8dc588463987598d4bffc5584c96ba16337abe2537361f0642044cf109c5ceaecb2e94f2b8a04952adbdacc809821e42ce1e0f63a6c305d42805254624733c429ab8648e85b73b76d5b8cf4715e65d55166426202aa7ac5b810bbd1db39bb5b25d32b4571b8ee338e05017dee145adfd0e8bb03f9dc00d803c76feb61c204140a450f145d299dcd49578cd5117e2f8c5e3b63019edc8a48221d9e1ef296d979ec1ff02d2a3fc3da4e797d8f7835d1e8454440d557e3f3c6ea17904e7ed801a7c836ef9ce2b77a5849956ed1c3c9764f3da9c416f33a298ec12d28ad56513ed856ba38302f04b452f9d1aad4a5c130ec792e45a34b4092b6749ee8ccc73098641b988e77d2ffa328c8ef8f0bfaf208c1cf3f685801d4eb5f061fd8df7bf01475d9b112cac342581c09ff9bba4d77950ea8130bef8e07428cc081791b7df20742058297ef6a4adbc158555ff011a9aac07e8dc2938bbe6e543e25c9806ae86d0023a4cb51d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8");
            Assert.True(Arrays.AreEqual(expected, attachedSig));

            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sig));
        }

        [Test]
        public void TestBasicSignature()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();
            FixedSecureRandom.Source[] source = {new FixedSecureRandom.Source (Hex.Decode("7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4711E95F8A383854BA16A5DD3E25FF71D3"
                + "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"))};

            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.sha2_128f));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            byte[] msg = Hex.Decode("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8");

            SphincsPlusSigner signer = new SphincsPlusSigner();

            FixedSecureRandom.Source[] source1 =
                {new FixedSecureRandom.Source(Hex.Decode("33b3c07507e4201748494d832b6ee2a6"))};
            FixedSecureRandom fr = new FixedSecureRandom(source1);
            signer.Init(true, new ParametersWithRandom(privParams, fr));

            byte[] sig = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sig, msg);

            byte[] expected = Hex.Decode("b77b5397031e67eb585dba86b10b710b9729f44d1c00335014a674bed98b2569712954fc906b9ea4a9b2bffc37157e4973b56bc31f42619e38d67e37057da076b694ffe6c973ddda2526d5cb9056ec5b0d15901d3cc712f659f19113281a7dfc88a202189a2a770e79233bd3c89fa28cdd45e68b90f23a6f50a31da75590e3b4cb38baba4415235517099b467d0fcd54954b0653a995b035ffe418c1e7ba589380899556d1c9b3125d1f95e5827cfccf27aab6c28c990ca63292f465ccb268b16bb4440edbeaf88b4441fefb233921c87a06efbd2555e18abcaf0698261dd38c9b8ce8e06fb685388d1efdeed30b4f89248f953b168d909a58cba1f6cd879d548b5ed0c99c2273c31307d85666a7aaa5220ec159024ba387b9a0d49a6fec92c345db70cf5e2f387dbfbd20a92846db29c718140eee861c57f7354a1b9f837b714e95801e1f9ec57b805078aa0007d13773ceeb5ae4a5d2033ce802e05743990c71953838e960022cbcc1a117db4d74c70f68600926f6678b7c413e4074870ab6594078f2235ccc77f5bb4261daae596d0cc949528ebb1d05a30e200bb10627038d7ecec177eca4d98d3744d78c0027deeff398a3ee55d25cb03d49340c2f8b9313e74733b8affc7a332472f71131f598701bf2d152a2c5ebe294235fd17c6deca8cf749f675ba246561c2e65594113a69920da467988b9cf9f5039d9dba8044ac5b32ebf6d40887743d5fd8fb40b14777c9542da410d0a1288a25399192932ff83d2eb754bb7de80f9a3f81e0656ec2029f933e5f317cf695af96d900d20ec6ce8cae703084b326ba133c170f502f5cef25b11f2336b37db164992c2aac51a6877f440eb92c30dfd359cad0c1b8d412d8669a1e89f361713c1c7fb0af32888cf536d25314c90bf84e18fb6794e7ece3579d5faa9b001484f867445abf841365638c0616436102800e4762ba2d770386f35d0465b9f951fec7ee0a9e71f2fde1b13fab4ede6a66598cc4f01db107afbb361f9030d25424326708804159089f5135ff7431f4b7ef1644c0162f136dabfd3f4d66cbfaa474da07dd75dedfeb8639e3dc8260973d27f940286053ee1cf8c014013c56d4792c0126062086812d22dafa38ec0076cae11f8280af11e1c3a5b51e6e82bbe1df2c6c06fc03b77e0d47a91c4959acafdeaa4466b5f19f6b13af4c8de4cda8dada9cd8bb1eb8aceb911841c6a4808553f906312fd63c1a54945e2fb2683c20ee47dd98f4638f9c60e0bbcb9f352dff272f6e292c18598d3279089ada457f93850d7d5024023fb8db95b7a3ab994a80dcbfa1120cfca74bcf16bc6b68693b093af58f4df469b96a1c16cdd2feefe0cfbd0b8de6695dde07b1dff288fd314a469f55db6b8e997757e391bfe4eaa88deda15b01688c4aad9af5aea2fed0e09a11b048d04188327bd49e0f33046fe5d8383f6c639d5c852936cdb20e7616cecbde2984d6119a9eec0c8532a39fde133739e1790434002cb57d6657456be6110d0289c06f1b5960269b6fea99a2ff67cb5f0dabc55dab8f72402759754c80c82825c639dd4c6c47e7529c7128c26cc908680583800cd6b7263e0baca09eafaad078339e4ed2fd5b91d13c01ba168254687adc787438e72d5249dd3816fe572bbcdccdce4b259b93b1a59ba4ded18eb4bce856de66e7867b7bc7bba3dee1af7d752b33bdc9cd61b41abea88fd415a81b3f4fde9435a5588d43376aa34a7a5c654248567bf045c4fe2c5ee4f713e070a4b4b7f7caa0ef31d0b3de5c81ba893c3efd197dd83ed5c92529383fc7d4d2f2cbdee3cfeddb939ec200e8ba37a2d74a3ce6948df5c2a09c3d668ae56835210532669fa824f6183d3daf1be6c6de9b8b0dcb83c6db66f00e421145d0d0887a167408ed86d5ba25cae25f0b95305ae718b7c203985c67c6529c6e9bff744abbf3da6b0188c808ec24b3e3301ea2b5c191b97d37c1c92ef94560549a2a7a7e8a7b00ca03a7eee4ff7b1e01e39eeb1897304b22f5e2e05b277e8b9a387ddbea2b759ea738b12d0a3ddd5a8026e7baa58701e2fe41a9ead6eddeacf0f7b543367dfd86e8be30e2053b5e336a850dbeb62ca85a254f9f564d551cae6bd2b8ef5b8255f650c015110ad3a01d2d3414032b6d6b3e3ad4b0ec542bd615ade98f06dddb732ba6f76cb4597c35069b2cb689e965609671ff629278806983c92b2d206f7cb139eb8e9c0c219ddf758d5b58e1a0ce27475fdc246d744e3b238ddbcf35fe965f97f7559d6c34f137e08d8b737f564fc04e00146483306408caa1e42c566a4106c13d5dbefea3d901b94ffd2cf14d30885d47144e6b63d58685904db1d18faadac0eb80f3d8403fe1b78807c4f6fe4b677a61812533a59e34de32655e78ce8c3cc2e8e01100ab04511738fbaa9e1bd26b3a4443d352ddebd5dbf3bd15bab146b20936b5b5ce4c3032a2d89a20daa9596451798cdb70bdd539bc9c3c396efba34a3c2cc276b4dd9763633393be3c4c76cd54a4b88d2f93f220d70f1f252223fba93a97f560935e0a5388b643796e65c2c360faed55ac20ebe59fdaf3c84652ace1abe52ef4dca01fd737a3d1cf345b14d6e12e7151dcdb85c83c902925d3e2a643b9d9a9ec4ad4f6a905491612394edbd8e3d0e159a5980b4237b450c71e1d068d6162b28eddee2c9b8a9d43f8ffaee9dd4b12df4998b8b9f4bff94f7aa2d1380fa27c8de29fad5b128cc0cde45222cdcd9d6468907ff2a49418cee5d535a85dcbf2171cfd99fbf7ff253f5d0c442b0bb99d638f3cb0aa455c2c948ee99197fd3231c20c917c9816057507acf5e25d5ffa8b518e50c8246f5fd57cf3bc918efa39ebc8a85139f887e396a2b69a39c3c3b60a6225ddfbbdafdce824be479f3fee0dd74ee751726e1490c37802e1208d4398a20ca3f9474e0b7e88fdaee462fa56a49f2b5912a6c6c31e0d49a70a75f6a7fd125600885745cce6bcb97955d7d71f62258318202afc4ef0cb3575b7d5fc85036fc8c05a1c41a9e95bfd86094a25a1c7150e1b7b3cf04efac3c4754c7d385061ad92eb88f722a4b422efb86bdc73e8d580b7d034c73dc0cd627d5698ce3ab3d5d26564325b6607dc3d3225045d75276fee30709e3a3556aaf104894c00e4622209e5ea290d119ef6abe807fbed1c75e0a28514138d346d891e364f8b66aae317885edd7a6267dbf0bd24355f3783c3a630391c4992a53d1fd7a9a3d6917f81c2eae5ad51dbb580e109c93b3f6ef521d921b9c6dc9a23a1f3707a81e777d5c4eefa00ed05e520333088c7236ca47e8a3c26874fdf28e46b0a6243c19efeb9ca8db26fcb5b23753974c0337efd22cd1d7cd4f565fff0c2c202ae92876c679514a3ad6e635219e24df04e683a6663ee01d8e5484f13a1bae303285cb5fef0e216a786e2cf2de22463000bd2ea0610692b0867fc99dac92e30e6419590e0ec1ba9e019a9adc764a634cc644f0eef532b562a6441fb38af94269bc3dbcf21ebc934217d7578edaccc69f096fb1317586e1879761593b0f5ecb6c9ccdcbaf3225284e228ed65e9bed58a1155d9314c0f59bd0a81fdb275fc435b5315e27721b3bb010bfb79426ec630bbc2e6c86c78bc929dafbcc99aa68428b692b3ba27361127ca3f767b022d69eae04dcb0749e83654f4e38b5fcfbee6cc85d44dbf7322bc3c948b4b2d8e243f47b987d4936c6c7b04b68c272e9572db02d21be567fb92775562bafe686c5d27c84344f777206252695a6269b67265a9d8e9efbc4f1c6e142062c5addbd1d7f0684e69d00cf76d397beede5e1289b35cd933f0c73544d3053f28c6bd69a35d66f252ff0dd5093c51b415affd9dc12f123405e388a8a8e7bf623b487d21c4d61bc19a01d3aaefc0b0f2a058ce3df837111d3ddd1c6b671761d38faf282f4ac19c51e31ea9b4845e7ff92d072f8fcbfcc71dcb3373ebb8998ed88804a82ce4df08a16efdc8daf107247a8c29abb1de728f2f169230e562e149514b170b556414bb5a57a97867eb2275b742f72bd7e99765a4fa4b4ec3d4f144e7eb064acd664dfaefa50a42c6eeb454644fb2c58c19e43c8cc3bc63f73f9dbb54aea2f1af54a82326a0b5d7dcc0a1f5fd4427579ee9a8fd11abec77a99641f6306750211cd270b68049e18630c9a8de7f1b81495720459b0544a0f7557635873ccd0739176296ba2ac88638b39506ef0abab8e609e5f2d3fae18fad79d63ffce20ec18de5b7a20e29555381e71c7d78c2a23e26e60bb89736ac0f487529dbba530166a283c3d6b809bb253c4bae2fe1573a95c54202b3a3cfd508de5946748f31b9bd93127d56cb59b30508d4c6af98a68c6a0960bc34bc100444973141cbc304d22022c78c936d23c29f978c05ef52671a2e0399ab2818a72699e1c227ecb9fa8082cae430172bbed14bc4d4325eac06c3dba1d9a9631f85b93405f8f1819df155935d20d910702decd638c56a1a0eaa09eba95fd7ccef463b8670a365baff0b1b49a9c344de385d7acfbf2d972f35a1efc5338c3690a287f504b86f53e1646d936375708554f835afe2e66849c128ba0fa6fa240d98faa293fb7375de3fa898334eb98bd4e6bc7a08e45a70b26710d92f544af27b6c9bed3ed748994fe26b7a1365f13e18740a4acefbbeff6bddb8fafa3261c27c2298f4e9a77d5d19cb5b9ebb371cb89cb37ee12fd39480f85072c3ce24487aa8f638233ab1b17aeb89fc3e0e6efc9a47db1e5c01ad9d66f030e2681f7d6b08f1ccb164ab091ee57d5626700d26ef813c807d399383d569bb274d01c02540ceb3a02b503ec68f62bc06f50e5f1505bbad87bb4edd84e193b957f8f7d1f75a71fda2e9426a395d444acb30e5d8bfac5484518c5db31fc05e82b05e8de4fbba4aa8d8fe090a5070d44d0eba0b18555eb2c30888a18921cc4236b6c0727e89bdefe15ba5b4fac9842625977151a677c84841f10e66af5d90c69bee4b7cbafb7591a048b1a406a384dde6dee737a3a65d1cbc78a8c58adf429cbb7928580a92b747d22e75fca419ad7f15a6efb5b61d19364e93171870189a2f60db90b12fa8452740eaf3dd6841e50ed3187e0cbd721139dc11aac761c9d2697c190fb78fbc6bbb45009afc75f42806d1007c3de9a4012e1d265921953502f6f1a3be76bc01e1653506fbeae79bfc666a2ce36da259834c5632fff3f72b7bec63554caaed996a4d4b0342ffc82ffd39de68bd942210dde2f6fce548b52e56781810749f284418ac13f44cb2c75c797547d26e138317761ad932adfa45c65775247b7ee83607bae60d8cc7d8e4bbfd63c58cbcb4f2a1fecbe2f01ae589a2a4a04b85b49004b47fc20d146db3cf3f785b70bf7c9fff8a23b250143cbe74c5eedb3d3339e5f5afffe4ea77539611ac9cd470026652554a0819f6db9a9b90b42996ef848f59ddefe5eb20e86afb56753e23468bea8387027bc0b4b88fe1becd59b7b9b86a47270fe44cc9275c35330b95aeab0b2ef0ce967c9fac24a54178a8560c8bfd389f8919733001767c1372264af30fb9aeed6cd2eb0355fb59edde9f31a29b72f45291cbab6e664d25b7ec07c0eab272c8f2de139b94b7888244f8df510404476dba4b746b9f4156b50176b814d21f5f921b77238ef9f24a3e8914a8c1bf6c3f62053a2ba97b3657cb3f1d773f97202a4be9e2e6b429ff5e313ba23f56db04efd47e0ec8d4e94d08d775df14967bbbcfe135d9812826e359384a5a2ae5b5ebb1975ac68e8c62e7c2de394fd5e7c3ee3cb81096be684485701172f0bc1e4af21e6a2beef267de52be8cd3bebe7eeb22a120f7e6028b481f6ed64624d106f6347c095099c86e95a8c4592cbe7da9bf7accb43ffa79f93a9e27859026f4e2e13677996834c29005680fb3c705edb5a9364586ee3886557c41cbbf2153edbe62e7ade7e769cab65f98502934b07e86e4972522e4891d937a9db2ce6143505bddd414b9e5c70e2e064cbb4f5db9428845aca240916e0f3974dc858c9157a1ef2382e2d297984aceb5512567ea5b7eb9048fa7053d5f2de4e7c6a505199a1f3eb1f2f679e966fb0c2f981b24f602850d372b18eef6414c0eed50954abcb91269495dbe7b4c3580c3e7fd0b0e4743f2fb52c4c8e13cf0cf1e2094685adfcb59367d3b686c03642d998f483f5ead7ffddfec18122b5348fd561ee8b665f93bba3837f106fdeefcff03d90ae167664583bd0970495d2c5c698aeb6ca934a4a8635fc27ecf605483f7463b2b64085cd0369ae3293df986c9f78c8e441cd800fbabc21d17a2252c70ef82d4f305278b159acdf0a62d1d1c32bca8fb3198ab01798a2aed8569db05d721eaed4776d024044270cc8957f01abea7d37617ff9c6eacaf7d5457ecc4f5c0d2baaa2b698b382aab9f5ee5c06164ffa4e4364d56f7baf44689fd3b99b0196db4eed4cc6e46ad8f3bcdbf40233eb75e019659a032f09540088e3edc95b02b780751bd314d6e5a9e3a10b3cedc4381ac1d601e3d2e715c402eb3487a474cfe3cad055c1a5593a978c928728270e5193b11fa3442f149086487a263e6612719d5dae60e49cbcb16bccc43e12d0df2bb5d08dd53e3d73d7bb3f774863c36e03409b8b585e20d8cd09bf38c6b0f5900d4d2aa93569b87a8fa9fe81addd9a094d5dd24c7479f8b4e13d68975731190670af02e5ee060fdcad842ac73519b8d9572cc4383c2e28a42d0d63394a4b88cf6d382b050f21efb1dbc9ee710d09feb464faa673ba2f319a5644e8aa37bd883ce1b1d62771df8c52b928f58ae0142a7db22436247e2ba9e1e257d952eb2884586a0b8c78af43a2ba928ee8e9a57de5e9a3c622c0993d5f8b35103d332ed84f3c856d8d289a4501fc0ea2023fcea1d0a5c945af886a5d8eed2c182d3f559a4788d1387d7417b37e5767a1070041570043ea99fd026f7cb6148cc261c1368e4cc1da9a180aea3e4b49ad2ccaf75007f42d381ab345d52c75e8c3e237f938c90ecaf4a57af3bc3b990c071bf4a9c4464cde801c4fdb9f667a8fe4196d13b1677db3e273a4519b5abb965aade5cfd42b28e8379ada1636105cf6a7b6e3ec276f2d4ad1c1abee7f084e7098b6535028e5b6e58f5b90f13a9e52d6101fe50b58e2d95e9287a8a4595521780ed2c29dd873537243ea0020eeddb775a9ec334260821f44ce10c22fb12dd95cbd228e0991069345cd4670c72a48e908b75e84da8a44c2899f9462cc932943058dcd0b23b0ef0c1e5f07059ea7deb4ed5dc3a39196c75a4acdfa04184d237f852a0f2129e1dc20d59653e78b4758338e85398d47850fabca5ca7271724ad65064160c61cd3c8df00c9ebefbfae455af427deaa339a2b8973ec47f8f640bb2edc2ef7bc7783ce05cb008d525251bf80fc262a80dc27abe0e80675b3b2afc69a31378324ccc8a8aaf3faf8007971cf8caffd066f487ad44f78acc4aa17c20112144f94a7418a692f3dde011badafd6d5b96e7bdadde3506d95e866b9f74a3f1a9238df900566b44f06d07dee7d4f2a813c2a441eaf27d2a2e3687d85ce447ef2bfa577a537f5353fca51511fcda1c18e3bcda9726258120a0bf30673f3b6d5bf1b2bde36d2a3d9598da0ad6cf2a0cf90205f6decb514604e8001cae824ab75c9cf637e66434e7afecf5f497bc3fa78e6478e7120185af82e675c651c68eb48c5b29b6cb983261b9e2a53def469210a9186fb469ad80c720079bae746042116e0dacd94774306dd764e83ce6b387bbfeab6d9392f2f3bda9a5f565b873861bea8f1771cef6dec27fed9a9a34a7a87765f1d937ca048c3250f5cbba5946420cdf4f2ec69dda96f10bad7b1dbcd68876724086d3fc1f030e71e077de6dc4c0ca92a535e344ec33076aae12a63175f80e1ef95af19ec88f8cffb527422d6ef3e67e3b3178fad746076e68dee1bfc10d95b33b73bdf1fb486104cfcc80aadec620cc438338bdbb93a2bd48eedc92e3562ba4b9bd67bdff768d78c83934ca3ce49c2439c1ee38144d42ff6d0e77fa54d0c684c0f5d2f05a976a7fbebf5241d04b37e4d4040fde9693a34daab9a3e22a375c6c2eb2f5296cb4b1d6f220991a5e68b777445889b9e762ccf6e3809ef5e8ec49f7c7e2f8f7cecaf833bce3004bf98693de2de64fb070aaf958d282348ff980a5879beb9f1bedc137e2478c0f68a75cb20d0689b26cc2f6640100d76fc25f5f0edd410ba3d9a4fa4cf92fabb3ddb00c4b66718ea99159087d1d9e2820e87213526d64fd22b3e2d6749e4a988fb76a1bc290706e882493d858de6f4efadd487d377e6f6f4267a2cb5a42a388065e76517346314c67769a57d850c0f7eebb7eb274fa3b5612c3bafdbbe1536626e7d06913e6251f12b0387d82640a40a86f140b870fec3385950a69d6fc91bc9fb77de6578aa4635a9857004eb50aad28925606d585d20ad74862ae386934f905c47c1c2d044af45ceb15be4fa1ce2df00bbe16768bfbb2236ec62ba2d6f546f5273a2797a20bbe55b266b8b79872e73df7113f9aefbf0cb6caeae02e3b587a5b7d6bc55279b566985676a6ab0bafa36038872371fb7678fce0db6792b76ac08e5f598196c30c8749b2ffbae466d90faf0dc24ba7e29eb783ca57a2bf5c8fe7c8ee4478b6acd3c2f96e15a62722dd4d96dbd598bacfae505f422c2e32e24684cbf6e5d0829001c89c2ec32d9e2fea38faf0a6fbb6afa43f066f7f48c50e8301ba4bc6e1c71ec0669d27b746118e5e40a0cdf8e2f71aa81a1c75c323ec8b7d047841a20c7b92fe759942c79fcd3ae7fbafc97fd0d9f3320ca7849f631a196644e75bf560a72ea1cc08ea6a5a70487320f9b89ed1dca36487196fc88dc4f3c98d2f501a0b8e2161abfbe89400b523f202d1bb0b022eac2481dcb3efb987aa536195371048125f807c90bae718a3f73fdce794bf671e3df3c779d5f95b830d27325744d60085451b090551cd846c8e028366adf212dbd85b7cecdf854dad81121e7ace0f1b0dfe89d22ec49324700d5db66ccf0b8ee398dfd70b86cc315833e2a7db3936b1e276efa033155" +
                "bfb2f8e64e4cfba8a5d5b956a03e2543796fe4b3476920fd3613c1e056eb299a02d3aba3ba2ef66948bccd530abf5bb37e8da9725de25896184635d7f1f4af44f073d124e2fe7988af57861b9ae0a90015395c429dc18f5ee90c0765d3995487178b71b427f152c37da2cfe14036d6137d97937746352cfb481a913b25c106d4fde9f614074af05626487f61d349d6fd0712a24fe9c56b5f5ab1b8386365237b3c864d4e017424940251eb2d54bfc58e0106a06999f3ef4b88a845f99b44ad5cc967456481048ce71f7bb08902de93b358cfcfa3f0ca9333c6c83aa77ba8b8762013f5cae34e7b2676990c01fdc5f619f1975ecbd40b6a6371ec3a4af3842794a093ac1c9b73355cbc5933ebba0aad104a6798eb6dad32425629fafc0db8bccd2b1f84db338f8828ff1783b633239c589eaa9fa1f045126a5c816cac8414c19d177d7a0b3da01815f9962ea0a0841cd1b428ac38050061a879fbda1345649f66703b7c7dc05c4c6941a72fe5a81379efabef69ef1f6473717c870dad980a4f5a2751eefc71a17dfd6728e7f0c293ba9f855d0bfa33e8c1fdca2b22898fcbae89bcf1038de58533c183bdaab094d537275b92ee0f38b46f01818ef4fb9156ae6485e11103e7cc4c21bbcbd2720fb61147c8fc739d323a25d1309b336cee39be4a354f93a4275b6fe153ab6f5f44b6caa7197039e23b6ba2c83660e7de0f73f939450c15f18ee31f8c095a0d9445a39912bdcfe95380cc39b483a6613c5f0bddb5ba6d56410eeff4d0d96d5d39202d1b789f33aa84e39b6d93b12f8aaf7836aa1ec792fa3178dd61dcd421e55b587451564d14ea3fec931b4198af45d66c98885c84376817ebe1ee08fc4c5cc7054409ac4e9745445c2a3fc8083f1c00c94b3ee2ce606c54373905e90fbc67ffaaa37c32b2df6d0758e2f0e661f40a21c939296d4ed4b1562742d00d4129cfef64862a1fc3c1eb910dcff20b08eda8ae77a4d8a8fd74ef5307de90d6fedecd89d11953ec718081f447446568e5e963e4f41f4b8311373205918e0d88fff9de755a59cf04b2d860146aac7d49ed9878d8756e4c86f1eeb83e15d4de9ba4a619a9c51e770b433c4519cb8ab6ad562da2f448ea4561e13eae4371e71b0cec593f69f3114323f30c7a74cee253bad994ac3610c557963ef49e64fe725e98a006e71d59b1ee395319e7e8ed414067440a457e90d2ec467c432e24012e74ea74a3652819909da7036bfba4a138eed2fa312b5f1eb6de40d5ed2d74266c220542fe4d85556220fb74c8d9510327faf768a047c3083482ad95ab1f47f09aa7391be806f6dc2016bf039f60815cb8b9e1469552020ff775c7c4ff246780fb5904835fcd02c8e902fa66b85cb2375228e4d24b208836399807aab7159f3f1976f28bd9f3e10a90caebdf8e63312b00fef5999d3e185067c56fa4ae4d607ed425d55337d95388cdef8cbf9881b07d431b423c41c9628948ffedb17e36ebb929bc5ba7af780518461ac6749d97247a253e343efdbf390f29acd98ac87ab83436fdbdc3dfc2a385f1ecc3ddffb206962525cb42c8154b19196ef7918b2e664edffb3a90f8c1da300a3b03850fd3451affb0f70a022abf7ee6212855bcda138c79aafa54f2ddbb54580f0b209feeb17ef20ca0fc9af2be68a9b0b67e8df93da7aeaadbb602c7fe9ae1ef1083b03ba089feda1dd797e9d4e7ebce47b6e49e584e3d36f1330809d4eb5ecd255c9af74c618ab061b4a8748714bc3c82386c53ff675a7e91fa0bb1b118a22fd31f88a2b3e4121b39d029261a93e3de1f0abb800cede0d4ee338a31e469a853ac338ec7a3ede7b5337a261ab470717587cc1d82595d1d29feb5810b405613dd396be3594df9fcf52c7f463e10bf2daf9e6c1a391a25884a05ee6a2ccc9813caecfdc82711efae4b860df67b8ac62bc6da2d521313b8c62d40e570befe2742a5fabe714a18b792cb73af258b5d57e0d74be479ff99f12a5308a7e4fcc3014a82980d47bf34b889d40ac2155310f8587c8a6c7308573cae57d8145be9fe7c6ccbe902c56f2ccb5428a6ac05493385e5e80e549b08ca310ba64c60ae359e19a8c2528faf15daa0501c1e784c37d8c77f19247e7742592aeb8f58c1281e75cc659d15f73c3d594da7c1f3d4894281fc0a364c84e7bc48c967e13dae8d636b392da1af132ea10aa6f792ec138ba67a530f498d365d5fdc0a5de1875b5c09d0ebbd53b315de4c1d8e90645327162f3bf15aff817da2f7d2f3bde107edbfb92466814c6d68fbce140914c16aa2a98a9a368f2c4be38cb26baa64e736ed3661dda53cf843fd6634526b8a69f1ec4e3c67de5004d80ff5cdb2dd05f69e9eca5912f03e094a60fb58b307abd439a1fcbf69d574d3e81c0057effc725c8807ffff4a37f087d85be48a28c158fe8c7f6c483cbed13e7aef1e1f2b579d5bf49469147eb9d764c14b04a305c39d754de5b933b7553f2d3e2c02786f6db6a251e1505e0ef5f8345c5411e9038b61aea75a4179b68e4b1bcb3b914dfb671adb00864dfdfded512b3a146cd11f8f586576bcae37f8f36fdd45c698252fbad57da2baba8153d442926a5225b94c3a680e3c0f162d1f37491a15d6cc7dff1795aced01679142418911ea0eeac548d844ce52210900a181099ad554f8357cb2581f83e94b343c90d2623c8ad36b8dc245a0356c041009826b0a5ff9f75e58800d0386039814279dd2ad9fc79bfa6214512a6ca21768c0138c2f6341c52d2bd13a6598bb0ece7f11055f4f3f9eba5d8de596c275f995371211a6ba1a6d02981c1ae2de3f9726044c56ca74c711f30a956777555b4b98a70555271b20ca1ffbc58ecd43162a24e75ca29ccc272fb1c6bcc9247ea23242d056268b0335d53b707ea48b8fe8eb6a2ca77cba6189ea6747fdd4dd99d572502b2a3dc5fad6e913901a51b9e466a9a043edc69f8f773147954c757200b538753e6d2ee0c63496a8827c8b9e051e2bbf092171bd508e9eb88f68f2076dc1c7a34c1539ce9bb5a9b9604bdff7806393edf44fa21a42cf9735643d2a4fae46363da61f899899c1a8a9a8e0d6fcacf0c0f016dfc491f0350bf3bffd8a0ff8c226b2427bc161a661fe4721081c74d0b71699dd858d2da2c896f5fe51ec432ca5ee396d6e7aeceb6309d30fd79dbf2831e75c7e6f20e9b0287b25644436b62003f812218a6ef02f3c49a0896a1cb286922494f29c1f58de65fdf8e32bd5e972311065ad45479b640e494d9e0874db53b4e08f8e478dd919479f6aa3eca43863f31836c879c763087642bcb231c88ecde7fba0ac3a6fd803256cccd4d29f581734570cd48d3468dd31e9e51695e2e21b224da3fe63c34b8ae52efd8076a81bdf3fcea4bb5b1afcb280c5004d71fb181bec19f1776e94591856973bb31d3b79a8b0976213e876ef9383707da61302f5c835ddd4353e30645602b66fdd495fffa64eedcc181a0f8ee950dc83555089d6d6950253ba083d7156f7ae07deb57a25164a68e076a798f1b0b3650843b4cc818fda3c98b38670cddc53c85c6f452edb99f3811b774fb09f8e258f0b5b09a0f753873bbf0606f6f26f2acf9458fb76810dafa36e77fab8b75cde898e35bddfafaf9788a35f4034d31df099429b5d85a0f7dbbde40384c540ce99c7fdb4ae7b5d865d292bbfbb0ad2adc2ee48f0c551c14950edd97c2a3ddb047b813a3e3be52049956d37e9cbd8816e666ad3886f8700ae41f2fde041f706559e95d38ae5c9da47b1f570a809d0206d67562de3a1e8bfebb619d8394320f713b272988f41ac27b4f7f5483af72096544d42bbc81bd28eb55254b4eac3edf617f94c1a09a736ed086c8f1092df4a4e195a5e61660923963de43b1203d49bd1f27515950b17d858e97c2af537494267210548faa8713466064f61dff4b2408a87bf8ace61b870d7ed7bddf7284f4b0ab8d85e08ef42cb00725e969078a01e4483ea7bcc5f20992a015444367650975d64ff2093477efc3d7fa2de52c1eca53cf8986d7b81ef6807cb062172139fdc855d206c16d5795b6f75605e7bc0d59c63efba4252d008c732f1c1ebe58b37126a77192ec52fff6d3715c559f4e789fefa2772bcc917236e7cfdc1467f46ead4227e4f97f7c425e3129497c55e77375b682a4576f0fd2194ae4dcd4484d0f8f4ea974155163ce87627179eab5791e219320488bd2721585e3e96841802f66205f22094d9218c9bf347c8868af2e00e691741f65e8df5b75d2db2ceeb0813bf7a3ba5c5e974a7c40915081b5abb08832ae870dbbdb42f87feb970ba0269f65673be2bca56b585339db162606197f584823fb6e532499382b77c6b386f2de41b0a427f83194658a04d98cf2040bb9d66c7832e109a236aa8f2a22f9d2c5b2a2e0d35dfe764f346aa03816e2d3ba0b24cb63082eec815960c88c455f340d4082c0c413f80c266f7bba8183cb2e44f48c701c482e465a71632a0df36f1032807b074d481d2c3d5dd2695f29274e8d28cafb709550a38fc3f5b70b09623eac0c9afa78d988736f172fb35950f439397da60ab8297dc013d9b7f82272396d2e1c3ac25071d8174da48444fedb9406a2cad751d20d833e82b89bdc5e2a149c87b704c4d13b1360ce36661214d364ad83e6da6f514dd6fef42f4e077e6bb2d3525f058bcf390c6e353140dbb4143872973106a00e46a749aeaa153f5b8e3c81535282eb3ab589f683ffca562bd44069312754d7cab341e2619f3560753b9b113874863c5b010fcba02e96c13ca58a0e82c348fc0e2696b64db2c62a6a36d74c557c3ede7c483898ade2090483a8be28f19d654f3aa371ef60f8e4f0b9fd3febe37b3bce3dedb2aae0314b96e6c2b2a034c636d038b2de6c202386646140f6a06f2bb3ba77f5cc584cc81865143de4183fec60859d88e91bdfa9fff10401d854448813b9880c7d677bc68472488cc80ba534a5376b21f80cc46b6579722bfdb59258ca8f31383ffd10fbad0990549dc663c6cd18bae014b906835a34d0b22041e47bd0d955bed52c09219721532782f594504f125769e8f186567d60de6c99307144e41a36cfd46c8da4c3bcf5a9fd129db21d9d9ec80ef1cf67b1af813f3621751aed640eb2a0a2564759e05d444a9c92602fc7521e1efc8914f3b7826f848829fdc11c3e20f1e9d695b3447f823691c080df7fabb66cc06dc8976345e81a148a56b7d34f09b97f43e59bf5d1c8cda4082f54fc886fe92f674ee706a0ae1c8a0d4a0620686e3d287576f5d848ddda55376616dbc05e508c246d5643d2a97a0016dfd80611db1be4cd5b350be1846f974be25daf5555968bed5c93ea8a16217639197bbf9d50a7cc57bf5577e4e2604328df08ea48a7f2a44b47a6bbab43fde8e37fd5dec0427d373ec2408d782a8caa30f180343cddadd034000e159ce04499a2ae2efcf55a54d19420d87a5b03868fa48b19ff7a3ac81ffb7dfe3b9554b8ae4653a4bc51383df06079e95f6e553e5680a47b218801233219ff86120b472f133d89d3c1be40f53126892db21d8128d30d9a67ca4958d21265b8a3835f060f4f499146417425d322990807ce86476da924127fab38ab2ea7813ba54bd2737246714b4a0a17fc014a4084b73aafb935a6da065658cfe436eadfad99fa6b92246ea1ffc9c0e9743506aa05f5df68d43deb5265ce6d8c1f79a69657d1b52fd8ef0078fe77f2a26532ce84a5b5a22ad457ebbc953e17b2cb47feec209025f54049dbea1fd79bf39462c265f2f0c27d5b842dfcea1fd173c6883547c20883c74e6778abd2f1ef2df9c69aca084329c946b2ead40ee4f1708f439c5686fbac228dbef69d080b95e996a09b8180e756d67a1693c6b1cfa4ce7916ee4aafe7cea281d2c6bbfc756d476e2dd965fbcc924215daa33d5f284078dab0bf52353523f46f286081a098325793deeb5b86db938a8721399160a9f250ebec36e63237a041568130d8ae7f2f80bc433a6bb174852d171abb144d17e18aaeb74175be20d056570b632b0cf13c5da162acfde4b884ec7d7888823503e96cb5633048098431cc91f26f3d293d3b925b18fecac4f95b2f544966b95afe2f0451b6315ac4777944116bc3bb6342857c06719e1a0a698ba3c1d49ef4fe5d35e92fcba73a5940087ab4fe58c9b17db43362a061db31b4a14a1fb1020a717ef27ab424a1f65998dc5c221e39238dd993782e4a1654b34e4e66b485defcf4359d835c5f7d7c5477a57c556e2f6c7a18bf18a0dfde8f2acea81a47cfd1976328322ab0e71d6c0de2fa88430bc6d69e1eef8ed700ea578ca9d304c53475780940aa2192843a45dd60409c19d97a21897a1ff20003554936e3a76a173da88166060fbd3cf83aa562f0a7478e031072b8895a7cf5e1bef24989655033ba12362986e1e3f67483c7619028fe40edfdcc4c5444b6fd0ab26b8a87d51b88118f4ff73766ba7c3685c63b7bed819104f70cabbc29de5701c5cce446658773a0f3c8d530e9336f7c728ef9b600f2d1ba20cb545cfadf756c1d77d1d66641938e35ebdad460341ec1e466dcac0bcb6ddd6a462f77c328d982dafccb26a14f2698939f392d1d26558a4ca94353a32e1130a40fb73d43bea8cb9ab8b98cd393e24df88bc8659508c3f31b6a8d6930ad292478f581576260c2a9b4692f2e9d3381b9dc4ee04bfd5d80740e64260d5cc69b9e48a2995a1279256144e7356d553a8e1652110ed808d30fd4506de4f826b036cc265a22afb372fc63e4715d1b43179c5a56bdbe92c4e7b7a4315494721fddf4bdd06c9b491feb4e9999883ca4a42b8c7bd84a59c25e065fbe4c9e485a36459e9481a048970e3c38ac871e16d558978a3dcf1ce48641d20dba8137f684ba2b218cf1da4a983b593567b9699adc94e1ff6e4f0284b2b8512fb3d7f5e200f99ba3494bcb3568828d682de2b28cf7a72d8c71d3327ef00eecf006daaeeca5e25a87b4fefb5cb20a1dee822e498e2b8abd9012fddd063ce938d7779882f576509d2b4e73caa0c2ad571aaf8aecb794c35e39b634f937661db46ce2f82306cbe3641aafcaccc0dbb4612a98b47993008ce759c5f6b7db6151d67f33a37e031722999310b50143697e8babdbcab9e1621bfc5ee99bebe750758420b58da87f9e16bf37bacc9d038f0539c8530d60080322547c4bc043e3303a7f1a6f2d0f0f888641f47be539c5fd73954adee29b52713406a3ef8a384d7fcb5da4c54c44d8af5ed61b0f162160151b66104749b7b8ff3e37fb58a39defdde38948180a0bc12c79ca354b557556402df71b1f0785e2593caed9808bd392c7d452e4161427d6cee64ac772fa978f4c2e0bb73f51c37f39acbdd9453e766b2946300760c1194eb3440f509fd3fd389e3b4c4b78af2eee613e5aea840488548a70c736ca2fba306084ce708c1adba13e7ad303df3b4a8b371395bca34253d4ca3ef79a7f03c6feb203c99f13f8a760aa9f204f1aaad1ff3dbd2fd644fa94f1c63f9f39ec48a7099c5eb47a7994a60e01638a9ee78028c64182e1bb6bf71f669d76c185f66152f4bd4498ca85e40ae9f5367b66016beb65c2b0e8a89d47cb4587bda2590aa21cd69f3431eadaf4b660a2bf89b577821e17d194b2d37553c29ddcc2f5e39cf3c36506c2ad36875dd2d68825c57164fc25f9341e679d2d7ec0002e5c0a2cb4ecc861df2466e223681f3db199b7b1e11eb24c2edaac854d9b2929db74788f8be7d5d0697e0d8c9cd21cddc45db44e4c5c6379309f5685deeb060a2afd4f80d200c80e4ba1aabe06bf99f1ff2188fc6861a178d830f02a0aedb8c5b8d98319b80b4c91211be418eb7cda8ba7946b81cfd89d510192c56fe5af00f01eaec7554c7bcc7d7bd13cbef42ae195709f461af2006ad661baf251b4f2a5e69a4216814d853d348b3881c3609e3f16bb8653a4f5ae3d7f8af302ea35dabf794cb3c62b382b70fb4fff89f50f846d7d08c50c0690486abb3783a1505ac4b54258910d8c1562ddcb25c5692c938cceced62c0f03bea47f44c93eca3bd910eebb98b881e7412f01fc7ebaee7e6738b547ce8e9de2e9f024a91885f76a166ba0d30b56888a1ce202b12e4c09e084fe2b2412b0d86a2869cd8607328a0ed7fea478a551df672dd80fed385ce048782540ee0f387c8d32874d4fb2b38bed64c08a7761ba86c7ea0f2d496fedcad314553f29643c6d6f9722c3c4ec67937a482ebb68964a589b30180fbf3a60c7a89483673b3c5ff1568ac3ec468a233bf696e768789b8e3bb92dfa391baea1851898764e94d8e0591e7256c92e3b70012aaa4d76b6aa6792a8d266e3f0d8a07f90690bd0fbca3fe0b0c08aecdcaf1bf2157a0ba9c4cf9728991b2d0ae0e19abbf42951125486932630b5efeb6c9bbec6c3bd32811ac226d96c4676fd5d79dbb07e315bdad503b940a3afa963019f56cb8544964ca71c68d070897870bfd0b42e412c759dd764eeceb53d8786fe0a159c7f02ab4da1995d9396c0509a53e7d3e7dac99ffe577f57723020bdb673c0eef7db135aa84c8dfef8ed8cae4d62beba61121a5df71ceecd5d99f1ca80bece5e288c758eda15286a085cdb2f144c247bc600fa30909097693945651da0083f9ee9502f8292f9f738905ac0fd0d96463b6a43dea79f9a03680d26bc80effa139135e9d0b7ee981c91a25cda6095ab21f5ab97f07943646bed426251bd9fd62e2d1bd80371b979d2fb3ec9d63348f34b33ae16399c6094121d9cd241b217b6fe5241c01a53e2bf30fd9057b8dafc99cdf19960f62ebc89b1950be59ef98aa8981983c8d46bf538e2c01a8a54cce3b8fbd09fe137b63c100745f8ce5aaf97b8d162399750ac7ab7a813f2d489c5307000f108da926317f866e7c7b1c54322c3ef4aa2320a574b8978f6ab9de2f5624d04ea00e5bcbae5b69bd7f261e329c181e48f371ff718898c158c3eeec3770788a377f48bb0710969d01f47caf9c59f3cb4b1fdd38f945b832d837042f51afb22752e5fe4744a28a24b2f7c429c50c1fbdffd0aab23f8c30fb83df2d606c9b771cb27ed7abb18e36bd7eada3e04fff2c695462117541971431dca56a2afeddf92896a6d6e26c3ae5f1d7558dd7e16ebb60c6b0ef13897b6edae11daffbfc8216c40c13cee2a11c4035f3312bdd03ea975b3806f34150395153b32e1aacacdaac7f46a1f579b86d96cc0dd349de5d589e97ba808e264406606285586d680292b07f437cd758ad174e5b9df967b69c6f0a5db80c604d5399a7ae1820daf5b3173101430b88b22380ffde73bbb04cafa6a259698dfed1d4c896dab4f43a901e33515f892cc474cb7a4e337a3e446a986e2120800e53c726343106cc6fa65687c9831015d8be90065d518d02e52d20f7f5ad10763cb6edd3cb9534fc0cd8a5ad14e319b386261df741f39756f2a3ccd263271da46b1029b5e5ca753515024bb50a4727e0eb75b0c1d93719cfbf7c96b0c3fa3e07bbc4af3910e3b01b97434358d1c74c73058577b02a59316dd78e676a7d7019cc81aa4defab4195fd0f2289a191698f21a6b96f1b92a35339199e6ebcde89591c862173bb260892fbd8f0b179f91519a76aad1d5f50378c61e677adf69026f346ba83437e818960da9390f5c00fedb9b56fa9586900cf2657e13ebe3abc7e86b37e5314c6a759d1b021c89094c581a1edb7885036df6f45b29d314cda8b34c2dbed35f84cb885ec80dbd8058418642cf8a7274347934a3309b557fda7b49691c855f8fea36f2b7f38a03ce7cd4922341993debc889daa2456539ba973e98474d4ccb294b4d63d9c00fb5ec198fd5da439cccd89c6843830785a6ee1cb7397ad6e208b014841667e9ee9df47e94e217aa58cbc52b15906a1051a3a574330e28d83cd9986e20b68a49a40f8eb128f020c2df1a6448e66fb1c5216276cd42b371b400d4ae51f063d9fe42c3a93231ac8b50ad24744eb4b44ed11064bb35aa16da9caede48f56d3e8f648e67b84b2a19921999994c42a59973e844a33edd67c8bf494bdc8718137ea82e55164af30bd38f5c47a59601a91574ec612ac5a8fc56eaf96141784d8f8fe59133cc39b3c76771971dbd5cddcc6b63d20bcace1d56cf95734b32c7ceb77577395d87c9f884885c92db28b343cdec25675b7fbc93640d7b11d319730af1b4414e3c5697e83ef24f9563fb45553a0fdf5f6ef449585615f3af6394288827289b1b1901aca8b81502c5b5c4081ac914047158595a5694fd6fa4b0a832828d4d60fa8bcbf48be1f792e5f7588fa0ca41f204ede8c56c8f4191e2fbae744d0a7e4232d1c53a3644170f832efe82723b50e2a79bde332edaea3e425a4646004ba98f3cf9fc19fd23af7ff3e1c8cd23e0983acb22d9d11a6d882785a0b3bf238697ce14b231a2935af1f1e294d43bae6e8b1df1d038d99462fe53e61b79a3c1ec3ca8bb7b720c427047fc2d2e3426047975162252bad1d00425afa3d4c2d3460b0e36c335b8400493bfcf5be7f4ad773b1cdfd1f560e1d53a457f901c1a58a648dc972f34ed9fa18ae7375a0633a68407b2849eafac02df9c28f299923fd55d8974ff5070a5d1a31cb96104d89c909b510b9aede6c9a529a9f74acde2a5b7d8f73d5270bf6203beaa88e71840c3953b06b6b5fe6f43a13bc1520a2079db18e26c89018c394f8f3b1d4e6529744e889cfb5df5d9e81e4806aafe904d6b81accce5c1d2c6ba8f3b740bd080a496c94b4c50c61c4efd2d2e49b7e435529ab77b8cc974d49649135f3b94d6fd224b94a5315343bf162430fcfab5857adf2be6579ef5689a3470509e927cd716b90529c68776afdf3afeee316017e33a1e759abd7d4d4b05faa8066feca343e99db2d9db4236c094d77f9176b275e11306dfd7d306255ad4eef0b74aeec64ba1f5b96ea0e38dcca3a9f7776af5c3ab7903a301fba182cc969d3500980dea8c71dde6dbdde8cd06141ec8587b4b8cad2060927a910628bf9908da84b0e6b25a361d6ba8bc68d1bba60071175d6c257893e421914448f49cd299e5ac91cd86725115a500de7d7862bf7a5067e1b7c2dba9696029950a28b00b61e57fde02e6ca8bff3d0529e82f2cf203a047c0a163617c4a6556c35d71bfa86559647b6e38f158bb99af519f47a51a30843fdf06d287d05591aa392126af65074fb01f7778f8346d983287432002b98b6bf9a58f428ad02fe46289deaf8ae065ea8929e34f5ca42b0811847cd6750004604547636918b72bee8cd001a42908e3317addddbd46eb198d72ea3b5874553abc33bb2e1f733585b4a4dd1fa2cbe1d2eb70a9b7d137c90b5aed63db4f4e2e45fad81f865427134c3f482d358cef2c821e34d85aec90f45088eec523c174ae1e7e86311f0b7c6c9f27550a32d93e05ddd4f85aeee27a9b2cbce548321bc5afc25bf7a6ae3b5b6dc385e398f9baab593e9da0d3b7d7341bcc054d2b8dc67ac89c6f290357570f81226b2871456fe3ed29bd55b9db4e6e4077fe5bd58a6e3b846beccff6cb2fc57f66076aefdb9e72ad0daa7d3faea861a160de98d91b57c17fbe729bc3e213640edb54c7986e5bad11cd606f636c56fb2dd22d63cb931612844d0ddd68f4ac628d6aeb83d4a87c07729a3be8705cc0a5172ef93891fb7ab5be09f5df836003c5b9e1b599cf9514b51094e838230ae2701ed2f2230b0127932d260d2b010992a3e3121d7a3d50357febd311512d4debfeda8562219f10ece6d76b10f04b67d713122f790aa97d071baa6d1f6f2a4125a30cfd2963754a08c7d5ab4b747bc13ca503059e5c10d0c359e237fc582e750537d8ecb04318e6c4db35d727b29a37ce56e812de82778995df40d3ce628ca8fa8f78eebd71d48e47996a70fc8f2694c7b8a33f49a6dee3ec0974e6134ac2b514dcbc8c2603e90cc872d1fd6f86f61832e445856b0fe66cd822dc99a3dac666b7fd8f8ef0ec00347600ac01c4bcd6c786cc3ee075bc3e520dedf2a7c3b2d11bafdd77931aa6be5a736f40e16665925eafee386bb219f42cc3d130033d049c95c5830450028d36d97b56d577e3e4b115fecf29831dc47b547e3830799c787cdc3c49fe04c84da3a7f2d5a8143a0ae7bee6c15998288e14e11ee669a46e07014c827c3ad44f84c483b81d93b63f5ac2dab4500678789f71abfffd336f24a8ca8b5351cbf06b23a20545432725b8bbb178cfee7975c89f0ded3e9be159db624748632b72c98cab4dc3515db0e559ae2bdd5e11486e866ab388c40e7a34add6d4a9fcda95a1cbd944356fa81efb9bb7c7a88fe92cf7568d9d065956a8a75a190f9c1086956ed10ec63b6014b4855d789fa0b0fbd41794bc6c6904447bb45f10d1ccaed311aa8ec74f2338c494580f2a8197c72ec72be26dc98040ef046b6ba184a5f170f897c38061480bdb8f3b5f1d2d1da537215b0239591eeffca21786b93fc42590989dc478cfeb50c80471b1e1313448b59c81a06e46836c89a72463e09b956de8438211719a6490e7f1fcdd2bfe95e9d8fd76fc74965ec3605cc0133608f26c1d69d8e636c6f5bfd7824fcbca7124f07aa601d54e9250611e65aed2f69cb6ed9f6071daac0be1922b662aacfa7c22051b3953c97fdcc6fc400111aca97b19b28bb2614cc61d3d875d27b82d73c09fcf29ff936b46c8eecbaeaa6ccae08a23ec5330424087a2960e64c688e6a7f8b6ba6100e1605bba923c4dbd532bf6353cdae7e46d30299900c23581faab86ddd3e8ad57657fd8674deba30c6acb6b36332bca701774a86e11f227fc65f958de5ec2042bf5dcdcbfc5a184a163e9ec81e4d832fb42f0430b27a9bf7138f646e646be7a3ea1c8c188e470249166bd6620d1f02fbd0d27abbc357349b76ecb17dc128b59f11045706042af0ebf0c4322ab7c507bd65b80068315eb090d1281b7755cf571885046c6ac0bd9b3f3004f8eec8488227b7820b29a4283db93a3cc7c93750166d55e9eb979100d4702a53d7548dae7c0b06faaf1857186d19732531fad901b0eaef50064556d2c9d65d4b8917a895a2d86feee765b54e8734771b43ebaf59c561c8b4fbd2c763b01f7797a6fca91b362a2bd45249563dde1eec7b23d0093c63f08d86fa75f66f45a9a7623aec153960666749d1943691b6536a9ddee7f92dc2471a1abcd9532cce3e716b6439ac928abaf3f7b4883a68c817393844c25f33a41f27790b800e1106ed82b56b56cab1b308c2606e3fcd460510a13ee80f57a30095003c2417f6816f14dee17b2926ef1650a6faacdd3181937b8058ed76bf5e869bcc9c8b01e9a528d559f78cb574d5f4c4912e7a8c4d2157b23a82db0545728fe5f4f27e75886e710f83b607d9925c7461358fd1f5aafe598b1f0794a340bc4e232c55372b2913ede045e7c2250247ce05a6aa7b58e425f2ed9e66095cdb756a8b846e1c91c2f2f55b0ddce9cd637ccd8412753445d2eb21dbc6db4e6059ca022d7c21cf47f3b646bedd5f626f42ab1247372c0e248839cdcf44c3bdd3f824d33b0fee7d9f5a66ec001762692ef667c263f59aacb7f3dfdb44224ce0049008b2bffc9b26636a8c0d4ab48a95691b24a6e805d9285b5a25a3d5a623c2ee585672a4d86cea9baad531951294393757d8e3d6939baa3d075b38c511dfd8fa746f7b21da0f6a5d91126a983a5feafa19e3852c40c4c8ac37da8058bf8edd948f459bdfb6557de291e86d9e1a5dd080196c050b1909a1cfcb812aa6785313b40d3574c2d06001b802eaa4e191b1fb22ce5416b366947b8750758eea112139aab6335cf9e80c98622b012a6833b770fcd3f9a3d4ac32a6b7a33d2cbcb16e8bb8eb79f05a77f459bfb61895ee2f5f8d5f6570ae2b5fd14e576a45e1e0eae5035a5b635c2e55019f32f1dbb2c6a4fb06b3683620bc9a5cf96f6de27858f99a06f0059b274c8154ee11be53b514df8ce57084bfc7d1032d6d01a8046a96d6a46755b45be3984941c1c7ef945b33157c48f9ecf6615596561f3df29660f05e78c9f200ae4e4161d0297c9d5a19ffc791706c9a15fe8828afd456269913bca88201c2742adf928f4ba8c5bed78fce63675336c54016e4acadc2c40e8b60dd0ad9db3ea4d8d4346d68ef41290b7cf842e2c69c0c41f2d050589a04765910ac0c2fe13b711a9b5a3b372a2cb5d79ca54b98e6d2f8c085e53e29e0e4f0311f02719968a72c5cc98bb16a9686ea5d4bb991f91d7f01f5ca2a56fc0d5c40a5bbc1e6ff0fafe400d7e809671f865b19e07db280b155fef8fc04b79a0aa33ff79e422b9a7aafba3204e79020cedfc24b85252b4ef7d0fe1f8428bdfc29957851b44daa36120bbbfd4155a8b41ad9526c64d0ec6745d4fa691065f157a9e200a10148b9f4d47d8e35229a408113bf60f1b90f2ecf77474f63398fd631f3f1644728efc6c891d83f5cbad59019809b4f0ec7a54c119785b9ecf8c16346a643c96e12eabbcd67341705832e999668c26dbd28464ba7010bfbf1a51758c79c89f325c26075f3626f97ac6fa914d8871977ccd7846323cd687aefed6edbe2881d639b3bf9f14d195790b7f55304104f5a7dea1a5590ffe170acc395fd5cfa4f6e6f9b09312862f333614bdf81223378565d8c2e7421e23bc4e3c50a2cd7f8dc588463987598d4bffc5584c96ba16337abe2537361f0642044cf109c5ceaecb2e94f2b8a04952adbdacc809821e42ce1e0f63a6c305d42805254624733c429ab8648e85b73b76d5b8cf4715e65d55166426202aa7ac5b810bbd1db39bb5b25d32b4571b8ee338e05017dee145adfd0e8bb03f9dc00d803c76feb61c204140a450f145d299dcd49578cd5117e2f8c5e3b63019edc8a48221d9e1ef296d979ec1ff02d2a3fc3da4e797d8f7835d1e8454440d557e3f3c6ea17904e7ed801a7c836ef9ce2b77a5849956ed1c3c9764f3da9c416f33a298ec12d28ad56513ed856ba38302f04b452f9d1aad4a5c130ec792e45a34b4092b6749ee8ccc73098641b988e77d2ffa328c8ef8f0bfaf208c1cf3f685801d4eb5f061fd8df7bf01475d9b112cac342581c09ff9bba4d77950ea8130bef8e07428cc081791b7df20742058297ef6a4adbc158555ff011a9aac07e8dc2938bbe6e543e25c9806ae86d0023a4cb51d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8");
            Assert.True(Arrays.AreEqual(expected, attachedSig));

            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sig));
        }

        [Test]
        public void TestDeterministicSignature()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();

            FixedSecureRandom.Source[] source = {new FixedSecureRandom.Source(Hex.Decode("7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4711E95F8A383854BA16A5DD3E25FF71D3"
                + "061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1"))};

            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.sha2_128f));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            byte[] msg = Hex.Decode("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8");

            SphincsPlusSigner signer = new SphincsPlusSigner();

            signer.Init(true, privParams);

            byte[] sig = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sig, msg);

            byte[] expected = Hex.Decode("e8a1883716841afecbd6f9bd8648bbf86ab3badcb227b624633d51913eb337e07b68834818c993532f90581ff8e26477449fc5f0fb37c9d8462bee7d3f5825316afbd4c9a2a266d71d7f8ba4db064c665e02e7aa0d1ba9bac5d0ac0934db69fa09fc85234a701887cfc0af912c7b5d3186c0489e593fff2e9b5c79a0a77ac312aac4049d29ad57db8e86cec1c1264e819c5083bd03b4ac44b94be97756e2e4b491947a2103b371c1b54940bba71cbb7f9bbcc8eb90dac25795d1148fdbdc3cacef7945bf9744c966cb73cde15b98721440d2fce6294e77c39bb2cc37738bb2c2ec45a8d64a7fdda31c2a5f38e9cf17afe942470f1227e05b907ada0564ff9cc0e1154b1459f4a4b21485d901582c2cabd443635262c6a899e774e27d7428d980c77e2d42c15bf9f45b702462dce170042b696598fa8a850beed7517f717cb48fc98c8634296e3b8572284717fa5248eaca46c8b20670c31347b919d6569d351e4ba30595a5adbf887c8e971aed2dcceb4593ad18db1e5f9226ae82366e5c99c44e22ea292912d00aa6c53670bf6ed0e969c56a95015b8c5e0641885b4ceaf45bd2d90d5b93f5b0f63a8798a572935e2300319aa40e6435441b611149750638e3894e66e7c3ffc6a4f1cb37456a7c82b05e2b6d16f8365f05391f25539b835159ba9b775e85abda82d16d6b7b626f76bd2e98cb31b82ba8f18f0309c41677c2b4f5e822f255dffe17d21e7ecd421cecdb7e6a3f88e4d76fa0eeb3d7e9677c0c983223d029a025a147399ce72a13572edb7d2689b361993a06492df19fc5391a1e6e89d4d81cb5c3eaf1396941f9a51b8897cdf725ae8669f2b4b9435277ba13899a8f1805b77fddf5bd6b2d6dddf02a185d10f3196c571ab246bb8e3e1fc97b0b0b4e1c3e2186f6839b615c210613c4c3c7fd922d1907fedf6631bf3d1ca99914ad5c9fd34ca51ae4093e2a925c6a967b2c2e8c97fdf73d8dc3c6fb36ae587e50e0b31455f618811162c30ecbe1e2528d325a8c75afb13cceff548863c535bb6f72779fc150b74d33b4f98f7dca144fa554318cf48863fdaf16c73ab14e5c00580ff227803b1c8c383713bffb6144ae7b02f0cc1113fe2f57b72b93edc1e0c363ad4745e5a96bc61b2ebfe5fe1fe6008e734fa9382c0b818834e22611433ca213cf090c5af84a318cdfd038d8cf6936479d5b35dacc30be7b92e13920c0f80e5a6365ffa3b0c35ee637a4e861817b10b6c6b8f6532124c45289ddd027365e86e76b57ac42b6c15abff1b0426d1456299f9585b16aa0301d333837e751db28c0e3ef942d577655b70219353954384b649dbb4cfd8754d80250fe9ed859ab8d51e6c663ab32bc6c5972620214f3e08b3275829e1e97a19e2795ee39a43e56c1adab144951ef5b1cc1512eb250625d7bc18165a20e588f03075a524c0cac05c5da810632680e05516815c5b32262eb5b3b54851477edd61ce14d3238c3d02f4518d809887a49d148e84cdf7e50e0c06d82b41e152a5151a576c69fbc812c327d440b41edb75c02ab444ebc7da11143e440cfbda9c6c7916264b95692029e4c1bcbe56c55bcb2af6530131147de4a1b384b46179bce044dc104a3131ade59e4a1556e665d6ae0ba1bfcb433215d6b9d5be7b023045b0b49490685808b1a545577abc9abfd069aacd33863c2f5d0daf41b4c5af5224803f248356ca7c1269315c1bc4cf8256cda2e1dd2b1f227b7032ac29acf80732120ea3f9aa07945b602810e8aeafccea49d32e5050f248f72f3fc839962ae0e1443b46b586fbb48a2aae82cca180d580312f918ed208a2b6a493cd63b881a75e321a5622bf47314877bcdc9474019b5c64152e003d857b9eac87b3ea6c8f378592078326a4cb16d66caae17694b306ec4965f85a064175763ac9d4b457be3609188ccbeea07087f5051c66b5ca51fd88fb91a1dcc3f93ebb7840645283595fd3c4148bd62e8dcf0c5da4b89492222106228717ec8b473f7505defcf6da41c8e31965c76a067604da9f031f0b34235d7ef587748ba03cac0f104ebd1d29a44e0ac96c85359550a115aed8a8f15536032b6fbf4ac8239eb94391b2f66d7f001114457a938e5877f0eae1ad36ff6a853d96ebd8d5e44391e83a940fe538dfe2caaebcf7b6110cf4e51617f3619480c3396d7c9d2af597e113acdd794cf81de24a21285f4ca9bf56df99e02587bf89674e7db2a1a06cbc217940fda6248befcb93a3f947234e59ab6b03333932c015dba3c88092f362d0baac5c5b9f2d9d5a829dd3ad4644e0cde89d4d8df4d547187d66179f7b350112c4c004e6afc97fc97793530be06c13737386ba92b13cce0c0b6cb6b0aa0d82000d674d1998f05b271643ba85f7da6304dbb6f530d2c80c40c3e2f925b87d32603e377b3a9ac486e0f0186c191f4648fbb8e230f192185498e3e09e82d321a9a6058c553419e21c3ddbf147c2ed88f99398a7eba4db3a7ea39b45693285c4d6d6c8a1eb8e7bc0ed937838afd59d003d69623f6cc6740f2a7b1808073fc7638960d649256026d9b714d903719ac7959405eed2a22e4a9d72e33ab6f0aa5d07be4783b4ddf36af1b4d4c78585cfce80738b9c1225660f5e16d9de5c9ac285d24db80c9680525d419b626435fafebbb683c9b36bdc1cfc185cfe87b6ae93a14e3d63db6688f300154f288484c07c97d82f438fb9281afe6254170ea6d8037108d8984e88872f1c9072eaa46ed6ba426282ddf6365f010323e176e11309a3d80be22f8aba5cf93dbff8658665a9d2e3b428e05218d9da73aa0324f9500732920cb278bce651e21816c61376d1cf6d2899f02423b33be6a8217c217dc42b1f97abf8f63ebfc367b4fbf0f158a32cb2aac06616446a9773f6501692cbbab803074b5c026cb3b8ab7f48d6e5818e668198cc958b8acfd6469e8b835aca0e5bfa5a8f301ffdea73c8693f6c656cfa411e7efab0842da13aa7132db26176c792fd1a99c79551ab99482be3674bd2e37fcd8e0701f2a9cc801b56e717c8186cae04287fc741296e97c5563c4b64e7d36b76cfb41ff3ef32c5c88a4dc09ff91a215d157fcae725f7da8801e72086e3f063529eac6a11d4845c1eb0bd5845801cf9cc35deb27d7bdbb67055f641b9f4bfaacc0af6124853cee6cc3a858c1b102fde6da1d245390d6a6db8492b1142fc09b90d8c985ddd2a82e9e79355a070eccdcf125ba45a2543d473cab41cd9ec464b77fd57c54dd5b346f954b1c2acd37841f29f9b7dfa767fd029bddfbd0cd3aa285540a3943c6d1018f4cf87fd7c17fbbc65016d5668d2b90e01f3176218160ef5241caaf3bbd747c81da560d1debe3dc258197740839f93ca6eb41e7e635340e9de07aac1b24c5f48182d0bdee3672097d2ae48960224038c8fd710845d0927f647dbe09062c586842d31e1018950a3e16ea5d209402367badae58d2344d169cdc05f5a47f86903d18902ef3bed7d3deea961bc2e8e7019d77005ff88be637ed0977354b26ca98a7c0dd436af45341626540e050d7f4f03b703f254e32bd9a3d2f93997052732773c2274cd1a26da956105c5fa59dbfb002efbc28d3cca08f91f0fa76289a1f68decc6f943cad337f710e26e8287ced6a35b3c4a5b2598162fe2412cc2d44b49948f383403c23ec22c585e95f91063202da0755205bb592fbd345e10bf1b545187a7c14aa88106bfc37bc05dafa17f0e2bb8edc2179b3093bb1cd955beb621d2e222b39af3cc1ed26c7067012b4fdea539c983e1481b70dea56506a3ad912257cd7cd58da4cacfd4370a0dd292c319f23ee3ead9695bfe91c7e83bd846bc186b1703061a9d4a69eb961ba06415d4dfaf2cfe839337a6efa0e6b4f4a23c700f678e517a64e8a0c1eb28c6044440f203d9eac89c8b7d406a076bcabdce36195119001022e640155df8ef46241ea50204df095b96deeb70c2306cea56794e9729b3fe27e114a95344ad4d033175decb92e0ac3a88a16e5ba32f8c94853764fc7aeb16591cd3cdeb84b24ef6827a341355e7efe0ef360991a20e6ae77a04d66bee1da160f14ceeadabb7844e3baec99a057202d80f41c01c6f59d6affe7497b137f93e377e3b9f6df995df70480098c46a85e5b9d9b3fb7d4b7c6f4c72e1ea8fc442f92d4d74b41ce026aa5ecfac54ca2b4f45995799330082e0b558f18c5e31e698c67f2e82dca0ed3540f8493f8176b9163633481d4a444ce792b1b5b7c1f390853aad64979678de457086d7b7a0c0230ee0d0c269322812d5e7dc8e6e1e03dc0c977e81a6ac37b328af654ab070c6b073e3d0194046e9e91898e8459b90faba6e0c5a14a764d919db650c798aaf27ef1ef87a62b3b5d0b69a5abd7ea8e12e19a74754deadbcd82867ee271340c0687e7091091585e1163da7ac9655c91a62da7850478d2283fb6946306834f2e56025d863044b564818de7b43a7d895bc3b260f4d8c55fdcb09d8d01d11631e7409e3dffa027be768340e5a1a71c518396906b1ae32b44b08f6c0b54ca53c7e73375713656815e503a799205ef9b6753d177794c753ec2a067421a13272d09131fe37d212c19790d707c327146823e7442b56bca450f3de89888637e0dc249c2e42c6d6d47a6a49a27dad3aa5b543a0130d7d34f6310bbf8aca6e514be50e2cadc80a7133545d56bfe06a017191e5dd5ed598ba52bee9752896c65fcd4bcb9de79f7a89d781dd47601df7445e23104f2d7f9341d6c1e833247b1f5b56721255d2616e6edf75aee159735f15a70a170dcced4f0d029800b6462fe50379eec7119530650b4606ddd7721e568e52a934ea14565168c45cc0b4e540149badcdc1f70e3079f2adfc8ffa44333c88c5e875e64377780a23573a6f009d8f8d8bd3a2ec814f9a5636f19dedd93b0ab1f70a4b6666520d7b060925c95c2725ee065f52fd09b2f3b2b89201de0174ec755680cbba3e5828298a054bcdefa112aa739c554f847069ec6f4bc30c099c67eb930a68d20a01e5c68d12b9f1b1f3c557fc9ddbe6083aaa884880c95721c85ab22cbb5980bba49c708edeac69a95f7e0e70c9a75fe011411a1ee730f2f6699ae74708608ce6f33435efa0b31379f6c8bc2494dbe7145eb70f6d4d46f8d7827071c49d55c487f9fbfe1a56a7db761cf3d314205a18866b872aa8b9f4b68a930dca64e8fc294b6d59eefe25cfc1008689c78a1e90bca877ce9f46aa05f81e66a415092ef9bafff8d4732b12976b925bd83439e547e3df349eaac385d674bb2672e23290e5db0784ebabb24bed7831e9965c2db3dc8db4ca4c3525b3b132439fd0de7fd1480e2e697c2165e1a27b646898c1af610276c6f58fbc84104a345783be38749ae3f968c980e368b6c7943fcd5a3fdff44f4a44ee55cfd7f94d0eac235dad9296e979f32d5ee4fd624aaca794bf5cc30584e505382b852b880f6aff7da68d4c7970dab6d5510036bb453a7462d7cef59fa78d03de0ba69b266685dc2f17ce8e8a6c23e465175b352c977eacd5fc611d55a03dbb46a831e5016ea28329373d40cba6414193641f75e27a5099676670634008678c3b5d1f14e688a1196b08e4dd855611e56fb74146876ee12b6d7992dc34bfaf68462322e0f169e61b127c00b9c8817cdb59bc675387f671e913d64662128134932a50d8cb6f49a13646fcb10e2c3f1c8c517c5296d1285660549d1bc0ade7c03354749ea811002a9cf526100e264a6f9506c563211e56a811d8ee8eb8e2e917512d9bd38c0c1f51c6968cdb10b9d526d19f4762636bfd9353f904cee43d28b31f6a65266f46e0af9e7882aeed238450a985b493bcaceaf8eef545c93eb6b7a264dc278fd621c338f7dceddd29f68c20625619374410db7d45563e2d90341c475a5df5a5f8dccf3c648072e205adba8327eb36b9d2f0e7dc5ae59933063ef105538974bd47f11379566342c07461f6fce54bd2ddae8004824e93eb63cbe950663d88c31b9cf20e4abfdc1892405b4879cb32ce9c6eee7f93da5e7955d4c04b04cd13bb4ff3f13ee1ced444b80c92bd18d8c122f43020bb423a15142932bf522d9df402a29087bca975a852865ae27a9989a5921ad4345cb4a64f7e9f6aedb0217604a11b3eab8b4adaf2b9f527fc108b3a6d94bf6d0ecc63a237a70489041d1d499316396d67b5b8c73f6e6b91d0a6af32914fbfd860087ef4d14ca4553cea4781cb9b075e47a9fac71c38779892c87a21ebd942a596be33fa3f8473e869d99213782866fe8ad4a79d4d2dcee9abdd53de125a179af9bda9a8b8fa9092ea6ef17b6260da9099ffb1cda671fcc364ad5e40bb4028115be8833c9c6ee381e64c20d1ef056cb5132a04dbebadf2e62f8c545808f685f8f08e817558f27ac120970d6fb1250ae469d33f181ce62aa6a150fec671bc669427151da2e8de1f010c572a000172ca2a140ffd253a48c612c413eac55e9087817b42a468e929e116f4e33a63df26934e2478e806a583493c985f75c4edac0280317bfdb572f1ae1452aa26f3076e7e48fc91a253d689dfa76bb46b199abbfd6c5533da987747dbe90a4c9a8ca664661d8f09df9a2b6648e2b7185f459084f35a3d56f773da2bfc70b1d7ab0ddea709362afb0435c6e6f6a58d0cc42da9a884d76123b6df031accef92a77b67a906abe90abd54ffd358bd9aa977f926a71bc46a5d9b13ee0e4b761771ca5538601cbc7204463f3bc3821e06738acd83cbaf7571abbf032e9607ab7be96baee4ba563932f172ddee5d6adfa4c01b21439e8fa80101847ae4cf5ba289d46fd65545a45fb7f4186e02cf9a0aa2841bacd3c463d6f23ac88514c9039987671fdb263621b4ce663c7838dea4568905a5f1fa3ee4d82f222579ce278e145785c5403bcb37825d3f787ed3f4a657c7d06a77c31afdd33f4042d6baffa3898da308a9a2f367203bf5e6afa82a6d5c428cd8b8bfbf98a505cdd24282867d89d7dcc7ff7f56cfbfe6ed07ebb3fa36ce68ff1cbd2141a656a7e62ddd90e5fe72308c5a2a3a5f198bed49e4b7d373ae4920ea0ba52b3c9d8bd9fa45a655bbad9ebfc64f06a759a79d97f0693f73d25700a7aa7dad283b88c9d62d07951642561911f11e1c7bd760c9a021cbab298b0bddbccf828a2d203a10e36b7dc7d5f40df67c226a9a423f8e42a62a3e91b3ce9524e0bf9d2d18e07e1d0fcfb8c67693168871de6b5e683c0dcf46e95ce63b5887d2538f76078121a5cf124f2f0c06226387fe22be207b8b966b59f12a702bfbd6b00ba9b6d9ce2beec702e262af32ecdbf54811850c51ce03544087d7b0a292a87e0ae406e772bcfb02c84c513e05836ce62116a2e21920bd219d49d0d888156577204b6222e1b017a9bf5f6d57f43011ec2631a6323ee0238e89d0cb2b20b504c485f8a2a001e79d3ef7f56b71e8fd30add6013dddd984a2b5ceed885afd9b59bc639fb2dbc5903acb55bb2612e4bb7606f5431d864a12770f0cda1ab87a9323a40a8db68214aad3a00e3fcbf12d2327e33c658f629edb36355de41e91bc9ab3f4ae43dc43c7f457a28f51eb1e27a34db532a4a869242848dc23399572f4a02d07a52c58e8829d1c1a6e2cd123707240e1abf62f737ece64cfca027b31ff67d9dd567d4ca309f18a91d27a40fd2a4c1bb9297ac329222675d533d048d27909acd0d562589c137d6c0b4534ed1488eebc2e823eaecc1de95f120d2fa5292257c6c0e00b4352fe3da2880d08b7e4594770d2d0c8c5f2ffbc349b7555739226e5fc3c1f1e4effe5072f1fd8a6eb1bedfa334dfd7c6bed3580f5209773d7c1c133d26b758b7132436810f27f497b7470ea735fec626eb95b9d301ce012c8f61aa4db918c38baf9d52c67c0b2add59693bfed42a4e0263a7edcf473a481ee870260f3e8b22a42a820be4b65e797b801a86e2693a3d9364f687aff0a7177a6a3d35c535239585688255a2e378de152b88133be4a0524ad6ab72b539006e21f67cbe460ac56fb696174b87cff050b2c577b59c0c4b1677e5e325ea0b7d89d68a2438d9a2dcdfd898b05327bc8a8fb9c7df586c7659ed64de3032bce462832304726aa0f842cc12a4872172bbb364b5cb7e5d24eeb2d332d15bfafa591c9616363d945f14ff46c6b98ccbdc8e949a5647312fee2b8fdcf3ecbff2d7e259ef14d5beaa0cafdc81d8434afa394ca66769d230811330f7b1f68b6be89ac987a45904fc4e853134d5d3a6a140fb56a5e8decc3c37d98cfe3a9b43928f2e01efe9518a6bb7749dca1d7ae8089ee2e3861151c260c5a484e2f563c518bdffe45b2488cdd8e9e965aeab01bf894192b5987f1e96e18f75266e21e72c5a728ed2995a1605b33e8ecb21a9d56d25938730d6936c701a49a155eecb39075e4da05849c67dae2f2ad40962837ccd03743cc331e1b09dbba32ccffd77895201999664638a2b035fb346d2a65b3236253874cf6fd250666f68fa517328abf9014dc8545736eefbe2649140510f9e669b2e28bed80f2618898bd2eeffa0fb5e7f962f685d42a7f694255a33335842dd5f7f48969252a35edf0f8e6920ae85fd2836f89d358c3e451ef5c843c071230" +
                "a2fe30ec1efac1e58fb506267a50043fe6b9b0aedaae9208520d7285bffa2857d0c7d276e9b7523a1c22b8889c5295b5a539387d6738b996964071e25841edee21f1884ef73fe4c1fafa393dbeb0a6bcb56598762c554ac650797c90fccf5973fca168c3a9ccf0570a791c80be4840039083318589138f566ed5a0222e4af8ff3a3569e4dd5914644208b2289e790f15e5b4c3daf9d4033b4e1c77c878fee8493e5b0f6f4a4ff5657922c0642a7fef854e5a1620af30d8804abc4315cffb8e271991353556fd2e957c235e028c2afbf0a2c35a998cfe3c87f1e9bf0da9bfa73a67e5a6f3ab73c9ffd554c82fe52b742a25587d43fe6675915f2e509a7f0c6566196f4c5aae24bd495579026328a85f668f685466fdf7f76a8becd25b2cbbac3efb8306b2691451414407ee41fa1471055a2ab02f5ec99b2c612d0d1cd16f1af866e773d6aec53ed2dda0fb6bb140b766c0b3a0f8e6012b7d67554e7c7a1876f51d0cffbee1fc1a11d46257bfca462c7a9c17a4f872476b9aebe991846fcd10c431beba46f02cb0376a632c4b6e8b10cae1eff3d96224886c1d885a8c46d9dc80e6a5edcde5d436b902cb0565be77baad995411199151f5ea61ac1d7ca5014fc2ebc01a8cb9d1e7662dd93f253eee23f474bf3a25285c4e992a0f77e7c707a412d50e5a04f49f1069a9b810f2ddc9ec9f468c389279b75bddc6beaeaacee970c768a05e1ca667a796cc4a5acf756401959738079b0578a61a80c1329ab59bdd2bc62fa98178b3acb2972d47539d7b97bdae13a81be76eac592537d096902a248eddcc8200030df3f9a2963ae7c8a3a86e83595940810a619b063d9bc6fc0cb75035e988acac64480f5a1a31a787855d8a83013919a793d4de679a6810208aae6835ba9aae843e6cde97ec57296398ec3c128891f3c7e44f3fe0c9779350f66f55ec3be94f9eed53dc6ebfbe53ed427cc44089a70100e605f554f9410bbbf77adbad858ce214f06ab334228b8f894fb7a9b2e3b4b53baa67fd4311fb910c424cdc486e6739cd432a711f570699a903c52a7071c2948a5c6c9d125abadccd242e24c2871e83d7c048dd2da6a476466a9ec31a35a652c06be1eaea5b6820e87f880d9b2faf5c2a7e60355e4a941e1b748fba735d0e75dfec06c6a9f2e57f12171ec9d6c69c0fbe3c6808324175ab324efaba125a22cecb55d7be793e6799d6a8c2a64774ecf894b09ee626146d46ee5b6875e74459751e16b62a4feabc675d887910cea345bdd470fca4229237d4ff79b7673a974bac5da0cd2f3df6ecd0c21ea039acb0cfc74472a7a97a2116d3250f183d0e427228a9602fe6d39497b02713c61e478b5c1dc68aa0d1e0294d7a5bd9bf4b8182d2cbaa1b9455c2cd2ee1120c83166d6f2dddf1311f40168fbad45b1c7afab59b95077540e64b638c159dda711a35e0bcfbcdc89f8ee8da56d7dfa2e23f39e8dfca2033783a3380c031deef512177f7128400ca8f49d8cdcac9ee38a5f86b8ff90664418509fee67e383bfbb478d7434ff7a6f50f6b4a279be9ab33b7270658f129e4f56526f32b38887eeeb13e2b068bca0914e730397ce5003d181f777b45744bc43fd05141178878e2f2705017b4616d23ea244d54aadc74c4d8ef3cbca173964a50521b13cf235c4348930f1c7d17552bf9f89c988f977ed6078fbda9f23d81e117404fac83961b7d23a91c7de2a5aeaeedc8ebaee2f0f76d9327e81a1f23fddc05cc577e4c0dbfed207bea589963c00c96ad79f2360d470e3304ad86d203e1c24738973b46bf04609f1f744dd1975c0c7f7f4e7a337bffbe7c9e83fba1c69c6e18287f3afa2d3996ffc1bd5193ce2b52444fdcdb0b19f701297d88d0fa29962cec5d2ef399feafe95db1f5e8c3c645ae63750de0406d519710dbeaaeef4139aa1b9687f4cf3ff77cf42acc00833bded8e853cfe5ffb8a369800b227fdeaaf6f54c182aa21d1398b29016cc7d468424beef0f5babde8ec7b1b7259b0fa178d98a5e2e2a6f100fc9b2dcc4ee5ea49b240bac283c9e4657eaee6a3f266b7f091d30e96666c14f1285a8671d02656a3e5583d4a4850da032e27bc13845a807b36a974593b1d232bc7742f3f20d1111781746deb4ea6ac95653a1acdf4f649bc060044d3224147133b44bd88fb13caebc41b36f7e48ec97b21e405ec941b270960837be1d49179664567d1ee2342cef5f9e4a559c7b27aa5aeb094a60845308aaa9c2afe5fd4cb808a44e4b6211111a69b40862e530247320863b7fd37fa77e69f05e05a8c43b51d3dbbaf3c715e5c348abfcfc5673f8c21a8126c762325ae3cffae51ffd43cee880f480006b7ef63e3a9ac33e6389466ef1a0b0e67e47537db6bf0f4950f735df6cd81ac960084df5f17d827ab400c074f8fc09bc5353bdd8cd17c6dec09842e7fdfe283f7f33133b33b704da89184ac05b9f98f0b64a5a437647107438cbacb161b6ec97814f56928e800ae519efd7129bfbcbcd4b305a9c703ec4c2b7fc685030e741f951e182da0e0297f99b28a1adec735e4a8b571e79035b78513b6ec12d815323fda7ed61353c52d490186450359c7fda3b45258bf276ee655cebb8bb23b20067bb914cfa50510832e93be450dfb9b7938d3e9888632938ba8d52760169055359373a558a7e2db3e3f7d31476c638a263c48b02f73131c737be93f29b9d9612b6d91434a26e6bce2b536a16d866985ad835a995781cb72680b8a5ab806da807bc77b9ab0f5cc39e845e2be7599db544dccf61c214b998469e8e7e568db4d171b66eddcecfcbc74535753a1b430c91c64e4ef97fbb70bc2468173d0362940a1379d90b358806eb49c2632398b2572b3d821cb12c0fc32c68106d6357b26ea2cce6c6fa8e1a17bda0fa64820c450752483cd066900f36ecbfc34b100799756296d7e46e48c5c48d38cdf333b98a8c7aa1adc2b02b58a0189f2cd046a18d1778192d98cd9510b40fb35350361fc4c3e917ac19c372f196e52c976c083ed500b4238f636fe21b9f3c362bd2556b16e45f67de52aa2e8f08d92bc19fd18a0030591df154df34ef121eac4ab0cba5b5fe8920c4c3f3a63a20f439ea9dcda4ec0d7601fe8849aff4f5d4d5552cab4c73b34d41543551fe1008032d101fe1d94ab4943256471f4bd06eff1f9593afab9fa8cd534d88258936cc593785464f4546b268f6adfd878911497d035a60a0e6c68b5884d76bb4898ad59c41160321b83d40a364cb427699c201ad78852a22eaaef3d5ceaf9de365018b271e16abf0ff5819345ed4764b70b88decf41c15dd243d81cc599a2fef2a3befb2949f2ab244fbcd412432ad3600eb5d92d116ba618f8730a477debcb3280d8b1dc04bed8b360ec7bb47b9cae89d25e702db37c5b583fd72c3f0c08a1495f75f15982a9931fca16b5b1ef1868c50a855116e6e0f49495ef82705f3a3c8d834d1725f0f0506060c2cc37e148f78f020fc701424fe46a5159e3a73dc834433d244568bbae114f475e5e60c13f47e9e14db1d21d451d2c5f39c39af0b60651d059a899af0181ba0b4c7fd5a7e1416adfb9f5381b24ce947b7d09a27a264acf7f0fa28d9db6f6f277d86e94ed96a4a53cbd3a7fe099d7177c2d6ec783314e08947f6811d60f069a1e65663b93f9aba00dd7de119c550181262340a88b316c191cff1c7b43d936a466c0226a5968c2e84ca61faf9a32cb3170fb8d105d25b3952395426d28531797154875af2cd089f7505dfa742c83a9fd15ea57427767df5db894e58f7e026eb4d126067eca69c7c2440d9e12486c63957013961c24359f94f5c1dc239bf532998ca339b3f0053961fa7b71c3c2a614d4b8a821b5e1a5544c4d079e71a43a7965c34e981a1c5460b25b6831979883e48f76c7ed34c844406cf5268936c01c3faf13a235b72444b9d7a701fa9a495231fcd8b8ed89ff2993e7a0241f8ff77e71badc7f0c471024a240f4824da0ace63db199ded2e6f3953c43cec3f5d60394f546eeac40331aa3f466af470311bff164fc90b00995228cda7e239b354a10269904304436ffc6f42c17e9b9ffe9a946c205fc0add8103e12e342b4542062ca0083c286a0be8ad469885fa7171c5526e2baa153c8cb43d33e9b1db7c635827ecd26041aa632829acbe53c38f63462e4d7a308f299efd555294be0894ecebd3a11d4242e1aef59cf77768197b77282aa0dd81d9085f87daf6bba680e40aa252629e2668d87eaf38be0e5399c95eccf3af5ef5b6b9d9da27251b8375343aba5406c6ae8f78d2311828bac89fad2291433cd2ee74ffb81fee1a3170ed32305ee77b1ecd22c7dc6b7b5b400d42917275058a2be78bcd1d79a661aee6ade1ce17fb1cbdbafbe2dffd3884dd87e14e36fd4a27a5c64d4f970541a75af417dadc969e6bb5f29415070e1078071472b5e043361e5747809bcb83af5cc5bb17b03ec564ed1349b563563233760c4553b0ce46a6adde8b4f1cbcf0cc33ccf6d8ec8551144992a0f530b012ec11e28de9a3564096637e590d549b8264c3aa1284270a9310496fea8d53024853bf30801c657fc2439f0446b3de62e556754805a5618eb99e3ff6acc52c898900a565139dc593c4b2a37fa9e212b646d9f4c7fbb204c2401ea0d838a806dc26c067a390f202bd3446cfda0a569c1cbd99be00c125ff13e330bf7b67f8e489c2191d73a74d3cdebf0bbc20ceb4c024bed7069d261cf7418fd07d305b03dec683dea3e3ad4f1ef8df8073f720be0761ba4c6473ae3e8344f76e7e7530258aae63b0b183b0d364ff7b53d35bb0182f8cb56bd550a5148737a1e7520cdfa5b11f0caa70390ad04d0e98664d47af518d6972fd4f803e5b395a68a3e08df1ae70e0aec356075f616c8a60502d45fdd6444ac5ed5d37d2f6083caf91fc5d9851e636ceb095169d44bb865387a60ff46a277ab2f9f6d8160f09d051bb581c3daafd79cc8d2d307335a7505573d2ef74d0f66ab4a432488c215b6b72faa1b672c5805f0e3265583947fea3f20e6b1f10b4dd717c0ce3088fafebc16d48ad74ee4cf5e059164700d3f50df68f2fb8d8b932918ec820c0de00eda4caf332a1139924cb9549c265339495fa248164c422fd6a31337a78320c8c31193101a9ef7202fe0ce9d30521ac08f0f71b3fe100625ff22cf651ee9494101ffa3b4e8c8c360bf03ce35a6c00e3a0a7f024f9757b4914cead8b17a52669fc31bb92efae1513aaa3c109916ea7c025298036cbc91c69b7a53d5774c1c28c9356e33caf4a5d6e9809bc11de2b3bb3f0d2573f8c28c8320b8a397ee9e384dbcad1d8a99d70cadc1c337d6c9c2207fed9f62963c46c866c79fdd4abaee40b62ab54b942dc2da4cd87dc404b742eaec64ccd087d2b60e06b1396765390f6f8c254bba3b0d5bc015100a67319fd198fb2850586b63d2d2b728d47aef097893178195064925954678bf2d7e5e31bc10ab8a315a0289c8152e7ce3051df782d81b7c49e4f171f1de5255b87d4801b0842318f60dda27545eb0c8797f77eec5a064d166da02f04faf7d809219fdb082abb41e0a59eb0c8eb4e7f2a260aebe453c59fb18794fe1bf21eb9eb330740081873e0d674f026d261f82b8262c2979a6c8b17a7cedc89a737f7a5a43e68f513a9c0cb084fb4723d230864186c8e465db6eff89efabc81c7b511453503847d69efcd625afee62118c8172fac335c0218adaa22e0b6b7a205e1cb0ec4dd27c769fd626eda9952cc2887c3e4e7c2586977e7145bd175ca45ad507a6ddfeffda0555ebe142cffc93ff70623f8fde34f24c6f9d654671bd784bb31fd0dc11da9bfe4577408527ec385d71ea1d3b739101083594e4e63f4156eb6c37541555344073f25e39cdc7a39c5a659f560c9ceab686cfea58fb62a1fa4c7aa3a35d91d4ff284706054615d0782bbb6dfb3b07a5fc80df69f1292556f2ff044d1728be0a4604118386c199a19d467bcf118b5b07b4a52181c73d6bda19f8952683c56b61fcf096067f00e47cd106626aa6e3806a80ceeb33acdd8ae7390252c815629473d79abfa9368e0c6c546624a60b011715b87fb8d5cc9a1f028f1079ade65b35291bb0b1fa5f02b6072a40a78275e2ec4784e41d16fd83357ab084935f6d7896788ce7cba108896c0e865b303fed152a8ec3c664f4b135739a671d3a8335b1960a1727d451c85f0e5562fa021088eb45a7f694371d16c21f7b136b9642e817cad5135901de9122756bb776eac02b894d04e198ae881e0af62b79dab09db20311c83e69852ee7b5c13a546714dbceb221b0440af333c3c4344f4fc324c301a60d1f183e7330f110ed3596e253fa8c693063f5f9599faa778b1afbe68eb2f832af2a6acb250d7236e956d0fd56eded2ee11caa420a2687fdf82a74785366aa22e916d75ad1597ea3d2f9a0c5b6d07a4d557a931022bbdd36b4bbc75e97c3fda081facc8cc0782f902771166d34c8ea91147d1c7b7ec857881fdd5425581f1d027ffd2108ee15a9b81196b29059a5791850f6f330b47bc5c7180db701fa81da7030cfda8e60f12a69172bac1651b7392a0927b93b28b42b5d2e9d590e736bfad55993d97cb1b79a1f519591e2c528bfbd0e5504189719b9cf4f7b0d155734cd43800daf07357d653f73370a02618bae488201846aacb31565b5b23e7aa818e70b5ece5dfe1cbeb945e449f3d425065925505e62a8bd5ea20f21667ba834d8cc52026857cf176677a658c7db9e27b0e0e0c479031960b9b3f6d06026e2d87c60c7135bfd63b9dcb2c00e46e5f042393ba7ff958ee8fa72c2c9e9594bb2fa9162c38688dd77c3ff7695303ce3fc79953453e2e2c7fe02628e53c52036297c0c2ac5f4630919bd359bb69225eca419c6a6c89c071d6716c6ec0093fc65712c2e7dd0be6ef7c7417aaecc60f83088b64bc0f247d038e921cf6fd1e47a59da17d62ed646fcc502aceed35870eebcf10881cf0ff712c302bb4e7eeca684b49fc90de7e12bd211ce2e0421d698c59ac3984d71d9b02164fe9cbe95966c4da5f8c4800fdccb6bc09e4056af229619ab9ab723ef6592c6bbf83fcc20dabf9f49511c4311a1a97cacfc030604334583e6f5ab08654ab43d9392722f40a41dfbd6035a5edc25fbe72ec02ac6775795a1fefa99c18948f548be1a636ebd24b697b0a59c00071b73a90511911d27c0b00926a79902d859a40d7f0a77488dcf5af259e818d05d186b0474a4425ec3abeadbe310922acf1ec22a615874764511bf80d16bbedfcf837323283c84971f9bcdcac612942fd12dbd1beb8f6b658da42f50863366552738016491073e24ec7ed6f429706ae4b90816471af4031be4e492c8c2a08ff1680e3d3d934f2e0a3e42cdf7214e3ef59af7b39842988a1f4cad45ad0ad419d0382f766560b861959132e76806ed08d5322da000d39845feaf455bc306af95a7684eea71b4ac31a972220ea22f029977030314b9a4b21f8c402b0bf2f41da5bd721179d7672ae77f48f9f682ffdf5bab3588cf8a49d31c002b7adb4434cfc5a05488ef8f26ac80dc153fabd6cebe61a04c2428aa04e037c977441b1bb93ed431c914ade76b0c08cc887e3d590f1e2a50308fa3c54b22d92f9b8ac39d485cb84eb6ffa0a51718693f58aad932695e169b7e41a4f4ce021362241472d13e2ef0c569110fa5f0d05f244e3e6f9b8a706817fa592b2f9117e8c2defa18ebfd1563cbe348c4f8de0a16e7acd71735a657f75ff196605d4ea3fbb120e954701c8c59e0bfeeee38f7312307ebcee061b4226d3eda9aad6eb31d460a0d3552e156f3e86489dff4a03791be54a6925ee5b07d0545896106bc847bdd561146ef646aa91b879f0de706c740bfdb5d1c3a732b640731436a62c431187e775b4880a0b2275a312a894779212407be25031e403d9f36cbfe07418dff4dd9fa6379d110416697ee0c114d113c6f99e04cc37286c3d6851c5ccf781250e5d3049d93d1917723751d8672639f0bb854f87564af445ac5cb47a1fd35864b6ae446eb1e4806a6f3bc9e4ca4bd191cf9d4b56530735b16254b920afa2415329f673bf921e849f0aa7b8c51f0e5b40756d04c19a1eff8b622965ecacf183bb07b2b4572630f97f6eadda879bc0fffbbc4bff7ed1e5aca9a847de2129a3c935c278af6c29eebcf58a1e6cf093aa44aca35c1bafa6e2a361218b000ff4a2a49c65e64c12344d94c5040d1e737f8bd78bf015ecbfea6ce19574837c5471dd660e673dbd703eae068521ac27f570786a952e37d4ef425607ad60fe45b09a228f18ee664d04652ee2cbb488d42a0c9faaf50f867afa41f1b68aa9d7967f15adda81deb18c00f29ea8a5e0775381cf931f58caacb54a7ac41db043747a218927fbebff95aa1520e136f366088a0c006a2fe6b61070626e0c083ede8c423acfdd70d0de04927a5d2f481d4cbd2485c5bc7aa22f6fe226be46be4a9dfa6d10253675bf0760f3131a11e169dcc62f4338fdc35ce0280f23483c2ccd2ed854b3666f6e8c02ca15be940edcb11e996a84a61db5b0f68fc6703a0aed9866396e26895aae65bde6d50f573ba0a6e45a6671bea93700223b866360ec5baeef69294666acacd89acf029fd7e66b37d0d1fdd9aa0a69a827c6506edd8e48a771cbd698b868de3d4d4440348f97a0ab76709d57139a1da8f1b9543252bb8778eb2f5be0ed17756e4ae806e341741dc992dd2f06608eadeb4cd819ac791f0d30901e622bafee36b5409c091193e4c0f5a5db5c516cfd9e40496cf91773e6d87817f639f8d47385df3a43a2bef3705c25f636414f9c2887a782bd786b7b1cde6793907b15eed4e9486c991f21e3a02f7d48dd9366ff8760d95a46751cf1d32c2e72515f36e0d98ad9a5f81a70c06d5c4560868c6d1990def3b94475b76664381f722fdabe739066c58370aa03a28aa5bd00432177b74d70f4cb53ab7f3a5459e99e1b430d1dd547c273214dbed7c3cdc673a0f5b924a860cce78aa1e8cca714b5f28471368e2fb5f41d2e72e6967e20adbcd5006dd31f644b4439ecfd62541f69d5c9810ca00df676a284d4646923f76dd4846d7f289d29cf3dd9770cc4fc2a2fda158264538584aabd66d28f71018252892b545992ddcdf4a40fa2f3a909abfe0da2e722178d70e83ccd21477581af360c93d33531b095951804c15f2dbb80d48a9db7ea9900edef9651f758c97683eaee8e61c0c88d30c4969920aa732c57f8c5a1aa2834b9f9c3285267dc4e56a381633d466a64b2085abfa052b13d812a6873efe6f2544650186fea789d6924599bc06046f151931d7b6b614b836a1246b8ae7ce4614563ecb68cf9a57cd3731f89e1a73951a2ace26289a366529a987592d18d4d326fd0a9f289a6a9517d4e33de1736ea2f9c5e2c52493378bfd5b4fb643eb17fa154728e29ddc1b2d6fea380205692aac60d3916ec163777a6fbf2fb8cdf840e09f910e29c85727812a62dc3a3a39afdc2ea167a5449e12c2ce1371a32d57ce5802cda1f28254f0d9c544080622df00e2c094011ea97e34edd702de6a84c1b156da47667699b63ada7d58c202fbc2f540c8d4fbf8cdc95f9b102257fac1f2f8ce5bfd2f50e99f7282d2463208c08b106782a1ebd4a135ae1afcb54319972689303d6a524307e29114a50cdb2f8c94fb0f204f637a16fea8261ae51ac33b3b1ab498213636b9c7f855b9a46308ffa1f8b6c8b25a2b6065920f9a20833f9c097b8f48dae00ff898d7d462e55dab5aa07f9d1396504b8e42eecec392fca1f64c30305e02602f5b454c4a562bb17aab60970d440d913b8db0aae3383e1f3f013d7019e3e9d69147810546b1dc6fd68c9f47ac3c4a67972b854055f4706ae4861e584aa855d42e4b5dfd61fd9d6673beb5801d2e31bd7dd78091d474d7ade651dbe5ea208360be3ef1aeebd9e38681768c0783193d1c4474f913a2b4c395ed725ba539a6d6a0ad31015248c84805bf0cd35449653e8801a6a397f228d385e8cc8da401fbc8c111de9dde1257c0cae82220202870abc1a1112b807287b06d08f9d33ff02e81a19fd66f02ce48b71524b5a5177f80b3674105d56234bf717bf682f63943f9a6464638053561b78db54aeb6525035b39a01e610249af2c0b5f2b3b799f14f8c0ee76b66f09ac685ed9ba4678268441d14a22a4a65fd3d7d72816af4d842bdcef9bd20ecbbb42c6b6fd6668bcb0cc8c99fe5a30ae7ee5c850bec2d6296f91c2c1976fa55a4c9cbdaaebdc8f718475951affbe88c3af773953001c08ae069e1cf40bb9799f569954b33c3f4330c74652f088ab669c8b7cd93c5557be761764be9e85b0f07439d28b8e9977586922dfe4c287bdc4122fbe6378923c86bc586fb547b1012f92b2a75047f7a48f88e1730408bf53a6b6ea2c905d1807916be1e0288294cc466ee73f909ead23f31ef36b61e5df581f382c81aabc761f45547288621d16ba21e52c14b92c93e276c22f2b4ce5106928cdd0cdeb67dcdf8ef98db1a701e9f196a2cf3353a27bdcfd5ea32f8cb53795c40beaec2e33bb3ceeb980688709a6f875a2ea891367aa7b1d5b5de2f90d717d2efea3a3ab71777d1f4c7d758487f2114f5ad4062b31b08fefd3edda89982138e4185ed9f4cdd122761389e06bd4eabf217d4197b3fa1a0691a96f7b1ea33624e528132c104b25f0440236ee38df45c1581a68d1fb44e1bf29c3a191cc95ecc2fe09c38c78bba281cf51d51f06a22ea1cd6476b077c6deca2c278606fe8d6efd65dcf9fcbb7e984d75e69ee6e1989427c510034fd4501f75ffbaaf813bbbeb148dd1019d45e2e6ad33a22304f9cbcc54b78c8c3ce958f8a75a2a777f092dbe3b88344f84d93dc9bbec0aa9287a9859c740dd4dd7bf28e5222cabd4a525260a94996ab21d70c4c82ae42d7c802dc9e7377be23b15e5c13872b0a49ce3894c60bd1aa235fcff8d4af6fb85656376a5fd0409fc4b33419f9a4f70462baa3534bb8ed68b8ca471adf0e11d5ba51d4b614b678231e3036fbd5c632d956298ea9fe845727486896056d0c03ccdd1c9e8a9a60473db4e6face0c4edd3d0353fc588e24e6b428050f18974d8c85c7cbe95dab305b6720dc14c21b1550743e335263c756399ff8091f48da7cdfd9e1fe4790cb337e8db7640f2916fb910bce94e76c9dba93ce0c72c297c340c76da7895a75729b2e103646d91170978de2abb1544927d473113947c2fc1e048cc08bde0fe3e5e0afb144fde4fb7328545b05b100e432ed26d16e435fe4d6c0a4413a8041614569ccaf741e8d3e4eac01490c890fa924792a080750f582a538afcb5851be494f8bfb0649287fd01b5fe10f7402ec63899c67ba5c2d377683425d4b079b62e13e6debe7d6cfaf1f7e8f6def16902a725e89840eeef41fb54d74e97777a31e5275cbe2c6b49428cc11c34a334f967c3be7c8228b77029e494a7f30f0f774f9d7b3ac9cbb0792e5af1b1cc7bf8250b879a558fe1dcf0e47f9eed867580bed13bf0880693a1eac8eefa43ad554f64f8c07aebb280f71112a168c320b4a2cb757c2f0aba3f7168c4dc1ad9a95a959ebee8c4057eb6a67df2d80a815291ab340fe4e1c7edc4ea32ef97eddc3a1806d4da1edc07ab7362a215be04c47d9d204f644ac4463a9aca3b6620cae9842a2c4140c724fd7f73ea8a7adb19143907af6e3850a5851334062cace2722124fa72935979ddda0aaf71b3d0cb11b3ef12e955e87ce03bef2f686354b8023b45933787146beb2844f6bbb3e4e6278270b700e73b3b2c4513a9e8de1fbc15ca0f7b76f5386acddeb400452b6fe7e60d109ddf62a3404b1b3738de303d0e824796e1737c35e1077af37d5f8d915c8ab71a16635c60e18d76b3c9280d876a34fb0973b87ffc3d4761075e1f30a2be34621baf1c73cdffc7f965e590a63ad34897c27047df2140c976b62c7cc9f02fcefd07d9c0ce7ddeee9cc6dd7b20245a7a08268e2246044e84474969e1eb63930f495750917bc0975a0c65feb4d5a1d87a2ea7e1508cb2436f319adccc4618bf5bc1885d0e1fd3f254d5779037ecca9649879f1236cfd843bc832c2a7c2d79e6775fffa67da8bb582e400b36a5b95a7efd3bc6d33dacc0e2588c713fdb46c87095b629294efa9f197784766cbc697b84c874ff109705f2c0b6c2570b3d90f5b85d84a5e1ab2a037136d187e37a7cb33b406b3011fa3897e649ee63ab76022db7dd2d0eb1b7ae97088b19634ff9970bc1cedd6d20f5c67772e8096c634a7dade70f5f92710e41ee9d8dc3515d7d1d73a8a6190e1db33e2066bd26a9e828a1b8f90f7ff12a2f23627f75fea4164c19ec1ac04b942e6f2013bfe2c2e43c2b57f3b21024429b468c6d1a1dff7540614abd4bc82d5d9b059bde8b1031f96cda606fe9e94136b4290bd046c5e2818ecda86bb7e1fef74caebae4d090b6a58e12edfe52362a681dc64e378ab008550c883fa84b062b778fe2db472f32ca3fb2f74df7be06ef0a85f2fa019260c5cc1e66d7fe6d6962bf8762e9149a689749f3b871e88e5a8d4a61490dc8c701dc8ca3e920067613e907f5c736d68c792672895b47e9e797d0253bec32b9d5a79e0a433e1601d5e5072b7660b5ebed7e67bc95a6223176625290382192efaff0436ff1c704e9f76e1c64d83fed9472197a6bc000bcc24d02e5400efee09bc5881aee9bc801826cde13fc6d22a0a9dbfe4cb171c9528a0240b8ded6f922c77de1360939fa0bbe4fb82c3105f22c90040958b1cfad71423aa7fc3624e0d22a4e9da57e3dc09950a599266fa71c0841f80764e96a096e1ce4ad161c0cb5348bb5248513b4740748d10b423b9cbc95cbe6ae43040a5eed2ae2cfc7eb34081595ab6b2dd1fd7480089ee2e8fbcd06c6dc43a3243c9c4450f05c28559df8c0fc41cadb644854825662d1475c00dcec00818b746a286dc12acc5175a04d0ab685b48c76b40bd0790afa606be65e6c7df5e027f8bbd6979f00a08cb985b68a64f1604e6386715a4aa242d8176e43f6d8147dd64377a4f44d24fa3ed06323746207d95bf6323b61b42f4903d32f6235a77f98c25ce6ebe8d5f8b76d689267ecffe9c32b7dde34c7f43da41ce215456f1423572b78b116af081226c54eb0fcd8272890ea4ff1ccf91614c309cace805da498eb7b538f2f5e08d99f46d1f57981c5d8488301fd00d11f484e13c00bab448bdace012d2951db621aea02e2a1efd5638931f55faaa0c62e9a3d25ee26ef6a57ff22836b331e9d4d9179d5297972891bcdfeb695e9d296e61798456f9c7ace85c8e767211c5b586eaa114c74dcbcaaf8acc932707f42c775032e1f771428bb60c6fbca0e34e17a20ff52f4616516c60ff59a0b81f9908faae30985bb3126f98fd57aefe7e5b62098f47f35be80891ce4f9c4c6991b817128e3917b91d6fddb764b19e9e705c9fc3b45d1bb4fd4e0e06aabb40ca9f276f618e98856fa6eefb1646070e7504247df6dace32b472aa7dc41e633f086ab7d4ff34874c544d07d5679e7a8ac5f36672cf59ccadcf0c002e9f9322ca34a1691690a06b2f6dc2dd5d1b705490c8bd3acadea5d4e7dde44bfde584a62bfc85ad067be0e3a733e27ce017cac0230bfa5c53bf423dbd2f02ef0b95678a215afdd0480d0f1d7a1c709398e3448eb7b7c77c33570dfe545a81c6984c1bf19584953641daa62be86c17ae3b0c39daa12e0ddc5c40998f64abea505af6ac562d79d5f33cc19954348b0ed03028e71f6ee00962b0a3cbfc3ed78e92b58da538e8d4f65699a96bc41987f1b13aeaeb6fabab6b9bc9bb9e30ebb96a7a5817b73061d368a356f3d332e77da5e0f16d5f4fd981c132ca92cf6f6ad0f6ddbbb8f20912c4cb8a806e3386f39b7c5f668763366d01a4d69b5b0516b1b8b0930e7211cc060ef0d0de91e49656ffa28cb3ba42f4c2a31892eb91effff5f607b3bbcbc61733e8eff2680547ba75f37d4a7a6fd49019dabd5844aa2077dc5783919beb2c0a1f2601eaacc0ef67d61a70a8c9c248de2af03294e86f555ec59ac8c86d78a35c450ee80d7bab2b72761412cb54250b27aa3dd40b23532ecb3a14fd7fb6d0ab584a3677f6b1a373a1400100439edb5e011c9595daaa69fbccbdd1621f8ea08f21d4ba9dec01f2b75b6579f5010bf6538de8240a266eefd7e2fc9f2096c23465b5d545627737f162f8c5691c0eb07fe59879d55fad9174ada4043b9ccca80e2c9919d005e339f71802c6e64107e5d939921989642da4e3a24ee3d58ef82e99a54a4d4b2c732d114a823d6edafede047b8877713abd0a37da3086c64abd0cfbb2914d41fbcb6c33daf9405e371dca44f9b085bd7ce80ce5dc10847111cb72a6fa0ddc4d4f5fa7284c4becc389936cddbd759338701adaddcdc68be01cff14f472d30aea3189ae4dce09afbdc6d41405e16dce2f667bfba5600d7cbdec3d4d30041544dd461fa876c085c15de206ea8a00b90f89b5b010622d246b63a11dd57780c09e6e66288141e5191c9aa4d3887989cf2960b5f7d7d0a00b4fafe80691e335e8836cafefb784c05c4c13542d47123df54b71503998f750520e6226690a6d0e933adad8555f519c8e08d4835ff8826d9e975ced67b2084b5f20c5e2e2de0f32bd0cb3bc760174c9e3d383a4d45af9505d2c1cd4ea892cb0190d0ec47f1269623937425aa3725366ac712f7e30358de56b757912fbab0e73dd0d5672f0e23ae501930c7cd82b10dcd41815ce7135b8013e8a5ef854dca11b7c984d9da15547820604df6d0e30b896da0ab8329306220a4d095c610566196961f840733f872dec575ae58c11cf507248d3a5a017bef3c939bd05b789a41fa6d0ee0e41b72e62aedefd033cceae2e13404eaf2f3ba109c6cdb10cfa8b4e6a78ac3ee7978a273c999bca8a58930f4914044ba6605638ef5dff33b6b4b1fc7cd76ce502060affcb5232760f8aecf01825c14e3d1c0332b98a01747965b8e62c1cba3a865754aeeffc1a3fe38683a0ae89f7320b1ba314f1bc5dc2b47b094ba9242e7473245e6feb8e5fa63699f320c755e4b81f8fdc22d277d62d50bf1ac0a33047b7ef43c9eaad8376e3049b7a772cd5a21fa3a1358efa46857699cdf4e26ca3541f8a508b9f4baead07e9b8522081461f3a965547dbb7a43cd53f804419bb9ecccd7e0be09f69b07d320d52db53be1be2f6b4dc4ff8b7665681e9ba4cc8b6ac989bac9002a15913d0600e7100cd086494fb0d44da52a13627adb6089d8634288b08e9843ce090e79c37a286d9facda1126adc9bcac24faf62650f793407c36bb71a4e26526c7c84521aef3a7c702773ec2e4d9648a2269d86002a11325dd8eebabd321a4f6478cb670b8fc5b1ec5346b58e57915a776dd1830854a81f2716b089a336d3c4c9bde6337c9ebb94f269d9990028c04fb12ca59c2eb490470e33534d8efb250b518d7e2b23d515a716905e8e5200343adb21ee504195f282c913534a76452a49c76b8f5c33a8a174f5052dc3db943565e6fccbc36e7951a1063c8410a454b7fad8e54a021340062d2fdf94981dd6d88995014a11a7dbe244b401ff88d6f780ae1c0945d4fd88c2c3426296bc2c80d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8");
            Assert.True(Arrays.AreEqual(expected, attachedSig));

            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sig));
        }

        [Test]
        public void TestBasicKeyGenerationShake256128fSimple()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();


            FixedSecureRandom.Source[] source = {new FixedSecureRandom.Source(Hex.Decode(
                "7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4766BA69D8560A9F84846AD8B765390C84"))};

            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.shake_128f_simple));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), Hex.Decode("b505d7cfad1b497499323c8686325e47afbc007ba1e2b4a138f03aa9a6195ac8")), pubParams.GetEncoded()));
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e47afbc007ba1e2b4a138f03aa9a6195ac8")), privParams.GetEncoded()));
        }

        [Test]
        public void TestBasicKeyGenerationShake256128fSimpleSign()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();

            FixedSecureRandom.Source[] source = {new FixedSecureRandom.Source(Hex.Decode(
                "7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4766BA69D8560A9F84846AD8B765390C84"))};


            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.shake_128f_simple));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            byte[] msg = Hex.Decode("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8");

            SphincsPlusSigner signer = new SphincsPlusSigner();


            FixedSecureRandom.Source[] source1 = { new FixedSecureRandom.Source(Hex.Decode("33b3c07507e4201748494d832b6ee2a6")) };
            FixedSecureRandom fr = new FixedSecureRandom(source1);

            signer.Init(true, new ParametersWithRandom(privParams, fr));

            byte[] sig = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sig, msg);

            byte[] expected = Hex.Decode("07eb19e7d838d71ef66b8263b5d1f8ecd2efd33ed07448479b4797fba5216cddcb44fa323ab9607d20c58772c8df4ab618d33a938535045c76508cdda022d93f1f53f0ee23e84c8dfd7e8035604949c6ea48881490c73ffbbd9846a4eb5f6bba4c57c26d6eb552cb549098669d3ad21964c8d1096237bcdaef80246f3d970ad789aa982ffb3413a5a8ca8e1bb5e64f609133aa50c95667d6d7645660723e0db4e34fd4f7e7cf72465f84cdd635d3fa5ddb3e76c591f48f8aa9e09c12c8bca5e5696747b28a3a842559421439c04be1ee6140f91c54b17f2dc3eef4b357e37669a7c411d6be56b4315f49c090497dfe2581aa23488354284fbc75c8aa7939023c6bc4035b914b303c50eb47dfb0e5f7c324d0d5e4bc32e0855cbe169c030e77ce5bc9bb3bda52b4dc83bbf2fc5e5d34c86f48ba5d828e4bf9270c1d3907bd10c68488cce4784c90f7598ba6639ddf5896e33eae8e0346bd84a9d6164895101e15ca808433d6cabc6f096254b225166990ab05bfc56e356d22dbb096baae26037c4059c078b03f1a454f3c42f1143b25e5166f7dd68a7f7e97300ebf35e8516e9800fc4aec46c628ae415eae03d0d88673ed0b6c8729fa3cc8b48e7e8700cf6c0427a714c16c1ada0e4061b199402ffb22763dfef58383d4654d11363f31fbb7dfb1872419547fc4275e2e807f8a7a4def2a2320be3b2a064e21180187dd5afeb63724801e50524f16ed350df41bfea9aac34ae862842817ca7db96daf5994a36c1592259961ecd5deccf4dd8ac8ccd16031836a58d9ba0571707c5a246be1dbd7afbba8d828afdc2273c60fd3a66f4252095b44300b0646a715ad810810a1db103f43c88b3b312d33d02e6b2f889c310fd7591c7933bf987c2fc58a8f2e7dc4ab498883096ce9f0904bc1fe93a4157b72f77f2bdd8ef295f777c7408add81e901b20d372d822ac91e87c1248b1ed1ebd9bd27f37eba0ad57a4f6a140e24792ef1d69231f28575cd7857e0aa789699d620f866f402e63ff6fe1d462bdd21099799825e52f0c977068f4af39b253e8453132de071f2c785a4c70b6c7623570534edc1cd87e1b65e56e3ff874503101bb763c1f6f59276f905924d0869ce9c603e509f127b01e589b2bc187877bc9138113fc52c18ed57bf03436ffb460ba03bbe51dee2d62f602655fb05687d2cb06a24728e9caaa8bac9db4d130ee95bd6033dce8620c714892c3c3f77d25192698bf57cbe62e0842fdc12b591449e2d0861293cbce88bec378c0cae81697aaac26865e7f774e7d4dada842b422543735bd260b75c447e01d19261dd7cc218a743afb6b5361ce02c911e503bc2ead2c4c6131db0c64052d8c0ea97b26042bef20f65c34c9cda1e0b3fc185cc5960af78863151ef48b897cd58f75ca32aa3888b71a401cc24ebcbe3c443469bb04215886e3810a09a7be206691faa8d03616ac21d4d7281fdfd8af529f4e137411d463c11d08e84e6e715fdde60f6229d96c10d219cc59d40fef7384938442122ab330129ff3ec32c2df7b44c150dd6be50c589457d722828c51b93e374827d23e23fea793c01a0c0187ca95531a7bf236158de18de453c95c2f669ffe87a0d155893296a04b9598a3cf3408ba1246f01c8491e718f0edf229da5e79b1867185911a203ec31303f0bdc8a9205baab40f54851bbc72e4c8641cc36e4af705255af3ee44f6720927d7950762bfad39fb5d1f5645a2fd5016cacc136957c060a4d2c8ec6e82462b348abc2fbd6413ffc383fa046db7ecaebaf30ea6325224762fc82775f6981e3444bede850d8cd02a92ea3fbcbde49c4290f99710ae93d2c5a209fe775cc3fde3a0c3118a74e70803e20687913a21311e0b714ce6a7dbe2fd523633c040e2e8b6a0d807aa7d51fbeb816157270d78e251016809e0eafece9391ebfcefb413898bea612f4884a27c6a49778e85ed517eb44ceb9dd3f0d0968053775e8d554357bf676f3b113d70e93414b868e17716ca582aaebf4f5f29365bb9f88b0bd9b1cbddd27e8d2287d6b4a051081be7a66cb015a98624b6812b669e70c9382c5a75cb8e6d49e346d252505b3adc61025fbd7054b6f8160eca46fa84c10b68bdc1b257596229d506457895e9553b153d63c5dcd061eefb2c8de12855ccff35c7bc6638d67200dd12056bddbe0bc103459e2fbffee706d8a9ab7e8b4ebcf47a9f30d77af96c3a4b603e30e9991296ad5f43b8f2cd9da912a0f79e2273a16df1deed09e438e199cce62819c6edf3613a1441f6e496bd02c6d0276101514798464e9aa36d8408f976cecead4e8fe27ede0c87ae61bb5d663b7d1bca5b874cf4ef72c1d9785e443722d92b7e5806039a817c76ef4a60f98daeb634d9d889bda3a1d1d086edfc40aff43ce22fe0451a1fdcaea9f48107a6b0e76b243d8c2885188075f91c81832f3b1fe5a406dca04adbefc1acc96b09e58a1acb01f5e2f4417251e7009cf9eaa28f2715dfcb64163db747309cd6d59aa2112af5082add942a6a1983858c11b0d8666c88525d967714c10d99bd3cbe400d4ec21b97b22f848acaeb4abed40ce6969ed90b02567efa208f89f9335c97ffdc51059dc979b32dbc2392f37e01f91ce94a17e936b836a9cad68169c7d8b73874569f8f40e78fe5ca8a7d5ff9486ab1ffb09d79fb97eab437cacee52c95f0a6d7d67527ab1d65ae6ee44dd1379915c8f65b5a229993ff4c3483af67dced2c1c644e7b7a910f598d51bf699b050a6be94631ed07a73b6dc38cd4036af554909c1e6725291f6406e1fbec7405ec4910d04fa326e2f37e61f834179c080a2d9a030d41bfc3f84612e046fa3a6add79a9e53f62d46da6899c8b2ec2dfcbacd18e53eb37fa65e446f74c801ef4202eb683e2fb93e2e8bf6a694fb6533850f081402241a9be10d502c3ea28e99bd33a854119c916b891528590dffeaffa182a4d6044190b165ba78475d3fb738c0c19e0eba507e2ff73d4e55f1e879e5b33b577bc3b5efa39e8b07ab56030d8621067ee1d0d2b6b578026d29b24410fbd21d44f26db696fd79b4f7c39e52fa71a17a5edbb341cac5a393d73c20aff8e44b75ce2668d3035ee73312a496ef7e7be43c4615a740d0ff9807480482341e0a6c6e80751badbb70267aa58722b9d0f017ecf17a1f797b363ecde0142dff2d242b983347699a79f7f66588df87f1f52e27b16ed2100efa7c7e2cdd7dd1df92366d1ea9c33c2e35ede25b2f4fff04ae955bef1b02deab05e378fa4fb66970221362e878598363e6b47c21d58764097f570707b91f12b15dd5c72f43570dcd2fbcf63e471d7d8c18b079b5835dca28732a3c42eb1514d1e5782a645822326ad771d72ba68830479eccd604465d63ee0ac37130cde9e17bff47111f49d79aa448b3976b17a8ded13832ad41437101389063fc89353d6a95f37319ccf66091ac58c286a1e1bc987103fdcd7b201b320853988cde734d36e68fdd1ceed5c9dd1d036c392c91834d5f7c564e4c5da836ef2a1a5f5bd1ef2d0e2258476d08970be46046539d77f9a0778d9c653874258940c4674e77fd4f01aae0e48c4616002609e4e109395581dbc3f33d1bf21d07f67a0e4267c60cfbfbfbf20135dd72910cec5d375c449310a9636bf59d90531d1c6ae06505085afa464307443e36b2654b453d60471ff86b4bfff90c98bdeb385e069723d17eee0c0ab141797a49827abff2391f6b4b8f7662a5f2344eda6478c2fb0f0bda249110cd03692e7f9f9a9dc006de9fab8df8de70fee7f2e04894d00e24c3ae309d27e114bac535a2740aedceffdff6f6b112d76a432830762b89e9ff2080e03402a9bf96f60f11e767a2cca95358dd019922d18c74add9d535ab88fcc950dca1a86bb88c4b6fe3328da293b7136cd008d269f3af92583751a0873f8b4c3d93e788ccdbaa0f2d990049191935b6d9a4010d3d9c1ee940cf607ba5b4957213a61caa8da27f7a4a6716043dbc7619cca81a8d5446006352a915b74a350c0856472ea870bf4506f187a5103409a87600fcf4307bcb54eefa9bfa2b1822abd4717a7d90ddfc80b1ce6452ee94fe4df4f6c7dc15fddfded3b444679dfa4b188d741f66ef10b5a36c608e6f33c3a1a9bc4fb94d141b9215ec84db4d4ce9de47dd11d88bf6c22cae984cbc4f81297a96674c648cf6e916d640fa160c9e0b9deec9aebec90e6acf012a9d6344ffcfa9a6871f4a7ec796d48c2c9aa4b0f2aeb262c513948370fe9ba5ca56c41b36f49697fda285ce774268375ca055792a0328ddf539104f5c76e4fc34f0f4a7afda71b0b6fa329b6ba1cfae5de692eee989c44931eacfafaebff6617a5c022b39d8fa6b326a3b2d1cb22931a5b91b6d41ca6f0a44e73e7bc359a3a4dd9740fbcb6491fe1cc0f03002f4ffc5af237ad27b0f5ad8944e391f7164586e5074872d922acd06c6ef859a965d3ffe15a39d15000cfc612cd6a44f5d1710cd2a3cb2c8ad3c4a1744368d98356bc55a14dbece4f7add4480bacd8fb70d9a3e1f5a4f1ba0b5ef260852d569e14bc243e2d37ebb979a02d4552b886d10fc543dbc27a2e4eb194f93aef7f52ed7a3736d8bb8525f1348a2d97742fa9428c8c7409b770669d92af4412c0eafe7351704e5b8314806faa955769f98da96b59191bc7b16a2b74a9602607c0b6c562f550154bb289f91e5bd34ed3b82d1c001dacc759008b19dbf7d75ee93139d4d4ccb6b95ebab6e1a1f289c04e64658f0e87d5f6b1387a3543c9fe0647eb6834532fe4c64542a172da933f7df48bcec4d68218dc49662a32573755a2985940e83709f0609f6ffce009f023e95e63406a366ecff23f6ae928e7d533e942125eb23bbc4557f8b9b75a5f752052f1ad2d73db639ad8353ddc76709c1922f8f982903cf57d495b6582e3d61c62ac401315261300ccbee070465ecd116ca3b02b6cf21392118a5bb722b33bdf447f1754e89c9e33e8ac48e798cfcf09f1144a537419e537504df81090a61428c092cbc1a13d8ee1160fa99c3db43a0703eb7a4806c61de696c76844996085aaccd7b76d1a0f46d2b0ad3e28c7285aa9dc11ea5ca5aac42fb211a1b079786f688266ff9d7af5ae7fb4838d0219846a13e02aaeb62ceff4a1012fd1c3c1b455442561f64f5db6f6cf3b6fb7728501eea757eee0d4d42617c8b0bbb84a6abf1e234ab293ad120b7cb8be424cdb822f93950f666d8de1ff6badc9146ebd6ce2378a356b0a6edce361c96175d1cfd0288c16d6d286c73967246e78238277685960307c6ba96a12d6b7e315960bf1fa30afba382cb9c8c15dd9457c1e6e3f7f37d5bd3ed6e64af2274ea80d90a33426e2b8491f35c5292cd24eb29e632403b031f64fca8287af1e8dee8f26828793e87fabdecc7fd11be7ef1d335ec5aefa1c8305b4e819222b22237aff967cba49308917073a6bea505bc122f5fd99775e23cd381c50f1c6164529af5f0f4bec8991a19e269471fa971dbf7efa7e890290c06ea911a047b5d1e4c76aac0e697560b5f8316c4c0b7cc54ad55ad3852c3efee2e4f2d91f7408c27da014d188f8640651f9d18dba99a22fdcce14df709ea052a917c840240e5386f1a361e0502966a7698a506aea38698d1bd28f36ad728e042061fdc387b9ccbb4e7566c32939da6851c982881a8eb925ba052fa0b7efe81a2f4e7b28e48260ae28456c1f110b6e31f87f2122fcd8946a5d965059f73ae98320ea2e022c6a0dc60ab21d5662700db22834ec67734cb6a3116b7005b56d326502c42954e16c65d09af49eca7254a61fe8ab329a2a0583cfcab1e40ef54e44b42fd349b9dff179473ce1af62fe96b239560400cbb8605c79adedcb38aaa76392195fb6f37a92f92f1e5d12e32bb327f32bc2bcd6655c25c1842e8375493b5415c0af2c0b4ac566b7a7c1325f5e4f7160e093ea00ef8811ca63b65abdbe7901d7757d0cbb8fbe300e7e0451b1d17f5987567be996b996fb75d70c9d477a31be7f107b5a47720042bd4f333c58d501e197c3811309c033382db2f61b66602b9ad20bf56797cade8d3200d57bb9ebfa86f44542a9d42ea0fc3fc6d951e6951278b114c5e6fa2041db624e8d7f43003fc808a61b0b64a707b118e1e46cbcef43d9d8505b0fbad9793602e030c010751416ccfa7ea5f84695fa7b81037d9df505e785ff1ee96780611157dc08d0cbe9169f54623174983e2a23975eda931e537db69124c0713393ae2999b4f6528a2959d4cc44916acd49f28d8f279a907494eb883770b8a8d61d005d2a724768958560568905291c52da232483a75d197c3a632ae80d1358b1bda6d9faeac46938e65c076051201c4c7c8660e3db8d06c56d2a9caaba97278522ad5bdd2a30fe1d4d32623773543976f56f3c6ef1cc9bcf8b16538277693c04119a335d2d83a730bdc161eaa766569342ab92b36fc4956526acb4be8bb8d527af63207387c9da2fa26e6df8bd2cd42aaa9a3b569312b972dea8b4068986f6d996a1b8dc7b56578e2a7803f61c480b545ab95b0e1342e6cc5b9637e3c2679752c736c1e8b237509636473127b59c35b449d79f79f97832ff5bd14fcc251ee1aabdf419918a62e2df33da300c12e7634a3fed4361f229f06bd1dd007945712bb2decec60aa877231f93000766e70dae07865ff416a492da1944a0411d83a36f3eec11be27851659751239685cbbe23436fb2f867f3b7ad667919e81052c62f7ee560eb840a9955d4ade9f6eed1c02aa2323f351bfd6d57f9218b2dcbc78ec139402ebf49a6296677a13b5fbe9ad83244ec4f89f7335eefbae2e93a58bf5782124ce4f8b32d5d5b669dfc8b2a1d5dad77235bfffb57feffa4203b3fe74a3bc31482f0be187d68caf1904f2c1952b8d8bdad3a363f4b0382f767a3713c4e1a08f8dc4d39abd8ccf448614fddd32362554a1b8d9a187af7846c8d36e796fc9691c491e367b6df7671228692c2d7e950fd408d9c367680eca9847bbdcd4f34cf4fd9477fe916e9b87ce3405285eb28a03ed38e3519eb4881bcc0574036252e8e44d9b20836ac3e1e240e144415e958a49ebbd552ccc4fee8d0f0278d794c66ddcec64773bc6df293cf26a3d756369ad6510261245ab9fc6bb05faf7c30ec9862d7686c8babd1acd9a59ca8206ab3c90a9da2b424924b0dc72fe1c16e74f65df13ee7732aa0b6f85bc7ed28265ee1e9e4d3d980bf6970ea74440b13c7585be6d9423c317e483f5ac9434e382e4990012bf0cb4f81bde09d715cf9de420e610daa02861929b3689660ccf082445e8039f04d5b5d4cab0394e6694c0f4a281995b479b8a98ca4a42357b048e24693a087e723f5b237cbd2ea0f1d2eadcf0f0642261e46fc6c7eee42d5db0a2db18df09511f1c230e543e6dd9a8d5de658e6ea9bc4052c6369394db0c6d89ba8abeececbc872795fd21b540767d9182bba786c1b4f9f12fbc651ade9fcbfb79fae9605f228fdb1442191b6e82872efb727e6868888306eefe1c7de161ae1c3398e31daa1d16068f7110481be32cfa640633ba407610fa105808eaab6f631a5858666a94e04744d7a4baf3c37710b204afa536c17d188736f33fd874f3ef86503e20fe9fe4dbe34ff29ce4c33b22f3336fa3a0046691069399c14467cdae752c57364ca8fab9ffefac2d05015f21c2e0b9ab568d5e3bbcc03f573cf693b3192c73dcdb297caec77b000f4130facba4f52a845c56b82ce708fdcaa90f9ddfb83fa74ad036ae203f626fb786a630e6eca9bab8b1921e500000fdde798065d46deb8ea1889ebe2a0bf86cc3b1a1ecc6683681c4d87321e0ab124078b78ccedf5a845d3144e4ad200b32b5933e6c72e692e74a2e39fc909b487f9c25f24f4364fef5f121a339212fa03e93b9a33b546dd4b3c1256d31ab19d0f164cecee630b128cb4be49f4f1382beb57cdd9e24d8f719acd9f1715f961a1729aa5e33be7db30fe5b2e791cbcf1f8a44fcac4e32c043464cce941bd16a96104866f52e76903b7f2c1906da118aeb2c51ba7cda85f1ff05a2b932d58a51a83d0467de48e611a1c5b2611c5086fed70cc48de01be9fe68f069804930c409c970b094451086e66bfe82291232c06f2489d6cb22dcb174b63656993b95ec1f6c03a177c6261208828a24ff945bf4ea2d5fdacd9447291950c59c42ec548eaf55117938769a6555a86147ccf0940e892ab7af8a67c82c016c81eddb5fd66669fbf73262c624ab05efaaa2003818a146f9c6c566fa40917ece19280510eae8c1b70eba7a016153974e6ee76ee7d82ce37141fbffcb8b9bdfeb7d1d44cfad2578765813fb231e9e64cd0ec7b179c615513248aa27dbb700d84cbc9813134ea54dc0aaa9d9f2ce287193f0c7f6232b4d6470eb5055f25eeec2ae1cc6b0f76e7e52e02fb3dc1e0fcd4135a28f07c5e8d0d98718f183bd401662c293501d41b51859f17d31a12fcfec4e067507ea2d5f268e72e92420236eab5e63c698781c8e027e9e50b7209f6f5f9f59077e8c6a5dfb1564ef0920aa86f00cf041c492dd7851ca62c2c889d4c014111dccebe8ccbaeded0c2a5198a8df084131e4671c12319b59d175efdf901efa95c973f21536ea3e6bf79a9570717152e0553a71600e3eb0509b6fc07d36386a91ff66c795f388986e2e8c40ead5bc879ca89249c6c876e91db6044c718940f11a82b0fc0611cc9776722ab039a2337c22436aaa0e201cadb356c33cf4eb54e8c5e25b3a17ba45605e5a05fe2d3830c9976327aebca4d1840df2564e8954c9d226b5211144469ad954998dc82106e4497fceb7f7cb657a467d3715f54d2b2c4c82e55af037819be21f2a055700ef984f49070fad5501058b18492401359e1111b42c90b638413b5c8ace7dd696569f0b07471caf0ceb3b9c1d46f5d63ae989b3e286ddd675beab96449818fa573f5074b2bad96f59235b7eada3d08c37fa24608be97f34c2c72780310a4ec5a03494bc682b02d0e65aba0ecdd7e3365f46aaccd36d7a2e6a28e2a7a52b4074998a34825c29ea980a8fd00b906758cc1ea5e729c9ffae6df27b0d168ec2de65648ae9d2e56c369a34c6a4640ae4a55a4b7e8df97c6c8b3d5fb31209204d238486991a333022e6ddf7c8144f670a33bd934e2bfac7e503874381c7c5bffdaf252756263896508ee3d281c336bb91bbf2b70371548da6fec13bf66d10966761abc8b796033e90b7b778a5496442911967fa8fa6e3f5ae7efedc154daf0e5a432665057fe04879034c3d044e6d5f122d76870f7c0ba3f52fd1967af858cff702e6f94162f3875054fc6111a7181b893db570d9a5d41aa5136edf3d6cb9c1e433eb8b25d681529b95089a2e51488fb9968fdc11c99abea22efb0e9cdcf8350ba731e1708bd3539af7182eb00f7b6ea491aad93198254644775f39fc29b4fe00003993fed2880b7278bd4685644b7b107cbb8607b5cb996257ae2e8320f04157d7b5683b929589f5f0c3761a4c69107d86bf5197f93855c4e971f3a96b78db48bfae224a20ffbe13d5c993d2a45afd7b68af7ef8c80cbde64bb873c337dd3cc761ddbaefdc39fed49f56649217bd667c210bc648ddf79d4dab4adcae0be2d98b2781437f65bdb5f9d17213c9e049adc24dcf979562de975e3b9f3c14996fabb9b8d709d0679d32c97d5df124781ff814587039986bdde8981219f2884155dd84ff459238fb4fc04bdc0a167b58f1d08be70ac35666354786f8c7464d796b4335b859e0bffb641a641b6fd50a32eea862d16c9980b3d5039623daf1d754685cced59d39a27593f995982c082deb92d3676fe5d82bf7692358a03a363ea1110ad38820440749d59b43c8f556c297bb93cd3512c157222b2091405ddc196ecf4449981721b97ec69ac051c814d27441864b22fd4ba48cfebb119b3f3343d2a60f4b6213329d74757ffdd314ab849638e08530f3e0b5cb24e969ca38e1d94fbd8e0a26de324b6c174d168b79e1ee9ebbdded1a901f77ac287f1251b00455dfa00fb260afdbdb51c78c9e73e4a13536d21b8786a3b802990d59b0c620d384a099e39e74e09df337f9354450c9b38b2614ae75d202dc1102f468a9e38e800f78291e9743e1834f71162c2d53b755b9844bc351a1d8622a22bdabd236633799311bc7e7056f10450e00dedfbc3ebe3eeb7b772013fc765c1287d860f270b378fb2d8b733ebb3e38fa3e7b6246e5eb5ffd4ba3b957e8075d931e976a81e4b085188f97bdb1b90de8f2f5445beba3316a822873c54a6f5aa6d3519db6d9de88189fab6e0779436676217ce6efc31d62e77275cc6400e6d770748babe24c82cb47a55e8fde1bb501f9f59c18bf999aae1f9919b1bc2eaf70b2a4320b3ac3fdd77e5b8efa5e675df120f3afc921e9f594fd64b4b24948da1af11e6d3b715444bcab58e006b8a91a8144466a5982df663421e6af45c7a4db67c830b05458408c6ee41a8590ceec0c5663d5d65ca35fda76bbf7465efa76cfb23d7db44efeb1b7c76d4b8b672cecef224c01b49d500c3ec0781426768a36d811e9797080f47bc184ff17027b9a58fe18cbe3c8eb442e9d19f4a928cdd365873e30d8b820cda211c991b2f6019a7ead11357910fc4781f24b915280b77ecf9b8f09cc85e539f55937b55c1cbe7709c3aa5ec26587b18a22b2a7201e9b1b379205d40ee64d7d26a9b6657eb6a4026859af4df23bb5092b9a8ef8b783698c3d44b7cdd54e0675888129f53429ebbb7948f5bf9f32dc28a126b76ea4cbab75a4881eb023e92881412f7cd9dd58399f5b100158f9345483a1515b7d7f77797f279b20fbd83f2907dd2a2171eceb1297ac333b31e65b57dfcbaca1e1b04ee28e89e8c938f6dbe5a7f14c2c5e98e77497b3e4758a51f2dbab5ddd38bea9c87756afc89641118f7d94b898d432f95df37321db3ffb4664e021f5640cbe5a51fe0dda3e734207f941f5ec4649dfd5d956811d716b6fb556342d58306bdb7bc1cd929c747ddb4b90afe3c6e6b4ce7a7fb7db5c5ec52653440c7af513529d9f7efded73a33a1565740bfbf35dbca95480263661a445ac2286386fe80b69fc8d74663cf587a9e5589decdf1c6b8a088b37daacbf95f55e6f4eb13f104f2739e90356da9d4e3e9dda87f23fe0c060409596bad760461dd2546eeb85d98e351416a35840582cac50b07ed59f18f1c30cd7ba954d31a84ecf9cd853d0c9b9b22a52aa83baaa2d04631e15dd32b8aac0cd36389e5730ef7bf42a82b92d7c8ce00a8089468380159faf1e643eef9f6b2948013ae4a63453a70ca96f2310572b8d474da66e9d3f4bc3951b8d0a8267166f952851a0bcd1231b362043cb8b52ec10d2584ae25c2f1635b9835c8d8567c5683d606e26e92b163c14fdc7ee9ea67444dad2b14b7d77738639119f986770582aa1ed89c944bf9a2e868303407c1aed39a1e277e7456cffcc53a427f67c5a9ae5ac42161c3203c8e44a8599d309e14334c76146da72495a2ace327fa0064f77b1d52b2b27c032513bfd744c7997deb73a20c46ec8db2a8f570ac03cc56c45c5edd01d42981264e30984dbffc7e7b25b4ca4bc94a5189e0ce6c256efdbe923c928c55ce3004a10fe8798f0e5c61f2695f53772bfe0fc8ae02e8e44aea21f013633f4c92a03b7c0ac63c29e2161f193505f6c61708da62dc3e683239ba7467bbc2c10466fb112f501f9f9a9984662143a1262f2a087e3717ac19194d3dafd04308a163e38fc25a6214bdf775ae714cd55a72a75df2db8659dc21483ba3816f519e39fd8283a55a107aa638d9d96087696849d960c206219c10a43fd9dae6abcbf65def1cc48aee6a18ee27d2d8a627590c4a6f6d2c8ca8ab3a5d6f6e5fbee239e8ff57ae18294cbd4b27a9ec9ad4dc46b52f7f6c275d7d1c75d563d8dd935a6754ff9789b7c1e255b89c6a126b4236b387dd1f1afe379445f5cc443e1a8049e5137c6fb45d4832af99da931a3abc48cf7de32c1b5433242598e1d7b17c1203744f5e9de84cb2463e8d5211adc4529e4f92ec06337d34b1bd41a7381adcb2968c142b434b0c0ac7194e32f7f76cb5ac48c36856327140e2f1edf947076a816784229733264298eb0169ccfd68e0299c5a62fa7b76deed0786e06bb2de46f309ce36eda9e9f0dc42ffb3661ac2dbabeb195ec26f335d580fc76e9bcd48cd2d472ffebdf4e103a862eb01d55779f579ce961958e6fbe89c738c6e517d941006b4576f8d1360bd418d472ed4b6be7a8a422ee14dec7f725580dfaa8a9ce7b2103c56fe9421734974db1df720763755241d5190b6ab3e6b3e3e4659b360331da1181503c251e02a5c12b4bf24de9af8d72456f9c397662d0594c512328e95ce2860562271496d072e521e1dca1ecaf21290dd15ab16edd633fbc25061414d0b15091f3a1e24e8f8a847713eb900e45c980740076eae61fe25339a20dd46594d05983fe8b19f5f319e1ff908a797c2d67a49596ae8eec3d961bee4da090f8053118933c34f520a6eff2fb7b66cf3af87d21d6708389fbbb645a37835689a9e91a7d58febc598dc82c2e30d14c86dbd849190cbe0d77c6d47da8c97f8ced748dc53baa4c167696ffe8ee61e1d456250e2229c66a5d327d2ada490dd92aa06ffcecba57d402d1a05d3b743087527c9af999d952b498a3a52482bd947fc6781c95002edc7a07bfbbfdb86aac13cac3fb375d6c1626838a0f301fa3dfd66e48ecf0c9ec30c55512cdf2bdc9bdee714f086ac2f7cd66ead9d48c62aa56314413c85a94d9b73ceb85f722327efdbe8fc005fb29f74feed6ae75c435e527b1ee20be088311bd5db8d8906759139f4f1adfbdcb6ee11d5d9715052ba5fa243f59f4c61b4acd3c859cc1a2f60f60e4f173fa73e52a785a022b242171757e44fdbfad5b54fe46f3ceebcd60e9ba5261d49318fec95e60fe5914e995737c8f470ae6268c0c8d6a6f4d3797b414d7844d2cde35a1dc92dc110b2fa9cc8241783dc3f56c78fa48285762801e4ecb8aa26cf11bf277a5fb769a2d20c03a499fd0ef6b81ad5f107aa1d54d2a42fc6a61ef75cbffc2261a97e29777ffa811008cb7a448dbc2c79bb4a90993f9c0b9da20ee0d2b8d64a0408cdddb12e01e9ec1cb91d052babd766a38a8604051407e3216a1ac0ffa6f9bdd837ea27e583e257216ed020a44461fb063efdd946b8bb887a9e929905c049af41b644c943c44e3b71d2368f25c35c44463a73681545b12444fb7c2ed4387b81392b72d5a08002214c93a0f3ddb564c3ddd66ff4bda1a4a809bca9d5bceaac74e98bf159f2e15f01f78f9411fe33e88bd23bb2c6589c018b5ef09810cf2210eca0cf88d30f5543daf69e659fee7ab51b27e5f86d8395306a0189f00b80f06a44eb86bbf63821d34e8b0f4b8897af61e88870dc44fe9dba8250359d04f41b2fafbad0d61471ddda25f104e903f46369af45867f8e4eaa9cc6d254694e7c7db9b591994e4151a98f0082e33b4c905e0ecfbdc1efababaa766cc1417ae96295b262e4307312d01488ca4dfdbe82a045ca3d13b2981f8e9c11d534a7f70a6395d6afdeef7c065a9d58693afd73ca7a6c5b0dc7de014a9e52eccf09cbda328a99b08bbdabbc1cf86536a9f3a4f9193d5b035a0117a8c8f3bf2c01b2309e32bca59b4bd879aca2beabb201f417fb239fbd804a331fc1e9fd3195a5555a83d80c49dac524f5bd8d6d13ba0493321e0a4a7b7e1ac245fe51b8193d996d19e2861a2743aa5d4b6fe94387b0cc0304ad34261b079e6efb7fe4122d9fbe50d5ed77f81116fe845739e822fb97c0d7e82655c11ad075e82b51563c38d7a9e27ed59ea657c8daff922ed6c97259b1f80d3ed264a060b3ed0fd5340bf5b7a9790dddf4f788d0eddc1d71caf1916198b6c2b88bb3f2e9391be1a9079d740e6e06bc7f68167196741a16ae0b1f096d263c1d57854d055d6dc5acf8af3ee929175b1625df2968b6954af433777f215c898cb6affd4ea29a762def7b23b90c192f78bf06eb1f2ed5b348f9c31861834f39bbbf45195fc51f33b30833c37620936ba584b4971568e8666cfddc0e78fe52d7adde904b2740768d20ace5bd5d556e65a701cce82ed76e6c0554349f39e1d4f45dcf6e1388f0dbd717d7548c8c074d34d0e09eb79d63bef01f8cbe2284902d90df866ce92987ea4f5c5ff3b9448970a8293127d4119b62b155948697c5b28995176d6623fc957b133cb28ec224a357892f1d84017643cc9f14d188aa1922ad8ada01e0add3ddc97ed371ea3420fc294dc73fd440333dc6908940b13a93338f43ca135b49e7fb654904ae54c4887d170af831f6f2a25180f87e2c30e09711c8c1c62ca0bb129a43ad78ce319bbf22419b96a673bf47bcd083fb15e2513446450e031a5324cea8e2ab317e45c3cdfa315523c88272af5b44dc9dbfa82ea5e73082d304654e4acda2b0dd27884ea5db98feeb0ea2d87afcad6bc22f8dfac7363121adc3e6160c53503b86d00a69fcfcf43dd651da233a9d7992a926a19c84c78902694cd2e81c68ad7d079841cf8fd993e2ecd00d156aaf8ea1c0dbfc11717a07e0702a2bb1b87ee138f555935502eb29bec93c2cfce66ad6c9e9f8379969a869225d53fe229a6201a6f4807db69c4299cd9954a3479ab9a6acca722449846fc0564413f1825a87cffa0c322aa8ef468e946dbbb18d552182e1d006d75794aec43039d58b7326c08bff5f983f34aeaac15a097aaf8f656a030ded23022e89164cf982b2a422f34b5cd80ebaafb294d875a8e59b9fb4ba6801c84c893a5b3fd6e30662ca68a2bb2c94506404df5abd94e9a6074adeb0cee045089dbbb60935fd8d6de78f1f132803ecc5e1ccfcd8989e2d06a1d1538a329d7faf069d94104e9f943d0af19923a28254cff628d762a33a4ebdf8ee9ccaa1189ad7c077df95955e0fa134b7fec8aeea3f9c6d90b174ce60fb929daa82da4b6cfe430bc749384254db21ff61599aa165ec95813e46dcb7385f4e8c372fcd8da135363e517db2e94dd587c9aaec8ee25d25ec3eeb8c7aa2168de8c2bafcd4c10d2c069b19b0438274f5fcf0663901695a3a77fd0c05ced7f05df29573e15bf21234807df7060407568eef8c71d8c1cd13d314f24206a3db3d11f5af1a3488015a9558d1a3b771432e50c462936ef6fc3b7b3fd8cb3434c5b3321b7ab82cfa54212cd15e85d2d7a8154c0475798f68175a81cf454529b7f08160fd15b9aa6064a2a0fa7b432baca3d326f000181b962da9847a499dd52e71e5816e5a11995ae9dc61bd5392f0850be25425f296f44b085ee7ab23ece55b4e197b2d19919dce938e6db063e5c529be569c001541080c8b2f6a979b137883fd871b8d6c61b4bc0a64a1a5be462b50e6686ba94a8a26e900a1c300a06256312f209bf20de9c46af092841a033035eee677ac7c971871d48fdd4eb097dc2cdb0ff0551c390c3daeb3a7a75a8d2fae37f6961c56493e7a91f2f1c0c7821a193f2ddfc4a483f695edd46b03e922474cb487f1ed7dcf1d9a156b80cda4b8a93816f773d2806a26efd7f504384c622ce7ff9dc70dd59f59a86c18605f60f199b0620d13873f5e67ba20a7d8399e0afc92776d590197ca6001143c1f8373f844b7ad5d690ed0313a5a4bcd89a37096e8a6fe8cb0e6a22b9e630af8ad49d2d2b9a8be53a75abf7e9eac22355a422f0e12d940ad33aa6ef65c7becd5ea5a9e05b10a54afb94dd25607c8618e86be40989f43ff21850f4619d37363876b3f9157e4a482e10e725efcbf63510c1594b25ed44c074850ef8f4f4623becd651dbee24729af5876da3523cc171be7b47965236f028d46b8018a5fc3c70248b6f4a7f6e9b5a83dc7964e38164ae7f417ee7a414eaf4670eb1a46cbfd6aa4bccb6ca8fff9b64f24bf62e12ab616cf7da3d9045383c4394b5bd7c9565e5f408b6eab844945c62f585437b13d70a0f2b0078a1c1c1e3d9060a240cfc2f8d88e4f12982220167f2cff876ab88d53108fa4cbd2187618f3965634d30d4ec62c5b941ce283eb96446e100d4c61aca2b9a0a2093a40fc9b12dc6efc89666888c98ea19368b4b893ba7e910bfc24bb6eeac0d2c44c5763162c23a44acd1c935044f17b578720a3e3f32a59f4618ece4d21172581138195022cc65f0f4196ccee3c620de035e5827c6c1eb82e2e86bafbb9a7c133209db33d877a2c4baf5994cec9b9866f720b16eb0a15e20dac0a1a4e8fbdbb7890ef562a0359c1f604fbd7f614ed1162a0c290bdb7ae1ebd6a7679dd81518870588826880a830b0cbbbb4a8cebc26822aeb0e14a8181875a81900d5ebb40fd467eb3b89226afd27ce540cf1980074299a27f8e78fa2d7f90daa13744f7dbbacd2f21662f3b15ad6ef74ef75e937ea437317a846c937b000e74dd1935044c3241c3a0bb2748cc46416c6e5b28c04ec55271a8a16dded47df3c3cd8762b6a248d54a8e0cff94a8751a4e06d459a54c9c6dd02c8c64a49be4adfdc2901af48641aef11b5160dac2aec4ab70f6401b0c044427666ded842b46f131941401fb3790d9314e5a02b4ac30a8938298b826d8cf4be9a32c997fb063f9eccea77d0ec8bb7b13e005397baa3b97e227488fc79c48f68d3d2b9d03cdfe246d444eeb32b77d9ed73ea9bd4e3e29827d69007fd85767e76c54e9ed42a00f6c4651ddb6ea8786c6768f2b18c74ad52d3f4186829e18ef2cdc994f12fd2771c2653500d5933af2029d23c7472045b37d549152eab9335d2d307573b1168b920d91f1f3205b1bc0c4942599c0113f785bc09b58016d670a2e8281e0dd63ea5335e1f506baa788e85fc06b35d3260b789d413816b5e48fe0ecc56b962f10edaa1407ff1e4985b7f3cb4146e6793229af3b60ab389a164d407b564b56b7310a2f0780cfb1b8654d79376e54bd22247e5ae80032338b0dc291d13da272c154cd8294f8cb8477cfc2e8c5cc3b841166bf2281ec376d7027db700705fa8eca0e26ecbf47927979367ee73f07e55320df2cd6b704406c1d36797597886424933bbccc58828187b6787287910cf258a5670e0090ce1044899596cdaaf1100707731e2467447c3d14420104861421e706204839a3d04688629ce09cfafc8590fa3bcb31b6c37d2f70ef24213d8f146d1515d173cb6935632ccd6058091fa98bf89a722af9698b954fb4e700046688c6f6696698c516de7aba878703a9a23b5d9dbdd63e0924f7428695cb168850cc8ae51843854c43bd482b19136efaa2fb3c0fb370f2d81f05354e97921c642e3669ff7c14f8a0b18e87caacf24c3095d9b8aac41dbdf0dc1633ab87a6e9d599b424a9c5c3aaf65b527508cc0ce238d7985672b09b8382882b783c453d694f9a2b2de5da8d1b713d1a3ddc5b36ea0a5e7955418e532474547b8310d76cbd1b40cd6fb336d44d7bf1c346accb6cc6326304834ee7fcec6121903abbe8f41e1024f58b4605040c63b3308e619116f1e827d25a7d6b337ed955b4616c9b757a479572b61f56aacb2773ca2b75a06d96590d9302bd7f5279f60821f9e21452a4c6d4b3ab62906d1617000df0b51599579e91ab0a7622437d798bfeefb00739f5c82c4ca395652c8f2a0c7f00915eabb952713745d609347e876b2f733e3fb00b4278f90cca8aa4d9c55acfdbed4a904b91f07d51ab7fa2b77b0f22c767b71cb86a6f8e2c169c50a29e733bf3dca895421cf4df672630753f897a0ad8a0e5606c97b096ca7d577ad3bc237a4ef53756d9d3369786616426524579e7bcfe27d1a622c11953202b091956bc3c5527b7530c080034caa2a45a21c32dac704e7b7ef4f3193bf0a36ba8961fd27cf44b7b1042def689bea2f5191c0c6369504078449260015b54c9a238fb54abaded8df118762d3a9ace989438bc25332a3de358f35f4c94d8eb58ffd9a88f935d6362ece8d838f1588b075ae74913f17a25bb7e1c3e00b62962515b1714c1fd23c07dd46ea7b7ec200560628fc5807e49f955a1ed06dfb24ebe211bc4effa334293532883abab142a72636bb0d915587931ce6079249a89b684ec3abc82ae6435f620d927857a47a0c29e3516548ea9a275a9fd68acf0c23f8c225bf9ddf1d88e533bba106178458a46adaf48d9085750404b80e65a12ce34679f8dd9361576c203cc86fdc48022b93d3d0d3355c6c1dd9b5c016bd3167ced0bfd3f21b2864cd4ddcba4a12df520f479ccb7b9a9717de050dc76a3df65a3fc37ea3003a38a4e01c752bf6b2d82e21191e4f956c0b2382a8a9efd07977c122acb5bb2a5973d3427d803d9869779502bbc92a21442e3b5de4d49d805b3a1a63e78dbd13dbe687d24e8db6dabf1968b1cf7df77b5a5b5424ad7c0167465edd0d7858d69d381d8d25c7aabdfe74dfdd146e177d4a9b3f4c8b82efed54b91201b7bb62642de20faf948bf200d8ab885ed2a8a944bbe20dcd0e736e890e72a4fd6f80784c6cb6a992d553cc9266df472292cf8189da1a10578f77c067e843676b4aa24cdd839b715eda9cfec1b005dc9b15b123eb7bd8eea57b80e2eede9944ed7e54b190bc9b2681e3da25ddac421b247e0fd72b48e72b98b4ae1e8bc31f9a6b5c0b033fbe0a894a2df5748f55d4d6e0fc9d60161f878e27bb7f8dd127d9d6cdbcd3524b450f528de8cbbb413113fc35c04f728798ddf4925cfd6d7d66f695fdfbdfb8a2d14cbc10571e3b300051f62579c7234586b19860b5e1cd080d4746837f6cce14ef0ae9f2eb08f7989a580e0799bf1bebbbea1a17ea9521cdd1b1a31f793984471c6d389bd24536fe977998ceb42ce01e9b789881593f76b806763d87b6732c81f636d694309b2a97a337a4a7f8d7b84aff98ba88e20207f8702c31f2c072e73102bdc4dab7a8a536e34bf808e789ef03ac2817a1396419688109ad4c56c3e36272c07570f7a5ba756fd143c3750f23d767ef71309a4d6912fd9017d179353e798c04516c35eaf7d2c8f7cc18a72fe3e131ad6db0c43512be43f22799dd34e0956b909990905182a2e6f45bd84223b727a45ffe596224d97c48dda603b3a96ccbe46ef7124e649b155d3fc35e24e9b57db83c1c9be73bb1335afd3cf92f12100c7b97627c7c2eb2cd789bb8be04b225b079c16819a25200e8d734772db33d3e1fedbe72d00ecdefd6e6e5cd1813ade7bbff3bf1267e25ff98d69635adefbddae6a047445f5ce00627ce46d8420d87ab2317135b010524ef4d10525c28eab8c2c161d07951a4771ce708b42bf15cdc7094c8bf70ef0c45fa74a7f26ca5be6b25c1b1abc25e5a89fd93e4df19cb25c54ca6ab3845e7405e583968abcd1b30afe1759d63181545f5f1ecbde94fa3d0e3022f0cee71554fc51140c8ec1b90d3e3b4e966e4cafaf6db2a154d19210dafeb2a9dfd4c10d0ce48784fda86f1298e619acbb3c5a5464de8d9ae6ffb0a745db5c1d3848218d3d55cd4b26076b1430e84411cc9a7c46f92f19671285e84c593243e669851685dd9d3fe4bc21a4fb32e3695544a859cf8ffa459181e7fb7dd2f140e5e2640acc1187eb38db4e20c486e52ceff423ab9fc798c4073a36018e29affe6d5466afc6dd7c184b732e86a53171cb50f0c17237c24b071b70e3d108325b54197849c1323cdd960c711e9eb36f1a0ebb864d600a3070b5de8488fdd104785e4cd0a22ccefba25bc178fcbebd61c59a4f6b1651bf20907ad06fb653edcc3857e097222b39b90675459f1ac59cab63fd06f48cf187a3f897b19477945e470ce2390622658d831ea7ef7facf0cae92826ffe1a2a7eb4be0aad3fb9828b4eae0e1948952b80db99f5340b1e28539e09440144a21e22b9e6673882f8618b4cfd201047a78db9f9466b67cf97ed4ebb81cb4d9a01e7dad01b521ba5820f954297c5663a85581ba7c01512e600f96a15d33be6120a454f8fe9ebcd0d1caa8f8e080b1be48e9df542910b7b085c44bf1885ddad30bba22da989ad36997f13a975a97d63dbc46e4b103aeb73cbf7c4f28ac0f548267b79388390403dc8ed4d249a2446ea5b9b0c204b1bf68cb46797466bcde73bc10fe7ce9d5859d44e5b90895b5b6b3b25aa89fc14af046295f0c14da9bc151a0cf0942d221410931962a739044f0efc5a6160ce5bcba8988e0c079f73c53be6e9182f771b143ae5307d3bdeb9a7fe1d28be54000f2b3c02e518c87b9ec878463ebeffbf3d1910e0359c42aeddcbb161082c71eec262e0da9445586177c4b440635d1c9b8af83c276a0374290145c0d899485a77ca9a3a6caee9952993016ce46f8a239b638370d01b43df6d3dc4477bb478342f90b3ec23fb279091eb1301ae97eff0b8ebfaf07c8cd409da3bc472f51dd37249f64655329ef4750c1c66c54e84e2f6469cd3228a1e55de55d03218189e81475feab302bfaf1a6c53a3faa50ab17b627bd45a9ba2587cfded84ec99e89e803a84b5d21f9001111a495e5866467018d463313465ce7ba73a071eeb83e8df4c97597e7585988a30c499ae321c6b6e9780ee3ff84bdb199b6bc905171c53608b084daff0f42bb61bb72780d3456b652ded654675df91e4a79a7924c78076281e9445d5d60524847e170df4c887f2e31a18ed55b215bcc27dbe0de127359bd0c8459860bc2d1deb3b46832c23d54f08b43bac14d468b5dabd51bb2c2ab9fdeb5626fcf865bda54712e882a3cb5f328ffbc6cc4c1f184cebb0d4e39f4123981e7f2ca026918b7fecb7913662cf8e29dddec0079a33ed226c73afe8d4039497aceb7eed111a175393e72c4d090a27ff9283cc5bd8969c8f239b295104d6bcb585324273bff58e09481053ce7d5cd882aa34c5f038326105beb85662272bed3fb9a9361a483ef6eb67dc53181589c3f63d4553984464a3c31f9bd940a0559152487f3e8eb0998f54cb4c66f732d05e5fb4f20a4b398bc84d7b10e0a60af06e2ca42d8e759aa4046765374625b57c5db49fb517853a7f57d14f626ef49d10adfedf87530671dedbf28e34bcf356e363c82a21bc1ef8c4cdb01ada71950d003a05c46985c9f4604c89f7824ecd7bf65d6e0ae88b4f07da8736aee9acb918e4e7b21d25468a9b6130689582cfee12dbb84d9199b75dd395cceef94354d2b28435094347b9c6fc72203d54fd235319b24a9ba867d67dd7b33f791397f7f306c063f7b08bf5f1db9737b16df1c97efca69104f2bb76259927ae6ad45db596ad5dc925b78417494c4eccfab88d6a0d4e88da0ed836f70df9388138ab7972a75381ede6a519768692e09cccb5c2fe15ec16d22354cb15d1a12df61f37295e1f687ad508ec8481cb5e6836fe15aad26a299a585d11c5fa5cb2a9614b622ea0a25f0f51ece3c4d8df40c9782bd0edfd6122c355916fddee2b446ff3f4a9320b2799dd9dbfdb1151c357ef75291e022cc5427348cb366de5f691bb33db8ad38f1e13002d500957b643449cd35140474959e60234a75f3154241d95314967eae69e895db608ebd708d7a92de2b691ba8229b4bbc7cdba57c5a19bbe6205d623277eac4058761d480ac171f03a73639199d2df7897e860bbf9fe83e9d26cfa10536de1fc022bfbccba5a34eb9b910df9aedfeeb98a9d882c09da7966c066f23f1f05f936a33df9a7d569ec678ec0e5a3f4326647439d080e253c416b5c375c5507a9f6397ef745fbf1de6a314692db99822ab883aa92c1b70581ecb2ddcbf6b8050a6391fa1d850caa2211df019ce7d9051659a250a27b93bd137fb682977bab22e718937ad32b97313efd3a38ad0cfdb10dc823f0ff49a1e2761e773940280a6731f8275914a707fdbc6b01117eebeb0a6385ada776ecadb469577f4c5ec6081f02215a36f2e8a183d6a126dd29cbb1317557f30db5593b75d1cde48631a750ed4050f7aa3547e812fd2515bc8ff85452eaf2a4903abaa99fdad2607bed5061f02fefc70c6221a1dcf5663afc183a140ad5d600b9a7fccb0037eea5705918464c059937e0e525252372fea1fb2ab59b8e838ac2afca220a636ebeaabf2f0adc00dad47c68f3548defeeb65e0ce8f350dc143cfd2ecd99681f74122cb08bbc73a97afaa3c641cda585d65dc0eeb7d6f8ccdcccb9e08fc34ef2a6fcd9ba4ffe17a83f7ea3f76b662aa829451b78083e99a52d0d86a5509ec634e12b87cc22913a984429dad57d7ba33969a7b2ce213c7bae9cc641a403a0e9f9f1e6d43971a4d8e41bf3c9d756be99a42ef46bbec4fcb0ef951d12a63e1ef5cd8e4ccca00ea75b66eee04ce16f02ecef1e321ec8eb9a1338944396843339ef065ff9df68a11028907f45f906cd87350f1db279d4b10d599b0bbe3ce1c5747ff3812ea5c242e76e67ae977f449263c8ea38dbacd48af0913b27cd7f84b20b02ba6d50760281f6e85828e4d974cb0a73efab92a5330a22ad00c85504e5514392e8fa22e3e7aa3df1bcd6d0d56afbe20df04d1908d7445f03d9a5b2234db0c0c8a2924cecb2fb2b9a329040fe3b3cf52589e118eb75de1c3a02596c0159cdfcf840cfa682b2548863d9ab34f3d82f73cbe78897e40adbd96f9240e1b4a51a0d22e58dddda4dbbf90c1037f3b631777dd9f870b017b337697b38906f68f6299efc5026e9c774903bc8a8a85a2f0fde95dc7c20c1b4540c495569bd9d7539ae53d7e2df5d214d1eaa85e7b551f7752e98401ca38337e21a9857e346b6cfde9e80789a0515808246c610a2e9f8c288f24b7628ecc98dc6b2848b0098d0e44e1531c8676448cd2d393835ebed828b78e2ae820ba3d954590adce7e1c227259903796280312eb16f00b12d7c30f09a683884fa3b2dbae9e47593f16ed7f3ef4704a7093404670646b3eeb062f9be55af5244b7f0315b273c3320cb9343e9251dd00efa991fe9a34fb10c1dbb95215654dde8ad0ebf922ecaac3ea60d209da466c9c99b86539909c331442fdf233bd8d2ea77ab9053d676c95d249df72f20a8adc25792aa9faca94f65c0841d43a585099b2b36eb9b2be76396ca5cd6bed0bb4357a5ee6f5385343b2a3d12caebdb836cea569031a5793c38580e1575a5282e5f2b376c542c13b81fe1a1681714c635aa5e1f643c616131b8436958775c1ffbb3c8a02a8dbcd7175e4be9d5a4ad252ff9a3d4a9a5e5554ce2e0c9d2f9c3ec2389ec2dedbcb2b734fe8afb95b5e83312bb220e35ef3e00cca7935d0294dac42946e09802de574257ca7f4390d78f21360e3ab6b181590e87855ead08448d4df6cef788e8822931bf9cf265f0a2ee8d029a3d1f8a4f795a9b60b77b52d2f551129468ae2b12764d7109e2cbbba8ee837c2a3dbf2fd88d2154493e502b6bf7a0747814160b68b72dd1824fbad318c2ba12fa16a5934f5a390f4aba1808dc60fc5cde8484bb431105aab788588d243c18c33b05029b7c84c0d643600ed8c1d250e883bd524a83614859b0e025549b18c03d2894f37b9c584e0b371212d68bcfed60b18570b0cf63645c808286b9765725754e4f751daf403815182b21c4b301183e2799f6bc144f16f98a96bafffc8b0b63b505762e2f66e9dcb44802d04d80ca8b33731d7b62da025ab83b4430ceb4cdd0de2433c396227e90f0dbd0c827826f9209a7672846b78bacdb935a271f3f18be486952826c29edd709d910edca1a8fb598712a3776ddece903f247a88e4247a093b5db0aa8fbc51572263f12063bdc8da8140843f581dabf765fcfce299ce315e67e7c965d51dabfc2ad5eb72426e0c43d60551e1c56170ca73f89b6782c4027b5ecbd7ea87d611e82c3bf54cce971a60a719be00e3c81b60e7b375c1532852cef9dafb88a130b218ac0f4c232c8418120e14eef266c2299f640c73b09f70779771c226fa4c3b8b00d52a195e2671201379e5245d5dce08df4ab4cbb9c2478d9b96f32413453988c875299c5e4a315623de8acb3f4f3039d2d7395a424c7c998fe270b6a21214ac1bde4730fd8e991dff3d38120bdc8223003a5a524e04a2fb9ba7ffbc2570076bf2a378e7c8f97f2ca4c74c4aa2b6b2a8eac571053b9553a8a96a6bd83bf665d473c742b6b69cfebb8763af518a716c180a41c2a66e6f5394cc8262779200c3279995a5d7452c25b864a9c8ea424e1334262871b2af99859cf79f71a256ec6f580068359dbd704ba65c4926132f39b723bd145c88479d7154e5f561aa0919217174be0204b0e85f8ecb3850ada9412e69dd919873ae9d2849ba615eb46d7b0ee036f2dd81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8");
            Assert.True(Arrays.AreEqual(expected, attachedSig));

            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sig));
        }

        [Test]
        public void TestBasicKeyGenerationShake256128fRobust()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();

            FixedSecureRandom.Source[] source = { new FixedSecureRandom.Source(Hex.Decode("7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E47354D75735F16E03DEC94D1F5B00C213D")) };
            FixedSecureRandom random = new FixedSecureRandom(source);

            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.shake_128f));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), Hex.Decode("b505d7cfad1b497499323c8686325e4714be46e5b92237d09a0ea8a0404033a6")), pubParams.GetEncoded()));
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), Hex.Decode("7c9935a0b07694aa0c6d10e4db6b1add2fd81a25ccb148032dcd739936737f2db505d7cfad1b497499323c8686325e4714be46e5b92237d09a0ea8a0404033a6")), privParams.GetEncoded()));
        }

        [Test]
        public void TestBasicKeyGenerationShake256128fRobustSign()
        {
            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();


            FixedSecureRandom.Source[] source = { new FixedSecureRandom.Source(Hex.Decode("7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E47354D75735F16E03DEC94D1F5B00C213D")) };
            FixedSecureRandom random = new FixedSecureRandom(source);


            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, SphincsPlusParameters.shake_128f));

            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            byte[] msg = Hex.Decode("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8");

            SphincsPlusSigner signer = new SphincsPlusSigner();

            FixedSecureRandom.Source[] source1 =
                {new FixedSecureRandom.Source(Hex.Decode("33b3c07507e4201748494d832b6ee2a6"))};
            FixedSecureRandom fr = new FixedSecureRandom(source1);
            signer.Init(true, new ParametersWithRandom(privParams, fr));

            byte[] sig = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sig, msg);

            byte[] expected = Hex.Decode("07eb19e7d838d71ef66b8263b5d1f8ecb3c75a5a8cce9174bef2da68e240f0b51034f5be32805476360a52ec07b9a85d655e9755c20b537d3958f3cf04bd9e4cccee4f739e44115497616a6b3f0f22de4430e08b3fba3e1c1f8274b4f26443f3d2f48fb56a16bf1cde1a41c047a466c97dfc395d00b66b85490d845925a13a45aae6810338c3665515cf755e31db4a2f81de06cda0fbb20a49d127695c4736d2aaba5381d5bbf2281228f8320872c64496622fc46d98e05db717d3e9d29eb897d0320cb13e5615b47cd81ab33fff16740e07f42702c20ac13006f2dc23c90d577d05b68a49259d0b2444d572f9536d50f36fd600ecce283c69ecfeade51d3a7db80c90370fa14e67567a29408e1df8268e73263fb4d60bc7e3e64e6280d9af1efe1fd8af08dfb6765a77f8f32b880ccde82d029fc5a32a940909a7aef2d7eea7b74c4a4ce06404e5757cde913901f3505bcea64e3f635d037370d2a0d0f71698023c06a8f97bd2dbcb19f6f4d1e04d1d88bcf9cc6e415eec899f379eadb2442ee3accb045b6df9db5e82f9f202bebbf9182e2f9493b5c705ebb1c0237ec4795a601f7a6e8ef99958e39bacf377c8566e01c26b9e6df4df43b7320eed4a06fb9e96a52a58ffadab4576dfba63c008b3ff69a118c019603ade1535cac3b3bc12bf257d0d3037074047b55363e3cd7a05d077302c6a2977d194fc18cba4400bf88770018e1b7faaee6182c3ab71bf0e9f99beb6f2b39167dc426cd4d7eaeca4bdc8621a984f85d7a05c4ceef94411562af45afecf3c351b3d4037a419276b323bb67460a77b394d1324ef3eb59e9e0fd2cccc813cd9cf7c80d226d5704926d609f9ac071d8910c833d8d69465e183951d2497e197e8f3db32d980edd00dc2997aaa1b600a5e3e621601a5029c2a92e498721c7e0ee9ed1a1226157b340f0ebbb181b4fdfa4cd5eeafdec9664a9426085dd7a2ddbe8bf7065c05520862d7881bee24b2d333b9522df21da194e99cf284700b35fe18baa678f1138a7e69cd26cac7bba4b18bb122bfd3174bfa6ced29c43be1794f3dc07d2b38419cfdd34aca4838b4470325243645d3aa5f2adbf57e6bdc1edaa62f0ec0a6ad67892f87c6bfd892a62039f273b0405a9f70e614e7fea358b4f2ce16847eabed36bab4a95bc0395fce442911c89c3eb6e1713094a4f9b9f3a56a9de81c4ddec2cebea46071ce577fe158f2a1d5466ce896fd74da7b78a5d2422ab94d8b2deccb823a630404274c57429ca88e52856ec36bf14605b3f88a2f159f91fa83982a4016f69493f4d9c01a149f4235f01826bdddf03973b980c351c961e1bd0cfbf45f15aec3b592d96543f7977cb8d4b45fccae486839e116eee6e532e157ca8982dbb75e755adca35a5652d6cce141009921724da0b2f5f1e88ebb42428111478a15600ec8e4c2d223c09c97b33607b05e984e7217a55f7776b3f9bc8936578f5efe4562dea3d1982424a62427403fcb2ad30b9ad8a808cfcd028e41bc2811d2fb597861d2ae696c8e6d49a9d85d95666db86ee26030876f1edff540c5cbe8e2a9ea38862d670359df6bcd6df7406d2cb23d9fb770d806a08c27002383d0204a20ec69178607820e43ac818f8c91019adf5ea3e691574148f2f5d678c94191982f18368878399c50b744aee6420224cbb4deb08a797bfd56aa3efe4fa54f5c5ff573ac1b6ac64a8edb9a1f16bce8d578ec0f5d36e86de7a31af23e6b1505f8da0fce9a587b5808e29f9c5532a75b69fc05c6f2c1c8c4d12455e43e8db661c66a33cb29edd065f33ff1157c6c72ac9526bc2dc8ecdee4b6ff949de5fb58103685a5c8346a7e201f74675e790318ed6a07ad567273a64e3893721794eab2cd9ca3d78648363ca63efbb1aca57cbbff3b38ac584a301d21f40c6d3e6bc661d4d4f96cd162eec8b2275a1a9536bb8fe4e8e3631600f6721e8c7e881366958fe0c394bb8c2e0df90aee731859c67abd043cb1e8dde8bcc928ad211aeb6c32825dfad9dfbe19f5240ba60aa6b6092557e05901dd03b6db67f3f12e99e46fa702671946b493a480ec4c13beba645b19c5a71d03a24a141645df8c85a1cb2e5a55bc9b25b29288fb48d854e5c206d6f5056c04c92f2df9a6e649aa7446a8fbbc013a08232999443e18f1ecc6aae31648b8261e5bc4d7afbe234807b2d6ffa226a1c7911b840648358763f90dcf9f774b130f21c0c00f4072f1f27d4a801fc3e835facafc8395bffa2bf0c510d5832da5e3e23d389a360644c86efd26a5050b5a92b83d65aa44967283d992868a232536ee4527c735091c10714b8f20a2297df62c1f51631c28ee6985a9df0c3a872722efead3d66b0ff04ef9038d2018fe066e4ac35f92654ff27cbbf1cf5d067c42f02267854a8c04a6defa3291af7585ed7deabc92479d908c91e605cabec5b7cbfd75caf2cdb1c88490ca136d7b55380ab1620ba1ca583d32e89d8667797c46956fd1c5abe7da361d67b02f7fdf59e540d73931ec578d936e3e3df909ddd8084dea2df604f1b90c2c112170de71681e359e31b1a915c1bc2a272bf26c381d119e488d9c78df4d7c4fecd275bb1e47db459f6627f7da5d24a14c4426ebb01377999a7ebfb8bbbbb11bac17e03ab860ee4cd5bd5e6196479abc369a47cc2c16e73d55bec5fc9397e03c0bbad28540990b5d6a6efdc3a7c9e23466f71cd1a92765017d6b4229da2351e95c85a70915dad1bb9c08396164a636f7e355c62f71c9c1b2f0afe2d1469c35e3b3ae7aac6b35bafd27f4cd6d6949eca4a8f7fa88c2f28083be3d3dda1f993541ca773c3ba449cc14d6d9ffe7e318e8887cdd1d3afc642747f762272b9465182d064e64be43131dae34d38bb35b182caf998cf918aad00bd09d5986e105c1b0f020dc1af4b483994146a8a39526ce49e00ca00695b406e962328eddf3b5599099735ff54677f8a6e0e6358dffdce841804f43651897726c128dc45ef912750a238e78db4cfc94dae2dd29acc6f7a2bdda993223a234ca7afc56e53dd749762487498c10b9da3f5f0e0c8e24eb4219ed1363989df4f33b67c0833f78ca30d380502248e4f7a29f8662f932fa90ff64b0a0d6babff78f963c274641f51a2274e070552d67735593f7b766ed198c74d54ea4bfc764968a18994c469eaa6aafea8b6912d4371f8175481d0b5d483710749c4a6d86e8071ede3aee45fce49247976662ce5e121866cf9af13039531617e29098d792b08d5b63097b83ee04bf7758b2b9df256cba121d74d6ed78e7367fdfa0555dba4b61b27982cf60ceb3674d4f7bcb0adba3b1ee2a32bbf98f820e7935982b765531e5b84b7dc64f5f22bb9e59181684cf9730babe6fe38bd4a159cebde33dc35b8ca7ed6cff60d844b5c1134cbd4ac1bcbf04f5054e0d58e2cbd2f16316e64a6720754d2f7873d7012f0823cc3594535309ac799a6783a987a2619ea7ca725d1c123afa310b0dae14696a8c4edc71cbc19f9f8c4273509a8475b4446512ab2c988fb6eef7aa08a5b3a1959e0ace5eb074fac96911694604c8db2d69ff1d43efbcbe673fd7d6db2524208d0ee61aab93aa17512b68bdb5733925b4c0168d3158ae9463344636a478e80e4ba0d97de982690bb54b9a94f16543d0793ae8df38f5f174c495dbee47eb98fc2dea600b080c9b2b7446801c7a3c5dffac1cf78de97508ccff81eb00ee58d9dfad9fe8184c05bfcfa958850bc57a4ea9a863f35abf032af0f264ee45f3ab11fb8b5c187d315791417a7fc490b0ea387e0d0d1c572b5d6c5146f64cf630532f3691e59e9f53f69615b4dc8988aca0db505c470c7f7dfdb36a267698e9705460870e31f1a24da92a91b7ada77dfa1875dbbd8907c34e6ab31bcc9cc23283e4cc6135cc994208793d8b271b4ff1f043e5c5ad9c9d532768a868d92c992e8893edc086028ee55e0bfc6030a83f2bffd8bc0646d616d9c11c1bc1bd5d37a923650bf4eb8379f9db1816a5716c1c76bb029709011e5d9cc4db2cd6dc9371a6a65fe1f5e9b41eec83514f96c323502d4b14ca15eb6e31b2980b45f00640c24af432da58f37edd34fd731fb8f491e10fd6d685291ea846396230d5989dd3f3f85621869ce58f36dce76777146cf7d6bd5471c8ddb9ed03dad3e57da8839846a9fd8528674b28726c66597b5e9cc22c607cda425126eefd88583a63e1dd456269fc261dc080ad9f4ea8f50186ba8a69b02861456fbeae17151cea196785379154ca5c250749161b2bec25fef7d4547b91bb5fa0d75cf5937201da21c1fda64d75a357b001228c0fb25c25edbcf9ea679fd2d578d9f8fe70bb3a02860413135a1b2ab4935f0c603855da794a3169ca206bade4c7b1606b2817468e09978c2dadcb0de366272bc4313409fbca4578304ce416e79290c30581bc8785c2a5b4d80269198c7b5d90e7e8bd35759334b3e70acaa6b240ec74c21ec488c9e311f331209853c57f66e0b0fc8ec0c9f33c7259c13a5546365878a2c6fc16b3e7cf3464a5c27a9248b707deb38903ddfb4517c20be4fb1c0dab8a75c8abab0613ef04122bc65fed14d2aa0371352fe7b5026f15d61ac950daceff9a69229308f1dccb829fe3d1595316cd57b8f09e031584ca2cbbdbf1933c4acdb8b3b58853947ad27e6ecab7f61f537d7417819649b015590c7ab5b15fd94107575102ce1c6bcfdfa713140289313821786eef96729dd8eb27ddab98519c7148445a42502f7c7889e0e7736487d829ce46acfd685ce2593b4a9aba3e2be26d63c8ba071747e74a0e3c7accdc1244660c3017036efb38b83e847a72bd4801d2951a4a21c165ede0b9a4b8adbcdfd2c57f31b8d90dccdc09b148a9e15739719a72cfe432f6aa0c0decff213a68dadf6037c836174dbdb07b945bd834da403a84cc7ce4f9344771dcf503288552e5b9a8971a0807a51000edf2c62df4164b281de0c20d75bad71b736fc823e6852af06f52c4a7152cf3c7dea700cbc6fd766bdc17c282864d9e902bb05388582fba3dd51e45cd89310bfad85883c9676464a04e2966499e5d1cfec1c7acb2264219e5c1d3e732656b760c354bb3637d63369e951894c9f4bc13d3ed6f935a82eb65b687646ce04daf93a6f617bc789a8de14ac1281d1ab3a86347c844e4f378646984fcb92e9a3aba1a4a2a58ef926bd096f8038cef4a5003d0c766fee76f1e1fd24b73ee469fcebc2630b5b61e24fa80819d0c6da6150859c6be122b97142b5a85509a0eadfd853307aa5fae1dac276b515fdbb71ad5e29e481392334c9bccd365db88e04692794578692b003b22d5e41d5534954f31c3cbe849a83c1f4a27b0605d6f5fcc469132da267c343f05cf03c54cf0c2c9e13e3aa33eaf0c89fe85c88d0556c331337b77a98374db59861deedddb07349437c89bb2921a2fb24c57ffee844ba09f7d8c4808922106a5c6783e275c9e2600ff58284919ef924fa6e5e4cf3f05bd087af998174dadc2c2d53982d48c3cfdee5700150259194d9222da67cb9e4c874c4e2f16a61ca666f6d85358727b5d34f9514f2b3c94fa4d1e94fef0d3085780a2357b7b4b7d466e8beb5031af6ef7505f9c3d7644929fdaf31a60f906efab783a4598b7c18459c9273dfa90dfb8eebdf8a5c09119bc962552628e494033452d1ace703fa16f8038ad5b4f13205beca166fe0bf666ec5bf07044163f077892594cd25dba2544251cf151584b6b05d01b615a3a435210ad2df2bcf71c455bf9f37b8405a951229b51cfb458bf74077c76b3742efc54cdfc05b33220661a52e7201b75946d052c27600b8d097969314902035385a5e231f51647d368b77506fcd0188e2a833f0e7f05bfa68dc72fe0b30fa31d88885c4001e380eced45c3d29a0c2095dc2a15b488c54fc229417d2a5b7f70df295e6efe387b0e4f3dfb0be54cb6d71e8da6ffa08965667424feb92026a1bfa326268c422c6c37f26c60df32aea741391b10c9181d9ae74766fccae32d07b97c47ee7c5c507ec330a62e9bfca5eddc8584cca2a7f50e67a3f247d48fb0c123091a3a9bb0ef34155af4e8f00313ee56df54c6911e4189aab5b039e532f59aac304e2ad1daeaa416db83d28c93a72fc5f6da31a38ac65a2866ffa2f93b3454cf7dc6ccc29ea99993cc34f04a1164c0b71844933594623faf2ac630fc54e43c45f9bffdd3b938ae2aaecc19231cb40ab272ae0a0ee73a8678b3638a49ccbbdcd1fe210ec43c60afa958e70ee344690173ef7a2e991656371a2a9aa569f500c35a3c110ec55c661f34b1a6b10a9faa2443f87971ee09dcba49cb1b31cceb5353e1486a5d90a60711b276008468df5544254b39636a829126639daa4eb7244bd67b1f093e02a433719f21db74433c976e6af6f9c073b217b294ba2f2ddd843dd409c3833b2c1890ebbc5a7bb445158fe936119d2d367eb4cc634a5c39724055c7e26eb215f473797e3785658d1e34c79a693197f51e822273d0807dc25a32c74f6fb396fdee5cdaebecf154a1d093b18715a05467947e31629cb36502a5910bdfc63c94436d3e5aa2d06e1d469290df1fa5e92c610d2ef3910ffb4983100c21ff3ebe06fab18ea06a8181f610cfd156eb566908efd0d834ad7d679d2a516bd2d20bb9bf766885387c86f00df9c2a9306884833e386241c8fc875846e6565005949cc3065525628e6af24c05736aade1b933e700eb105dae6ee8ded902e34d9a57d8428949a81dfb0cd2ab5850f860d7d6910131960266fde6eed77f268f8e1b55f40cfea2a6243033d631d7eb5371304dd39bff262d139de79c9ae8817935a04e433e5e363f8bf32ff42f41bb97e12a87df66ab3817d4fc8d85e6b85bd2f0b1fd99c698d635b8d038052001f313b1c78d155e3c4dfe27aa9718fb24018ba69c585b2f3405ae66d916b69afb1eb1ca33922f56a39c13227307dd92b092dc7076bd7c4f5ab14bab31f295082cd5082cd6ca4567d71d0f33c27e9b51ed005a24de8fb1af3b48917f96af89b827ee4568c92fa77a1d61f3e1112863b7c38725ed7090a67b8c0e7ac812a6ec44dfd413b9825a4320cd092d7544791e94913ad63cc56b80231dddd1369a013fe68e1a40e0c4372d30037c26d4721678d9e751be086d2126f49303cd3290d686686d24ce894e6ab40b5b1a1346cdb114554e7bfa33b302a927907ec38913bbb7ab0b1ac5b2956e8d84d4362bec453ecd959b21dab4c26c2ada507bf92078d07e1c5894bb10415d82f3916850433c75f74b776b7099f724225ad61180c8227cb4de74a280468eec5dc747e00d36d998bd2825595d820eb163846278bdeef262894813e2971c7b07426844791ad24f6ed93fbb4ab7095b17ee13843e077b3865fce51e75b5d8dbd2c68ca66c07ea53437c8a774a33e8b343b0cf1d57bddf01506592c51c25ea6a5801fbc8be584f8b58a7fed58e69a42cd46034051dc9d02b7507067751a14c8c71e7b88d0a26bda81dde376df74c031b9390c7dba820017d49f0e3eea608af5b40db998bba8f4bcc3e321f0ff6b787b372c65b046c55d31b063cb7c3aa8ded49261d69ee0caa6b5c3d067573eb7b78699ecce3f89fe4d909b0d0d7399a967e1eb98274b69d6f23f3bc6a071f37bbc922930c73a2a1d131daaad21ee6c6f4896b179f3ab5b30a4dff66308f49048c76480760e2a864788a91f7dfc61a0bd0ca3f6cff01e780e698b9e3d126e72a50c2b16b97d72cc3e3ffaa0839a5022d0d339d005e80b565a43c6734e299c619da99c70083e8cd13f3e6ad5f6ce814b7f0539fcd467013fb6cfc666b23d50dfee6573a51454b296363d0064d079022b92a5bfdfe1033afefdfc7a96825d5d75a4c65c92248e59b191075651ef1b2057b0fb82fa6bd62c860c3791e9074336efae3e9d3840e1d286a4d07c4021347975b65d7446f980795dbb4b00d8ccd92a67347b36a9c767a820dc1f3f9f14a099b298720317f31f17ab9aa4cc0bc0e320df44031c9de5f2c9975d5585f1f6f93a56ed465a1180790aec83212236ea84e3a85f3be50781e4b300c5b047f0e6bfc692b6888081a43263ee4178f63022f4eff9313b153e115558916b2ed0858cd99d65123e59b9508f44d0564f61d1e71b174128633ed4c06f7c240e4db9f15627d1242954344c8337ddc0b9bf5cc3f3f849e1c58f9c9f8fbbae88e034bb9d0f9c6fb700d3f3c81eee70f589ea35034c966f6d0da30a61a1772b0e12b1cacd27ac27006955c313eb656c9ae0823fd039406a1a4f59ab53a29b4345bcecb8cb68194962afaa9589cdf7bd2ffb385cdd8a37bd66273d87b68eb272decde294d8797c51755bbb1ce98ef75ef6ea3fe0b9e90cb0cbbbddc101d502af9271aca6f1c001c54443d4068e8ac02893ef78ff60d7454276a1a96ce8be1ef4c27376e02dcc5413f08b2d5dd5762ef491e0ab191f288e6f3fb34a58ca6f50c5fa1a01d844862fa8a5dbb372a472a29a7ed8653d08d39a9dd18aad0c7439039bd33852918ca011a029ac178a2a815226e8e8b90c6ce7e2ed3d43c121c0bcb322e0f4cc33aa05dc516df6048a65bdb3906e138e0ee8686f1c54391640f95912aeb4662b81a113b8de8e8a5b65851f96f97e678b000e6b13bc6819b93a29deb3199fc372a53ac5d23ba3e730c28d705ca2427cc87578142990eb1fd26bb17bf26392ad03ea93cf40f359e5a631c112f25bfa32f74e572604fba53e5b73110ea9b42b7e60411f10b9656c5d944a9e9a3c2eece349b890e5f830711bd129d1dcd5f41e7782d8fa70460f56d13971ae7e9fb3e91ce913dbf7e44a9901f5c713bc481b9ed20f3f1e4855367caeb4705398839403cc631b72364a46916d30fb02966da979c9ea5aac7bcf97da339fdc08c4e00396f96692e62f9c6986fff9f46958699e4e96c5a77260a01f828b206234e4504c5f8c3275441a86fc9a90043db5443775727583950dcc568506a86bbc0a20c3fd05a942cd217ea8bcb2afa05946d60101ee220430cb116d6f3364416b50cb33e55f9e55743c80efa6bc1efc1cf64a4c85f60fb7da88db2ca24b13323198ab20c80c6b90626bd514d945ba959ae5fa5d2b008dfeb63cd334649253bdee147b0a873648a99ca615ece456e6d85080234c4398c02ad9a5e2c5abad1074070b294d9b16ad8c71dfee9b894a3a203e87efde97a322e83b0ad0bc04287e5693ffc0dd51c9542219dbaea1dda7199e56fc03898e956f5850dae83c4bd91263269c2499e283e55fe11102385d6dcaf235f7d3aca38837148e61eea3608b641296117b8256c87f41e130ee5ed0b612aaa4530fb679081edd3a935a29a66e4636cd886aea80b44c5c125536252c2c614b391a21bf598283b581a6831d58607db09fd87d8e0f0964432ff0206d9f0bf29f48e82b54818c7830064e7364b8622d228148d2c61faa377896eacf8621e04e84cb9e5c29c56920a3e7c4133e6b60eaacea1badbd922c672987bed670b47e2294632a7ff313684675966f132207c17946381498cb2cb9e9e11b6911308c2c6ab8d115e155a9a65faae099cc5eb2a140a222556c4069a08bf0181c55e994a6c59f6a3fce26bcbd4ddedb5ff9f1fdb6c4a622d08c19941d4f6a49730296af0475cc071cee25044ad0a59a88538c3004f88309b8bf56c479b7057973a07921492043a2e0362c2c5a44b1e1f1960ddff1764b8d4e612fa0156e3ae712c03febea5342419ed55cae6b02ac635b1db68ae489368eafa943bbae10af93312dbd6317806b7e4685ef78b0109fdf5688f0f0c8670c17b8320a0d2521dc3d8ef9d5590c8431ca1e95b770cb88189d75f26f448a3e7d60f44405824ba82cc48daa805c423edf2d2cebe504872a4011c23adf45dc3b6c253e9c568efcd0f89ea398b11a117b86e5c72f13f0ff3e5f58c24c50d50d73c9a208f09399586c3b85177ada1eb97a4e10da649466e3078f26c3624cea2f8e43ac2ed00fc8e3215f812317bbdd065beed93e0c27ed828a9f7c53fcf4c7c5711735aa12ceafac04d1b720fb898d1b629eda2e2a208c7defca6676eca88913fbeb57d2529f9b28c269d62d8b863763ee3221686e04aa97964033529247d7fc471540d6110b5576d4b5007c699697b240a21b4eb69aa3e3c250c51c4152e16bc5afb4ad37904c68597403e6d7d3e22b4ee2ab08ea52be8ad814a84c9846ffe0e7f55c22f4b2bae688a984aaed56d19b1fe1ccebae2c39b0bfc8cc233ef9c8425896fabe75556277e3312f34f9b3352396c37e6304f25ace940abaf0559039dce13295b8dbcbbb31c7832650ad9b1f75f4f3619f8278c202e1aa8f3098faead539097ee595a10e651f4c6413641a69118f9b04ef64d807d6973469fbd6195d41bd74f5581df027104198177ece36bcc9fca295d8574b6d1409f4f0d5886619d9b05b7d0e64565616cc63e14448e9e38ce53dd6606dfcc57ce9ffeedab387fbc65081c81c31141d88e8d7a13edf29bba7d7b3afc009b91f69802e7d50bcc5437f3c2365e5e9d51726cce848ca9361e7414d2d03b373a7a6c8d31e11935840aac042d427915541a813c75af0790dfd420c74ca573e9682e68dc89ee80ec24ee929f2f75ab4b08e50a5ca9fc162d394e8130295d816d058c51903e5c570f76b8071db68d82c26ca7944d279ba8a665c1c033586aa07dfafb7746d124ded53579fefe34035d76bd6c6c135e96271c3dd41e897e98dbc699400b13849ab978e50641fa1fe80defd2fbc77e625e884741ee44ec86fda946c2e63296b8395668ea9c4528845aea9a73010dbb9550cf8504833716db1f6202aca0fa5d666588111a6726c01fef920ff854b2be31e95e0dc0c26bed005438bb9bbee6d91fa9ed02b1542fbf2c0459ec18fc6153a07248fcad7e2c4081f3aaf467f0da26b0fb9d5ed91ebb4979df5acaa3f88764bd1548347cf9302974481715fd6e7ebcf28ebc5d396a3e6c758a3ba8607154ae7b8416903feb584479e7baef58babd64ab81579a02877563856d536ddd38b50ee270c4b754d53ccb72b58f455d434eb17dc98b63ad37c622d44bdc4c8d42b2e3945b55250e1d296a83b47d0816e9ee9220bbb7bd21c7d7dac5929c65d31659c0490ca5f38d3cecb0b49f5c01c5d8a28746ac65a65f2f36cf4c91cc1c252a56b8c5e92974b9d91abf14f2f66f6737d19823672966ec445cbad25d26df2daac5f90bb05bb72197f327483ebb5de37e6f23370f04cb9ce6676a2d8649d7464e70e7fa3dc0bfe2a45b47e83fa782f6d07b94bb6846fc726648aa835af5df505f997206d4a380e24ce1f0f13145980e0e60f822cd650e6aa5301a8b1b928da1444569bf78b0588d5887ee42f09c44a6233f98fb74c8a29b7dd632bb10ec0caf78ad08e70a163e0e59d643055d8b6c77eac7d50206104fc77df8cf358736eeee07d147f55cc6e109c659af83d4ad22326bd92f53af9771f346e9efb5420ff36262087e0857bf68e589ec75ff47d4add188647b7a2307d67755bb2ca3bd036a722169cf3bf4de44409c9fee6bb3b3ed0659ad207f56f6a5f9bd2d2dfe2c337790ed83c39ea08f5b701761fba1c56abbba62288ec2b9f01e7cdee931926cbeed0ac0af449ac419a8abde9a20e5dbcc2bd9eb5fcb2b162b598e8a741f7656cb5c8fd251f09922be85ce6958de2a1f36ba3d9dfbe7eed7f660f7d28347cea72983413b8f81f57b69761a3bb3f7af730e1ad34a28ee3237f3553673d8da7b0e525a317db7b9cc959f061942508366de5a5c025d1de3e60e8f4f91a581c69feb4ab5f60eec9891397f6a9b63593691a7ae02cca693f3eb866eda8f2c2aa9cf4e533208c29b73982fd8667911fd6a4317fad0d8e0860c8c562f8ba6f6f25ccb313a26b2a3e495ac35f53681bd85e912168792c4a3136168189b395dc04c057faddabfad25f556f72f2a1c031d8d891dfe6c368e4c265a7970b512ff4c6636042f4ecb88d95723924b192b50d26d3fd5282006a3276b765614884a18a299cc712806c26ad9b45e369fe2e23798e03a62b378e5780958c728670d8675c6247801475e322edfd57a7770cccc62d1c7e951337c8b4f8e87cf362c7f844a8dfaa2756ced374f1d923878c4fa6c42c0bd5338e9b1dd3335a4ba753d30e5cafa404d4829f032cecb5258a48bd4eef786b027f93de0006affd41be2f710448168f491180ecd493911f6b4f82e123d9a85a2af8d5470eaa285be41c71cc3ef92d5902102fc74e6028c1d633eaabe06488b8d28ad98a97a25ef3127c2b6edaf86243db9ad68e2f7e5a857f2b3c2fc079d234b2f05e023b6704a4e3b76e2c6d076250bda44e439eaa1ca4d89d0bd93bdd2e270fe1b9bb68f4b26169f0b2ce1697a148baaa894ae8565e6bb50def8285ef22fa689fa64e408f5c2dea265e6c634c653f2054bb8172b83b056570db14edd56a6ae73fb910124de2645ba3d77202d2c497c067a5c5dfd6d6268ebef73a9193fa2a7558d8f9c837ca034375b938cffb1bd1962e1ba673e9b9a471bdea7073460e218493bcd89b8db7d08db57b2df304f4ff1b540b6fe00a66392f9fc9d392c90f00566f862880b886fc60a79ad69761a8a48e9bd76d853542b15ee771750b26e69445aa362ca5e1b2077e9e2f68e064dc1b032c9b0e81408aea1f36457ee45feb43f36b68707b7db4329f815cd9264c4426cfac90845176b45cbd154ce4d6c4fe6d4762765e2434967ea43b6f824d3e4e38754361139bd75f45829b8b51c4761434039ec431176b23b2c41ebf5aef1bd673cbab6219b0f7733a95528ac60f5e1e5511b5ff161def464bd57e60daa2d388c9d6b0df9ea586312d1e9e565b7a1e9ed75fb2e1a22363ae62d34de32579cbabbc206cdbd2305e4a57ae884f48756c034eb58cc78778709a54b0bd78ed7303eaefc19cdbc89bd168e92f4cba2a1c1ad2f3c76748292ab0c957197b53e533836d2732f4d07760999a181bc63fcfaec71b3aedf829491be8e6634899a04e16a42c3853268e419410353f902940e06261312863dab14544023f7aae24a2decaef4899d3830a73dca1f78789c8137944bc6a0bb5c459e830dba1bc892adb860fc172511de3b992cea440e608629aa19a89230bc882c4f1bccbaef0502138bf19d1f85cdc1b2f2e2d3a0b86acee232ef07761007abc9f032a1584226119e1d3355768b0c79de797cd2673d85b1896d03a685fb92d3844cc3410a8fe95f660b34badfacbb400d9e74927fa12299085c0013f9db26e7e4730657b34513468f631923748e486eeff792d91cc1fa49a0f4831749fca2f7e90cbfb9ad1d6f744ab0a70ec050213f013d214be30988e7142b87996d3603aa71458afe03c34ffd128755f9da0efd02b0be74cfc7c352126c26bbbacc22a4e9f8e7c54b7f82c1a92aac5732fa660d4b87b81011ada8704bf042c9c3cce684a9f26a858654d9532f9deeb2a21c9f49f97718d973f5d4a7db29517ed97d53e8fbc79ca0fc3785bba430946dff26447bb386d3ea2eb33e4a06f5936c9828628329826d69667f90ca833acbd09300a66f72dd7b0b3b25bfc5fcb368749279b35da8a094230a9099b258e96b053b8cd71ddd38d27538264fcb014d9bcc5087161165123af8751dfc78306861fffa562ada37097647af4c97c8931edd17a57beacf1bccd9c19ab77713545698f82fe06be0db715626d2f5d3cc26ca335f0e8f1c39f8bf19fb273f27e460ca3c76700ea7d7f3af450d83aaab75769e8c3900f7300195b3aa14867cd8b3545ba0f229ce1d6c4daea4332e81a09c22bb4f25ca65f5ef92236d0be6cf82680891fa0661782911e2994aa340faf8259978255245af42f4e874116d4d5bff848484fc91402bc213078244c06dcc7644b517313e6d7182228495965fda2056d8a3121e8e24f41d53fe67f2d38c9e64656af2d322c060db14d512642599b78b8d641cac08b19232d6daba8cbe3344d0a9cbc5cba4af5bed9e4eb99e7b4466c4c3597568ea85f9f58478472c77b482762cb67e6dafba3e601c67abd832e050551e50332e5f50d4ac5933a2d6f0d3a5d13b52487e0a7ba2135062f8def1a16ad81087191a67ef4bb72ae2c7f638c36ba8813fff1c2b3fe30e6f5251e43552f8183b7c257ff431757ec2e99d3c44fa6b899953035c54e6beab27945d99963ff55e13e9bd957696d9d3547fe507a28f221932c1d3424b12677c526650dba9319fa19db405a9f0124106bea4090fca7da292ef76977bf923a2d2b94cdf1428b2ecab57602db125a56bf0942acf26e2f8aee539f231fd6da8c80ff384e2cad440b9a37cb2f85f62f06338bea9538beb63eec290fc99a9c2d67017483a0396cd99415c471037e686f74a22cd605412f5442133a54e7ee618ab3bff32af9a402fd4ad6e96e6a3eabfdcf143f86107b73a395a967ed79bad251db8549141322b5d6283cede318e9d3561288c0774c60454ee7c4e144e623f6b0f14f5a927f04d4f5a2bfacc611d79efe06f7f0139dad377d0a7d618a9b7d1449e43ae59f410b9c1a3af0e3aa83d1b17f7c1fd13343f0a0bdec05ea12a97cd2a59ece2064ee260ad0fa1ca825635dde7956aab8f11c0327051086048eecddecbba33af92230e451c7325c0cdf85dede08e23ccfcb79e0900a669b58c77caec7b1c2d40f2769a52333407830bf266462ef16b0a97d0985635cffeb0a2e2828077f204f3772923c726ae3542a10b5aa5f3d6c3d1c6f2db3b8173f452f53eb3acbca44b7f46c528872f4158e1b80a5334cdc03a0b86ac1c363d776ea92a7beff0f510a1e2a208baa91ba424c0e5622aa4058adf82489eb042f56ac15ec6c8c15298f76e18b3a85dc9ad12022d3961539a5d63adeb1175ceba2d70eb15a8f8994b55ffee1d2856fdfb1cc65d0527a32c0be2167db2d479576ae3b7fac0ac8a946e2f9a74b0011890594112e5e8b744c3713526aab972a6324caff20ba1f9f872b9d859a01c95bd0a87e2a2ee7b668b3f096c2b09e346bdbba9718a1a644d5dda54d78904f1b681767a76c90366992cc8ae25f3d3cec9431e26c11699e4d469a7f9c420987eb5d655d7b02167419215e2cd0513dfcfd592c2da68faf55c9eb2d7b2703dba16903320d3d0adca318d20e427bb8202abf02f6447730faefe5f813b8138a6eee5cfae4680adce3516f9498fcb52f63cc2405a74274db6ff66ffb51579f880764282d9785ab9fc86097e0ca0e5704bb160ebbb0af980b2fcde5c6d22f755b635f1912a499a71876414a7870ef3e273016cd8a64e08a3af7ad444cb5d53eef893e731ab0f630b4876a7c12510a6c1ba785c8f335e257685aabdcf5396ab0078983a35b0c15b238388f0701080c7d5a60cb6bc3b49a7666957b68eb395dec737f77233a7f70249b0747bf83cdb1f1fe240d3d7aeb9757be2678b07501176bc176b1e0783e43ec7665af7e7a24eda81ac24e959df75602aabbe6c16c78d43d977a32cad41fd707d7c0eff936a00b87ec7379086c305681bab44686e3af96e5009115dd4225d79bfb03488e6c354589ba4dce00241ed78f480538555b53784d32d24802f4215147810a77ef2afc3bdc4bb9b2258b4754fe8a0d1e2ac8ac374b8cd17a83bf78619d607b64cac861c04b49635bdfaa8d7fe1f86960b1a7c829e0fa4044fe511440d9376c3bef009b5aeb6102a05c3f5cd6a203856880b1e2285a09441ad6e99a5d1fa8c5fa772a7c6178a18db7d0f423ea6b67bb67cd2e798b9ff17f52cc5b69e9ed540f3e82e81f2ae4a3a89fd3f8bc8ffea256ea256540d932830b434094e417ea30d7b443c5de1260915170c58e526276de8058c276e1c66690070fd6297145073d14bd0b8650d19679c13fd41e30b91b7c9d71d5355140f957ec4b5176aaf5e06cdea03f9f6503e0d11e67e3d53a145cd065852f792d85660c2045af022129d8949feb7e4b571a4f1c0272f91510f3641e86387b7971111db62055462301b71e41249d3860f4aa671c147859922b9aaffe4515fa9b810928a6cf6eb31bc859222ec68e0bde9c7d95f7f35746cbba68f5b82aef284df6df1bfc5291f4974bb2c6f53a6b4de06565d26bf8e844818219ee9c1663fc9a3d15347cf704f3bc8c3b16d6ed5a0499ab631dad17b385db67f5ee8b95d5408f737282c2401e436d8a3ebd29b96e30c58c14b3febbc64a104f04f76692c03c46e3ba4275e77b1b02abfbe1939addfd57fc95664166e2db6299525fcfb37d5f74597a27cc97abd07ec2151c9ad3651456100ff0236ef2e179a75f70c62c7d5ddf076bf58dd8a085999068a16c4983216d4db959eb141f7489dd08cf4c095b6637a5f3dcad23ed9bb8a814d165305567cb589a01eaf58cd4dfdc6255e9c443c29d26bde4e9cef30d11db5665d0a79bba44e3cc202fd834ffab5963db6d1daf38b86e158abd1894f6e39af445e88fb338bd2b98d7af690a068773129fefe0cf6d1538c2fab51c5fa54dc9522572456352aa45605b71b04ec3bd85b4f6a39c66070a4869d575805efe3270ccc0e7c3cd8e8a97873537c9c492e267e965ccf67d94659e822b798fc443cf4214d26ec071d981ab63181b20cf827732dbfe2452dac746b1de8f767ec305e1159d74291a787440ea2a7514a852ce73d9bfae5c33434bda2c1c2a682d356368e89754ee694a75fb1e4e9b140e2a325c28469085931f00e0439bd8a7c358d7430cc45032de5b7d1ea9f7536b64dd58754e352925fcb88d0c86a866da3838e301324f3106559dfcafecdac74e2815c6b50ca3909795e060393d66e92d668b73e43d4da0b8e22863f7d105a442879e899c65bce913b2656634303f0b85602fb676e17d8efb9e05a24b14a1a79e4ed9cb133351314ab8ebe7f5489c220ad4a2ded294925bc6ebb146f786c48c1ff9b11ef6b055e89564ef0716d5460950ac820ba76cf29ede2ba7efb41a1678c9624e52920643366e664ec931362063f594eac59a7fb1949bca3d58f21d261302e802270936382df26c14c291866a4fa1341bc9ca95e38810cf6505891dfe7e552775eb8785f20722691372f6ff95a0d1df07487b22b80694dc74a8fe528a17d299720c37878876a042648f47edc2afda778bd1aed75ec313e4a40c5ebdcd9a2828ed50656096aed39468f39dd46c915f7fdc466792208fec4705ae82e538c327936f80314a506a0a0d950f5e035e845bbb339363d4318ac4d29d4050ee1eacc3d7d4823088451273929e00ff2a1dfebc77c7e48ea609036625680804e562af231965786d52884e531ecfff2a8cd0511ff6cb3d5c8f118b324d23498c54ad5517522f629e34d345afc76b9fd979fa245f5a95ae0cd51ba121bad92e3a7bf9cd28ebdc857565a64bb6e693f09da3db0af9175ffe528d683b031dc77fcbd2abea875d4909d11f5a1fad162e7ccace955e7bda4643746d32c1234caed4a4084e8899e19e01e8fdcf2f0b0109dea1c73a272faaffcb9b93e761c805c64a33283f4763b742100d2a08f368cf6f1853cf7e8500d95ddad853f766561a7bd3b1cbe938e9540c685c2698a0b25c06c6e5e0dcc27ee079ab2337be8bb84f4fbfd064d7cc6a220a1154ce43395b2a3465ef876502d3ce5470e090a1493d81bfa87a153078495abea5c95710d0ea7ad0c34b33c053353bafd372ebb5b75d0d26e15568784ae013f9949f216f9a130235d4a7022021f76d70e34abe85b11cffcfd42dcff0b98f3a5c3aed63b1ead24b6830ff16992bb61882e62f923ef4aa611bea3df43d7ae450fb4496d300da091794953a8b0b70e23d612804b477abc19207ee909b0b88f8f3bf4ccc34dbd49d2f528b3b1d99058718a3e7079080676ef3dc7ee7d76e0b4d1ee68da4cf6d09850fe055df013dad5d09b96edd0cd8e3c5d6e5d43f94b8199449f6d693b31c089fd443257affc9339e11b577017453e797930b7e37547ed6bdd06cacc2babb3331099dea2fee24d588cc7fc5f0659e7beaa8a4a88ab25a2d3cb18d18240af9c8f168b80f5a3a697b943ad7229b4bd978954a58beb202865d124436fd63bfd9938801fd1376fe16da2f5fa7287e219ca0a6687ac9ca76f0ba52d1b29d126ae56c786c04e3fa4d4f3b9fabfc7095c007dcf35f3aaf5503d5750fb62f8ab91ccb70eb8943ac8b3de7110a57737a261f42a023e1545c999192e12c88807169ce515b3df4c69e95665973b596bfe057767f570b74aa503080a66774640b25642c4b00dca3f4167e5a7481d3555dc46d96d6d7e3e214e39c3c422405d19a568f04c5229d56a49d8dd5f55cc74a702f99aefa33c29a7d15c971c91081d9a93cd2d0037cfe96f1ba965c0a78071527b8021189a866909010bfa9a0925581075f6f7eb6fe7f0b58bfe18a67211b0356c80c8f5fa7e21cbb28142e4dc0a08635911034155645563b2b2b5d7e5a47600d2fccb3fef331b75ea36de55f6eb7ac1f726ba825d7bcd83c4c3fd0362ff51509eb9af46c8f129ebf6c8ad63cd126bddcddb145b5549552ffe846bb2af1638e049c6e0be469f5701ceb7c8a889dcaa3995cb920d938c617ee376389736ae12430a96467a3843b8e6f871607d68af31fa4da8adf70d35a5a6bc0f813612106945d7a0c427cbc169860c59e760c618c04b670e412eb78bb1de21bb70b1e26f40d19c7e674e3a831a8e28b55a36feb4716f61ac5302ef6702c0204f599a968ceba45f47375ac17e7ed939ca61c6108d77b669a80ffccfbf4fd41e8ab39603579cc88351816e111b6480953f2ca88991f944c3ddc7788843276e03c16ec8d1d69cdc5786609e2d45c146f4af9a2c7a5e88ce9d7232ff35036290fe947151fc6d86bd412e5d5a1e3221913d58a3d83e2034ed60b38d65651223eb7ab57ef89e813898d49f1de808c92470a1a310cf701ba1fbb4d8ce0064f9c3857a6505942bf960918e3798dc05aad2811be2a9e42a1fc4d41fe935c5ec39040b9401116208ede462dd383b398d29872e0eb544f1ae74b3bd76bc654c6e14835de1983769f65619301cf31c978563f6146188d05cf340965fd9318872ef09b75989d69f444a8816ae9ffdc6286316a9d62cf1b00ea6712927710dfec3985b63876d53e93e1532efbc3a428482dfc67e0ec9175e577ba15067a0604ae24b50c13cfd3d2e6ee9351bb7a7d841366f64a0f06e4f2b9080ec4f31895b8a0ec6aa850c3b51c6d61dd4547abe777a895e4449014e2ae084c46a1cf8f92f34559511136f4914fdfa53f43c424ebc2e8f6d7dc7b99acf6520d7326a3febdef9957acf6871f79f1f97d04604b2516b7ddfcb152c2dafeb0af4c5d1961b44378eaddc32ce2b296bb4f8f70f998f61e151faef9074b489e4827aa11e24e955490544df36c222bc88159630c79b48dbe0cdd4e6786feba932d8f809e290f1a5c6059520e8986240ca2b040bc0630460ee0f415501693132d788cc47034552ff07a7068f838d8816921d9b90a480a303652aeeb9aa5a0cba2bb89e8f0477e46ba18a88a975ef6a1588dbb792b6751d88d8dcc2c190761be040c77dd265594e7a47a2486a339fd6c2bf0b38403491ef5120be6970823c1b8804352cb9118b60af65bac2d308547cf8a2a3a2dd612f5bd6495fc19a926555427d408b9a05f7ac1d4298abd8cbe975aae2cfdf2acc66a7ac06c6c2e6ffcdb7427f7127e2a15967eda9d1f6b1efb174a5454df33ebf31834d2e475a924e6359b92b0f58653de279dcb7bfa4674220bf52191ec044fc5d03ec5e9275205d8ae0be15a271b502db9d0a5bddd6157a6be27609e2c6146b983265e3dee9a2db24857f4297d3560aec0e6b20e57cba8ae31f93b853b07bd0ccb1e7597d8766d47e6ec2b62e8e47addeb517a6ceb281037f037606bd53bf7b4d9fee34a3163eb47b3719db6d18f9180214c5e05f48b77068e44325a9e726071b5a4991e43abdb48114f05586ea08bbaf65b1d5ac1a66fef935c3930a65769d28d45bcb5a0908d50d264daccacd14946c5fe830c1953daf239196b6e37c40ef69eb841744f4c602cfa1e75b3262c78fbb69dfd4a321899b498064f09feb7854537c4460867c26743f3c13383a27f566bb21c947a43dd3fb26bdf348938ab320a9739349866e1199b7c2aaa494db21f6af165ff41473a7753b89c2deda9cb2cc67590a7cbb1caebbe38a29ded5223c5a13cd9cc817f973a73cd3732b748a3a49958f2306acbe8c683c3683e574e3fe821dbd78cca9049c90927232279e01dd7753abaa1e4953b8db835916727f9da3fa21026aee406b9648cf453f72ada2cfec1885959f49c3adfdd2d6c8807e34ba4bb21981ec3e7fdcd07c264a038b642d7f6feb6f37a8ebf634c355b157d01f37b37481248e810be8b6c5865be9ac5c08fc3199c9827d537afc44da4ec05c83eb15b0babc485f99c68336771d0d381e32e1a286e706293ec641ca7b34f595daeaa8782e8fd2dd46761831599b6f30c39619fa7c94314811353c55bd7397b944d42034b30d21af7ed501f8d673547ca5a66d78c112fe53b7c95447f1cc420c178bd137d00f848b8c314af94d91f2d38e8b80062f4a964a72be261b4ff4d98146ce0ee9187f51faaab797718c39f310ce7eb8cf9088fa94a25c5b9ddcc6e73a23bc601191569327fc40c661293203bb341b2a05e6174fdc5708fed37ffd0d460d9b40c4cf38b84f28354885c632205e63aa148d40dce59d35b964693196df0b23e6e59da13f4ee51a5a2fbda2a46b26d2c1023ad3049e43d259f00090eb5ca462c0382fecccfb3bc8fa9a17369c382b9044edffbabd296e0f6f64325ce985d3d3de0a78093cef4265058e34435f1475f4d338c26d5ed488ec5bde3dc9f44e4bb5bb359b4142290090c8d477ca4e2017f58f5a363f41ee42975afa382f56ec43169ce6d3a354bd5e81bdd494e6bc207c54b2dd0131004155f9b23ccf5cbaa9c4a7c2003a7ce2c258b3fa0cd591c4444c81e24a96b89f3e0596b060ed75b3a666b147480bf685d009f9f343b4c31c3bf574dd9f588a723d69a92d1aba7ffd9c93fbe0c70bb5986a7f6db5abb06e01fa0639cba18624aee98811f7763347e752251c6ac7b7190fceb7de2689e5df43843a37644dd65bc827d71dcdfb479b45000986cb2099bda849b5c24c8f463c91a7aa8a02cc783cb1b7b7b77aeee46371dfb1f3285d1ebf42e079fca054530285fe0aedd28af7d3ae6675cd0d953ee1c9ed561e36a94ea30e4280c8db625a509886fb389a9918083e809a984bfe3638cfc74641416e46f70061d6d608b46080f0617f863e4caeb12b5fde3c2f4eedf8d63927c198b369d0d443dcc3d434c2a5c9fe673739265595430aa1f16ada43d10da16c5308dc22f9dae651daf948f03dbdbeadd96fff5385f27e817c920567a6076ef2a1696d848afec50fc1135e0c24b91978a67295be95de58abe17d933e1c92a945363cf31128159c4fce97abc494542ccd7e53e1cfbb9b0aba3a1876541661315072f8fe7e1edc76d3e21f77efcb8efc6b3047167cb931fc1fb49ba710797fcea7ab135c9d2e93cfdfdd081dbc6beecbd2e5850a1850a9a7dd19607d1a77148e597c4c1a0fb3b0c69df4eb06bdda38834b0fb1e2612644a3364976779848a6fcd4f60c4797896df4002dcd56ef7bfe51d5de9100b15e147786b4430368d73421897d405e29aa336d2e8edc8d7c4111996f9ba294a46b66de7078f3a0ba5c1d3607acecadf590bbd0ec78ae6563c3c05a5f12af3ee7d5e2b59105c51cbda2255d96d809a374f1525ccc87f7f560843282414ea107f7e507f45a6207e2f424ae7f7be774457f3ddedb11a19edc5470bdb6bfe28f5acc6bdcb180be427e373dacc2a4decab3965c6c8c12ca0b7f36e41b80a749f677a6da7c978be1d08adae4c41221fb2e8985e70710698e4e4bafa4e454815afc6706dca5650b399ed65eda7686e4d2e9226e5a7ad597dedafda00245d67ea10b3e0577e22f7d425a99520555df240b1ce422e5814f691c3953baa4968a090072490b470137bdfd36f1a69fe56f67891b67a109be900e5b3956125748eeb261e9a59aff43e78cb7d1c78678f8de1664cd24620d17f7b08eea1ecdf3989dd0bd6cbe65f656e0666e1d4b9da534fd31c32bce0ce09a88730f98eb60ce0404e5d9e7c679684197634199e5fc87904090033c5f4227c05a21323b9ca6a967935315a93e5c62b2c9d93fb77875adee72d1dfa1ff0c54e99f95f51ea72161a5d342baf43b444544a82041f70626a27bdf490bf663e0bd0c02c3e58b3aad8f09dd7179105e165c1e00cd668ee55e68046824db6e87ab8c8039e2f2151d3ffc90e8ef3d396dc29a822c83136227f6af5f4c8a4629e556101884d1838121a5cdde8b7da9757739f1508ff9013e6f4cc5ece012c0dcfe837e4c0b3e61b5c39ea60a1ef53c2350e639489715c26ab4af845d1937e3e55956aa124132fbd4bd983ab8a2f18568f8099dc1c41c93ee65f1c7d983d7bd68286af18f4fb833f14ed193fc6d4c6ce8bea7a3b770c308daedede36512587e172bc23a1b39f71f4aabab7ab6e4f471f47671e3fa015fcf6c0c690e96c8303a7f3d8c71443e6643cd1e3173eaa761dc87af37b390171c017dcd4c4459d8a661a6f087bce7435f64c9045e14053280074d2e8a4e2a105bad2c486540d90fff8e9565b0b827da9de8006b8c8b3ef4a2300b8eb02fd71281dac3efbdd66b251ebde24af780a8d8030381d3a127db273af5a98058f5cd90e45aae57ea90180bcae4e31fff2fc82443c1fa423f8311f2091faa96834b818cd7333003b8dc465b1dd30a80551ef4e896d7c2c61d21954ad7a14da4047af387a53836e06bad7c3284fefac431830934924196050d95ff65bdc1753acfdb4daa24be60ee2b9a61edb4dd52b8ce92e8188151aa544c38357a0850f1b8c0a5e87ba835c02314f0c6333a896d8d336802209e4b2d3c383516a381f316e46bb0e7b61dc1a7c076907090f03caa5de2edea21fefcd094aee704f54272f4da7a24a28fcad1083fb6fa0d0a98a398ef0f5eee704e2a244452d2d549144c4daaf1bf13b36aa141d145991b93e08fca049565928d7c5dbaf5f3130f54c9904521d122484c452fbd35e7342f698736f4bafe6504c9d1ee5a1db7048bfd49b94de09d035cba130d33116e1a64fa1e306daac7b4b80e9972ca3855b1094cd20110314a390533b82b466bf69398085e8c09127561123063dc0f4aa777c43f0bf3dbf1e434407b830bf92e93794431dd112153887ecfef20e47da9f426ca4379fd646f737eea3dede46844423d8a5ca52ce1b2b9128d6786d95a0de0a16f9f628a0f0b69b918216c1c050f0f3cd0ce34511cea09c0131b3fbcc228c0e89aedf5bdb717bbad0eda7fe7df2857590b5a6ff253562220b9af892aa63c2f69ee26dd63dd85b2e44ac4ce5a200997826f201cf799ed7f80addb06bc21d3c1a6752db79c80e2bcc42f1ba0f8c5e2701858c22e01867189a80efb812b0b1ea07441c98b90710484a1d5f614ab100606a9766579ffbc51df549aed9d93b877fae5322b44034e6771cc3b997bd8efcee3d15740f5259c29284005c88d9a845260c73ac79fe631fe8163c0233eeff32c2e768864e1bf2ec9f068108e9407e757e8ec76442e8e9c6fdec2bcbcdc9ff6b5040a97385759bfb488f87bf33a892e8c7d62fa18af0119ef51205578e86ef06880892653cbba2da5311c622ebeb1736fd591d45a8897153e0e4d83cbd9ee8dc622f3e6ead71de075186c8ab124fd3c8d8414f6f2551bcd0142032d4a290562f04c8f1754ee9e184fbe4f919a570910522e6705b451f622949ccf50fb2cfefcc845dc8f524bd31f115be6e3d01d24482ff6e415ecac4482ff8d4256255a81c388d9cb7df0251294b7e3eba909139a3bbdab78e0a5d40b8288ac2ed3df65747cc917a1f464b71ee8d7ef6c65992e785a4fe866ecf4ab2c3a4fd5dc95357bb87d444ecaea98f8493eec11630a75238d90a9e43290b232d625b6a3d36cd9b0db3e20072f8d9da1b0c9e5854c762593bca31fc58a1c324396c9f1b4428dd743420fc6214b5c46757e3f180a7c3bf4db5d7452c25b864a9c8ea424e13342628751a451988b8c8ca882e4d50ac95054e569db92b7200a0025b6a5c9ba1c25e975a81fbb63f235c94ebe56a3a7c10d015e63787dca099fa1a50f1206f5037b9208f64256e5dc14f42e741ad67f7fff6deed81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8");
            Assert.True(Arrays.AreEqual(expected, attachedSig));

            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sig));
        }

        private static string[] SplitOn(string input, char c)
        {
            string s = input.Trim();
            var l = new List<string>();

            int idx = s.IndexOf(c);
            while (idx > 0)
            {
                l.Add(s.Substring(0, idx));
                s = s.Substring(idx + 1).Trim();
                idx = s.IndexOf(c);
            }

            if (s.Length > 0)
            {
                l.Add(s);
            }

            return l.ToArray();
        }

        private static void RunTestVector(string name, IDictionary<string, string> buf)
        {
            string count = buf["count"];
            byte[] sk = Hex.Decode(buf["sk"]);
            byte[] pk = Hex.Decode(buf["pk"]);
            byte[] msg = Hex.Decode(buf["msg"]);
            byte[] sigExpected = Hex.Decode(buf["sm"]);
            byte[] oprR = Hex.Decode(buf["optrand"]);

            SphincsPlusKeyPairGenerator kpGen = new SphincsPlusKeyPairGenerator();

            FixedSecureRandom.Source[] source = { new FixedSecureRandom.Source(sk) };
            SecureRandom random = new FixedSecureRandom(source);

            string[] nameParts = SplitOn(name, '-');
            bool sha2 = nameParts[0].Equals("sha2");
            bool shake = nameParts[0].Equals("shake");
            bool haraka = nameParts[0].Equals("haraka");
            int size = int.Parse(nameParts[1].Substring(0, 3));
            bool fast = nameParts[1].EndsWith("f");
            bool slow = nameParts[1].EndsWith("s");
            bool simple = nameParts[2].Equals("simple.rsp");
            bool robust = nameParts[2].Equals("robust.rsp");

            StringBuilder b = new StringBuilder();
            if (sha2)
            {
                b.Append("sha2");
            }
            else if (shake)
            {
                b.Append("shake");
            }
            else if (haraka)
            {
                b.Append("haraka");
            }
            else
            {
                throw new ArgumentException("unknown digest");
            }

            b.Append("_");
            b.Append(size);

            if (fast)
            {
                b.Append("f");
            }
            else if (slow)
            {
                b.Append("s");
            }
            else
            {
                throw new ArgumentException("unknown speed");
            }

            if (robust)
            {
                // nothing.
            }
            else if (simple)
            {
                b.Append("_simple");
            }
            else
            {
                throw new ArgumentException("unknown complexity");
            }


            SphincsPlusParameters parameters = (SphincsPlusParameters)
                typeof(SphincsPlusParameters).GetField(b.ToString()).GetValue(null);//todo unsure

            //
            // Generate keys and test.
            //
            kpGen.Init(new SphincsPlusKeyGenerationParameters(random, parameters));
            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();

            SphincsPlusPublicKeyParameters pubParams = (SphincsPlusPublicKeyParameters)kp.Public;
            SphincsPlusPrivateKeyParameters privParams = (SphincsPlusPrivateKeyParameters)kp.Private;

            Assert.True(Arrays.AreEqual(Arrays.Concatenate(pubParams.Parameters.GetEncoded(), pk), pubParams.GetEncoded()), name + " " + count + ": public key");
            Assert.True(Arrays.AreEqual(Arrays.Concatenate(privParams.Parameters.GetEncoded(), sk), privParams.GetEncoded()), name + " " + count + ": secret key");

            //
            // Signature test
            //

            SphincsPlusSigner signer = new SphincsPlusSigner();

            FixedSecureRandom.Source[] s1 = { new FixedSecureRandom.Source(oprR) };
            signer.Init(true, new ParametersWithRandom(privParams, new FixedSecureRandom(s1)));

            byte[] sigGenerated = signer.GenerateSignature(msg);
            byte[] attachedSig = Arrays.Concatenate(sigGenerated, msg);


            signer.Init(false, pubParams);

            Assert.True(signer.VerifySignature(msg, sigGenerated), name + " " + count + ": signature verify");
            Assert.True(Arrays.AreEqual(sigExpected, attachedSig), name + " " + count + ": signature gen match");
        }

        private static void RunTestVectorFile(string name)
        {
            var buf = new Dictionary<string, string>();
            TestSampler sampler = new TestSampler();
            using (var src = new StreamReader(SimpleTest.GetTestDataAsStream("pqc.sphincsplus.subset_" + name)))
            {
                string line;
                while ((line = src.ReadLine()) != null)
                {
                    line = line.Trim();
                    if (line.StartsWith("#"))
                        continue;

                    if (line.Length > 0)
                    {
                        int a = line.IndexOf("=");
                        if (a > -1)
                        {
                            buf[line.Substring(0, a).Trim()] = line.Substring(a + 1).Trim();
                        }
                        continue;
                    }

                    if (buf.Count > 0)
                    {
                        if (!sampler.SkipTest(buf["count"]))
                        {
                            RunTestVector(name, buf);
                        }
                        buf.Clear();
                    }
                }

                if (buf.Count > 0)
                {
                    if (!sampler.SkipTest(buf["count"]))
                    {
                        RunTestVector(name, buf);
                    }
                    buf.Clear();
                }
            }
        }
    }
}