slowaes-0.1a1/0000755000175000017500000000000012126341052012241 5ustar bartmbartmslowaes-0.1a1/ruby/0000755000175000017500000000000012126341052013222 5ustar bartmbartmslowaes-0.1a1/ruby/README.markdown0000644000175000017500000000204112126341025015720 0ustar bartmbartm## gibberish-aes-ruby --- Written by Alex Boussinet Modified by Mark Percival This ruby gem is simply a modification of Alex Boussinet's Ruby-AES(normal implemenation) which can be found at I've fixed 2 issues to make it compatible with OpenSSL: - Correctly padding the blocks - Generating a key and IV from a password and random salt # require 'rubygems' require 'ruby-aes' require 'base64' enc = Aes.openssl_encrypt("pass", "test", :salt => "1831BD4EC8E35CC8", :size => 256, :mode => 'CBC') p Base64.b64encode(enc[:salted]) dec = Aes.openssl_decrypt("pass", enc[:salted]) p dec Valid modes are: - ECB (Electronic Code Book) - CBC (Cipher Block Chaining) - OFB (Output Feedback) - CFB (Cipher Feedback) Valid key length: - 128 bits - 192 bits - 256 bits For a really good encryption, 256 bits CBC is recommanded. For more information on AES-Rijndael, see: slowaes-0.1a1/ruby/test/0000755000175000017500000000000012126341052014201 5ustar bartmbartmslowaes-0.1a1/ruby/test/KAT_MCT/0000755000175000017500000000000012126341052015323 5ustar bartmbartmslowaes-0.1a1/ruby/test/KAT_MCT/table.1920000644000175000017500000003040012126341024016643 0ustar bartmbartm00010203050607080A0B0C0D0F10111214151617191A1B1C 2d 33 ee f2 c0 43 0a 8a 9e bf 45 e8 09 c4 0b b6 1E1F20212324252628292A2B2D2E2F30323334353738393A 6a a3 75 d1 fa 15 5a 61 fb 72 35 3e 0a 5a 87 56 3C3D3E3F41424344464748494B4C4D4E5051525355565758 bc 37 36 51 8b 94 90 dc b8 ed 60 eb 26 75 8e d4 5A5B5C5D5F60616264656667696A6B6C6E6F707173747576 aa 21 44 02 b4 6c ff b9 f7 61 ec 11 26 3a 31 1e 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394 02 ae a8 6e 57 2e ea b6 6b 2c 3a f5 e9 a4 6f d6 969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2 e2 ae f6 ac c3 3b 96 5c 4f a1 f9 1c 75 ff 6f 36 B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0 06 59 df 46 42 71 62 b9 43 48 65 dd 94 99 f9 1d D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE 49 a4 42 39 c7 48 fe b4 56 f5 9c 27 6a 56 58 df F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C 66 20 8f 6e 9d 04 52 5b de db 27 33 b6 a6 be 37 0E0F10111314151618191A1B1D1E1F20222324252728292A 33 93 f8 df c7 29 c9 7f 54 80 b9 50 bc 96 66 b0 2C2D2E2F31323334363738393B3C3D3E4041424345464748 60 68 34 c8 ce 06 3f 32 34 cf 11 45 32 5d bd 71 4A4B4C4D4F50515254555657595A5B5C5E5F606163646566 fe c1 c0 4f 52 9b bd 17 d8 ce cf cc 47 18 b1 7f 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384 32 df 99 b4 31 ed 5d c5 ac f8 ca f6 dc 6c e4 75 868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2 7f dc 2b 74 6f 3f 66 52 96 94 3b 83 71 0d 1f 82 A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0 8f ba 15 10 a3 c5 b8 7e 2e aa 3f 7a 91 45 5c a2 C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE 2c 9b 46 8b 1c 2e ed 92 57 8d 41 b0 71 6b 22 3b E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFC 0a 2b bf 0e fc 6b c0 03 4f 8a 03 43 3f ca 1b 1a FEFE01010304050608090A0B0D0E0F10121314151718191A 25 26 0e 1f 31 f4 10 4d 38 72 22 e7 06 32 50 4b 1C1D1E1F21222324262728292B2C2D2E3031323335363738 c5 27 d2 5a 49 f0 8a 52 28 d3 38 64 2a e6 51 37 3A3B3C3D3F40414244454647494A4B4C4E4F505153545556 3b 49 fc 08 14 32 f5 89 0d 0e 3d 87 e8 84 a6 9e 58595A5B5D5E5F60626364656768696A6C6D6E6F71727374 d1 73 f9 ed 1e 57 59 7e 16 69 31 df 27 54 a0 83 767778797B7C7D7E80818283858687888A8B8C8D8F909192 8c 2b 7c af a5 af e7 f1 35 62 da ea e1 ad ed e0 94959697999A9B9C9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0 aa f4 ec 8c 1a 81 5a eb 82 6c ab 74 13 39 53 2c D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBEC 40 be 8c 5d 91 08 e6 63 f3 8f 1a 23 95 27 9e cf 2A2B2C2D2F30313234353637393A3B3C3E3F404143444546 0c 8a d9 bc 32 d4 3e 04 71 67 53 aa 4c fb e3 51 48494A4B4D4E4F50525354555758595A5C5D5E5F61626364 14 07 b1 d5 f8 7d 63 35 7c 8d c7 eb ba eb bf ee 84858687898A8B8C8E8F90919394959698999A9B9D9E9FA0 e6 27 34 d1 ae 33 78 c4 54 9e 93 9e 6f 12 34 16 A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE 5a 75 2c ff 2a 17 6d b1 a1 de 77 f2 d2 cd ee 41 C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDC a9 c8 c3 a4 ea be dc 80 c6 47 30 dd d0 18 cd 88 1A1B1C1D1F20212224252627292A2B2C2E2F303133343536 ee 9b 3d bb db 86 18 00 72 13 08 34 d3 05 99 9a 38393A3B3D3E3F40424344454748494A4C4D4E4F51525354 a7 fa 8c 35 86 b8 eb de 75 68 ea d6 f6 34 a8 79 929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE 37 e0 f4 a8 7f 12 7d 45 ac 93 6f e7 ad 88 c1 0a 464748494B4C4D4E50515253555657585A5B5C5D5F606162 3f 77 d8 b5 d9 2b ac 14 8e 4e 46 f6 97 a5 35 c5 828384858788898A8C8D8E8F91929394969798999B9C9D9E d2 5e bb 68 6c 40 f7 e2 c4 da 10 14 93 65 71 ca A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBC 4f 1c 76 9d 1e 5b 05 52 c7 ec a8 4d ea 26 a5 49 BEBFC0C1C3C4C5C6C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA 85 48 e2 f8 82 d7 58 4d 0f af c5 43 72 b6 63 3a DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8 87 d7 a3 36 cb 47 6f 17 7c d2 a5 1a f2 a6 2c df FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 03 b1 fe ac 66 8c 4e 48 5c 10 65 df c2 2b 44 ee 18191A1B1D1E1F20222324252728292A2C2D2E2F31323334 bd a1 5e 66 81 9f a7 2d 65 3a 68 66 aa 28 79 62 363738393B3C3D3E40414243454647484A4B4C4D4F505152 4d 0c 7a 0d 25 05 b8 0b f8 b6 2c eb 12 46 7f 0a 54555657595A5B5C5E5F60616364656668696A6B6D6E6F70 62 6d 34 c9 42 9b 37 21 13 30 98 64 66 b9 4e 5f 727374757778797A7C7D7E7F81828384868788898B8C8D8E 33 3c 3e 6b f0 06 56 b0 88 a1 7e 5f f0 e7 f6 0a 90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABAC 68 7e d0 cd c0 d2 a2 bc 8c 46 6d 05 ef 9d 28 91 AEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA 48 78 30 e7 8c c5 6c 16 93 e6 4b 2a 66 60 c7 b6 CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8 7a 48 d6 b7 b5 2b 29 39 2a a2 07 2a 32 b6 61 60 EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 90 73 20 e6 4c 8c 53 14 d1 0f 8d 7a 11 c8 61 8d 08090A0B0D0E0F10121314151718191A1C1D1E1F21222324 b5 61 f2 ca 2d 6e 65 a4 a9 83 41 f3 ed 9f f5 33 262728292B2C2D2E30313233353637383A3B3C3D3F404142 df 76 93 80 d2 12 79 2d 02 6f 04 9e 2e 3e 48 ef 44454647494A4B4C4E4F50515354555658595A5B5D5E5F60 79 f3 74 bc 44 5b da bf 8f cc b8 84 3d 60 54 c6 626364656768696A6C6D6E6F71727374767778797B7C7D7E 4e 02 f1 24 2f a5 6b 05 c6 8d ba e8 fe 44 c9 d6 80818283858687888A8B8C8D8F90919294959697999A9B9C cf 73 c9 3c bf f5 7a c6 35 a6 f4 ad 2a 4a 15 45 9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA 99 23 54 8e 28 75 75 07 25 b8 86 56 67 84 c6 25 BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8 48 88 33 6b 72 3a 02 2c 95 45 32 0f 83 6a 42 07 DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 f8 4d 9a 55 61 b0 60 8b 11 60 de e0 00 c4 1b a8 F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314 c2 31 92 a0 41 8e 30 a1 9b 45 ae 3e 36 25 bf 22 161718191B1C1D1E20212223252627282A2B2C2D2F303132 b8 4e 06 90 b2 8b 00 25 38 1a d8 2a 15 e5 01 a7 34353637393A3B3C3E3F40414344454648494A4B4D4E4F50 ac ef 5e 5c 10 88 76 c4 f0 62 69 f8 65 b8 f0 b0 525354555758595A5C5D5E5F61626364666768696B6C6D6E 0f 1b 36 03 e0 f5 dd ea 45 48 24 61 53 a5 e0 64 70717273757677787A7B7C7D7F80818284858687898A8B8C fb b6 38 93 45 0d 42 b5 8c 6d 88 cd 3c 18 09 e3 8E8F90919394959698999A9B9D9E9FA0A2A3A4A5A7A8A9AA 4b ef 73 6d f1 50 25 9d ae 0c 91 35 4e 8a 5f 92 ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8 7d 2d 46 24 20 56 ef 13 d3 c3 fc 93 c1 28 f4 c7 CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 e9 c1 ba 2d f4 15 65 7a 25 6e db 33 93 46 80 fd E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304 e2 3e e2 77 b0 aa 0a 1d fb 81 f7 52 7c 35 14 f1 060708090B0C0D0E10111213151617181A1B1C1D1F202122 3e 74 45 b0 b6 3c aa f7 5e 4a 91 1e 12 10 6b 4c 24252627292A2B2C2E2F30313334353638393A3B3D3E3F40 38 a2 b5 a9 74 b0 57 5c 5d 73 39 17 fb 0d 45 70 424344454748494A4C4D4E4F51525354565758595B5C5D5E e2 1d 40 1e bc 60 de 20 d6 c4 86 e4 f3 9a 58 8b 60616263656667686A6B6C6D6F70717274757677797A7B7C e5 1d 5f 88 c6 70 b0 79 c0 ca 1f 0c 2c 44 05 a2 7E7F80818384858688898A8B8D8E8F90929394959798999A 24 6a 94 78 8a 64 2f b3 d1 b8 23 c8 76 23 80 c8 9C9D9E9FA1A2A3A4A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8 b8 0c 39 1c 5c 41 a4 c3 b3 0c 68 e0 e3 d7 55 0f BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 b7 7c 47 54 fc 64 eb 9a 11 54 a9 af 0b b1 f2 1c D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4 fb 55 4d e5 20 d1 59 a0 6b f2 19 fc 7f 34 a0 2f F6F7F8F9FBFCFDFE00010203050607080A0B0C0D0F101112 a8 9f ba 15 2d 76 b4 92 7b ee d1 60 dd b7 6c 57 14151617191A1B1C1E1F20212324252628292A2B2D2E2F30 56 76 ea b4 a9 8d 2e 84 73 b3 f3 d4 64 24 24 7c 323334353738393A3C3D3E3F41424344464748494B4C4D4E 4e 8f 06 8b d7 ed e5 2a 63 90 36 ec 86 c3 35 68 50515253555657585A5B5C5D5F60616264656667696A6B6C f0 19 3c 4d 7a ff 17 91 ee 4c 07 eb 4a 18 24 fc 6E6F70717374757678797A7B7D7E7F80828384858788898A ac 86 86 ee ca 9b a7 61 af e8 2d 67 b9 28 c3 3f 8C8D8E8F91929394969798999B9C9D9EA0A1A2A3A5A6A7A8 5f af 85 73 e3 3b 14 5b 6a 36 9c d3 60 6a b2 c9 AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 31 58 7e 99 44 ab 1c 16 b8 44 ec ad 0d f2 e7 da C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4 d0 17 fe cd 91 14 8a ba 37 f6 f3 06 8a a6 7d 8a E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8FAFBFCFDFE010002 78 8e f2 f0 21 a7 3c ba 27 94 b6 16 07 8a 85 00 04050607090A0B0C0E0F10111314151618191A1B1D1E1F20 5d 1e f2 0d ce d6 bc bc 12 13 1a c7 c5 47 88 aa 222324252728292A2C2D2E2F31323334363738393B3C3D3E b3 c8 cf 96 1f af 9e a0 5f dd e6 d1 e4 d8 f6 63 40414243454647484A4B4C4D4F50515254555657595A5B5C 14 30 75 c7 06 05 86 1c 7f ac 65 26 19 9e 45 9f 5E5F60616364656668696A6B6D6E6F70727374757778797A a5 ae 12 ea de 9a 87 26 8d 89 8b fc 8f c0 25 2a 7C7D7E7F81828384868788898B8C8D8E9091929395969798 09 24 f7 cf 2e 87 7a 48 19 f5 24 4a 36 0d ce a9 9A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 3d 9e 96 35 af cc 3e 29 1c c7 ab 3f 27 d1 c9 9a B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4 9d 80 fe eb f8 75 10 e2 b8 fb 98 bb 54 fd 78 8c D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2 5f 9d 1a 08 2a 1a 37 98 5f 17 40 02 ec a0 13 09 F4F5F6F7F9FAFBFCFEFE01010304050608090A0B0D0E0F10 a3 90 eb b1 d1 40 39 30 18 4a 44 b4 87 66 46 e4 121314151718191A1C1D1E1F21222324262728292B2C2D2E 70 0f e9 18 98 1c 31 95 bb 6c 4b cb 46 b7 4e 29 30313233353637383A3B3C3D3F40414244454647494A4B4C 90 79 84 40 6f 7b f2 d1 7f b1 eb 15 b6 73 d7 47 4E4F50515354555658595A5B5D5E5F60626364656768696A c3 2a 95 6d cf c8 75 c2 ac 7c 7c c8 b8 cc 26 e1 6C6D6E6F71727374767778797B7C7D7E8081828385868788 02 64 6e 2e bf a9 b8 20 cf 84 24 e9 b9 b6 eb 51 8A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 62 1f da 3a 5b bd 54 c6 d3 c6 85 81 6b d4 ea d8 A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4 d4 e2 16 04 04 26 df af 18 b1 52 46 9b c5 ac 2f C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2 9d 06 35 b9 d3 3b 6c db d7 1f 5d 24 6e a1 7c c8 E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6F8F9FAFBFDFEFE00 10 ab ad 1b d9 ba e5 44 88 08 76 55 83 a2 cc 1a 020304050708090A0C0D0E0F11121314161718191B1C1D1E 68 91 88 9e 16 54 4e 35 5f f6 5a 79 3c 39 c9 a8 20212223252627282A2B2C2D2F30313234353637393A3B3C cc 73 55 82 e6 80 72 c1 63 cd 9d df 46 b9 12 79 3E3F40414344454648494A4B4D4E4F50525354555758595A c5 c6 8b 9a ee b7 f8 78 df 57 8e fa 56 2f 95 74 5C5D5E5F61626364666768696B6C6D6E7071727375767778 5f 47 64 39 5a 66 7a 47 d7 34 52 95 5d 0d 2c e8 7A7B7C7D7F80818284858687898A8B8C8E8F909193949596 70 14 48 33 1f 66 10 6c ef dd f1 eb 82 67 c3 57 98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4 cb 3e e5 6d 2e 14 b4 e1 94 16 66 f1 33 79 d6 57 B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2 9f e1 6e fd 18 ab 6e 19 81 19 18 51 fe db 07 64 D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6E8E9EAEBEDEEEFF0 3d c9 ba 24 e1 b2 23 58 9b 14 7a dc eb 4c 8e 48 F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E 1c 33 30 32 68 2e 7d 4d e5 e5 af c0 5c 3e 48 3c 10111213151617181A1B1C1D1F20212224252627292A2B2C d5 93 cc 99 a9 5a fe f7 e9 20 38 e0 5a 59 d0 0a 2E2F30313334353638393A3B3D3E3F40424344454748494A 51 e7 f9 6f 53 b4 35 39 23 45 2c 22 21 34 e1 ec 4C4D4E4F51525354565758595B5C5D5E6061626365666768 40 75 b3 57 a1 a2 b4 73 40 0c 3b 25 f3 2f 81 a4 6A6B6C6D6F70717274757677797A7B7C7E7F808183848586 30 2e 34 1a 3e bc d7 4f 0d 55 f6 17 14 57 02 84 88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4 57 ab dd 82 31 28 0d a0 1c 50 42 b7 8c f7 65 22 A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2 17 f9 ea 7e ea 17 ac 1a df 0e 19 0f ef 79 9e 92 C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6D8D9DADBDDDEDFE0 2e 1b dd 56 3d d8 7e e5 c3 38 dd 6d 09 8d 0a 7a E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE eb 86 99 96 e6 f8 bf b2 bf dd 9e 0c 45 04 db b2 00010203050607080A0B0C0D0F10111214151617191A1B1C c2 e0 15 49 e9 de cf 31 74 68 b3 e0 18 c6 1b a8 1E1F20212324252628292A2B2D2E2F30323334353738393A 8d a8 75 d0 33 c0 1d d4 63 b2 44 a1 77 0f 4a 22 3C3D3E3F41424344464748494B4C4D4E5051525355565758 8b a0 dc f3 a1 86 84 4f 02 6d 02 2f 88 39 d6 96 5A5B5C5D5F60616264656667696A6B6C6E6F707173747576 e9 69 1f f9 a6 cc 69 70 e5 16 70 a0 fd 5b 88 c1 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394 f2 ba ec 06 fa ee d3 0f 88 ee 63 ba 08 1a 6e 5b 969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2 9c 39 d4 c4 59 ae 57 53 39 4d 60 94 ad c2 1e 78 B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0 63 45 b5 32 a1 19 04 50 2e a4 3b a9 9c 6b d2 b2 D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE 5f fa e3 06 1a 95 17 2e 40 70 ce dc e1 e4 28 c8 F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C 0a 45 66 be 4c df 9a dc e5 de c8 65 b5 ab 34 cd 0E0F10111314151618191A1B1D1E1F20222324252728292A ca 17 fc ce 79 b7 40 4f 25 59 b2 29 28 f1 26 fb 2C2D2E2F31323334363738393B3C3D3E4041424345464748 97 ca 39 b8 49 ed 73 a6 47 0a 97 c8 21 d8 2f 58 4A4B4C4D4F50515254555657595A5B5C5E5F606163646566 81 98 cb 06 bc 68 4c 6d 3e 9b 79 89 42 8d cf 7a 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384 f5 3c 46 4c 70 5e e0 f2 8d 9a 4c 59 37 49 28 bd 868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2 9a db 3d 4c ca 55 9b b9 8c 3e 2e d7 3d bf 11 54 slowaes-0.1a1/ruby/test/KAT_MCT/table.2560000644000175000017500000003440012126341024016650 0ustar bartmbartm00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 83 4e ad fc ca c7 e1 b3 06 64 b1 ab a4 48 15 ab 28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E d9 dc 4d ba 30 21 b0 5d 67 c0 51 8f 72 b6 2b f1 50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 a2 91 d8 63 01 a4 a7 39 f7 39 21 73 aa 3c 60 4c 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E 42 64 b2 69 64 98 de 4d f7 97 88 a9 f8 3e 93 90 A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 ee 99 32 b3 72 18 04 d5 a8 3e f5 94 92 45 b6 f6 C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE e6 24 8f 55 c5 fd cb ca 9c bb b0 1c 88 a2 ea 77 F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 b8 35 8e 41 b9 df f6 5f d4 61 d5 5a 99 26 62 47 18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E f0 e2 d7 22 60 af 58 e2 1e 01 5a b3 a4 c0 d9 06 40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 47 5b 8b 82 3c e8 89 3d b3 c4 4a 9f 2a 37 9f f7 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E 68 8f 52 81 94 58 12 86 2f 5f 30 76 cf 80 41 2f 90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 08 d1 d2 bc 75 0a f5 53 36 5d 35 e7 5a fa ce aa B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE 87 07 12 1f 47 cc 3e fc ec a5 f9 a8 47 49 50 a1 E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 e5 1a a0 b1 35 db a5 66 93 9c 3b 63 59 a9 80 c5 08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E 06 9a 00 7f c7 6a 45 9f 98 ba f9 17 fe df 95 21 30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 72 61 65 c1 72 3f bc f6 c0 26 d7 d0 0b 09 10 27 58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E d7 c5 44 de 91 d5 5c fc de 1f 84 ca 38 22 00 ce 80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 fe d3 c9 a1 61 b9 b5 b2 bd 61 1b 41 dc 9d a3 57 A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE 4f 63 4c dc 65 51 04 34 09 f3 0b 63 58 32 cf 82 D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 10 9c e9 8d b0 df b3 67 34 d9 f3 39 47 11 b4 e6 70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 4e a6 df ab a2 d8 a0 2f fd ff a8 98 35 98 72 42 98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE 5a e0 94 f5 4a f5 8e 6e 3c db f9 76 da c6 d9 ef C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 76 4d 8e 8e 0f 29 92 6d be 51 22 e6 63 54 fd be E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E 3f 04 18 f8 88 cd f2 9a 98 2b f6 b7 54 10 d6 a9 10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 e4 a3 e7 cb 12 cd d5 6a a4 a7 51 97 a9 53 02 20 38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E 21 16 77 68 4a ac 1e c1 a1 60 f4 4c 4e bf 3f 26 60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 d2 1e 43 9f f7 49 ac 8f 18 d6 d4 b1 05 e0 38 95 88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE d9 f6 ff 44 64 6c 47 25 bd 4c 01 03 ff 55 52 a7 B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 0b 12 56 c2 a0 0b 97 62 50 cf c5 b0 c3 7e d3 82 D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE b0 56 44 7f fc 6d c4 52 3a 36 cc 2e 97 2a 3a 79 00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 5e 25 ca 78 f0 de 55 80 25 24 d3 8d a3 fe 44 56 28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E a5 bc f4 72 8f a5 ea ad 85 67 c0 dc 24 67 5f 83 50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 81 4e 59 f9 7e d8 46 46 b7 8b 2c a0 22 e9 ca 43 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E 15 47 8b ee c5 8f 47 75 c7 a7 f5 d4 39 55 14 d7 A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 25 35 48 ff ca 46 1c 67 c8 cb c7 8c d5 9f 47 56 C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE fd 7a d8 d7 3b 9b 0f 8c c4 16 00 64 0f 50 3d 65 F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 06 19 9d e5 2c 6c bf 8a f9 54 cd 65 83 0b cd 56 18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E f1 7c 4f fe 48 e4 4c 61 bd 89 1e 25 7e 72 57 94 40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 9a 5b 4a 40 2a 3e 8a 59 be 6b f5 cd 81 54 f0 29 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E 79 bd 40 b9 1a 7e 07 dc 93 9d 44 17 82 ae 6b 17 90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 d8 ce aa f8 97 6e 5f be 10 12 d8 c8 4f 32 37 99 B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE 33 16 e2 75 1e 2e 38 8b 08 3d a2 3d d6 ac 3f be E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 8b 7c fb e3 7d e7 dc a7 93 52 18 19 24 2c 58 16 08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E f2 3f 03 3c 0e eb f8 ec 55 75 26 62 fd 58 ce 68 30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 59 eb 34 f6 c8 bd ba cc 5f c6 ad 73 a5 9a 13 01 58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E dc de 8b 6b d5 cf 7c c2 2d 95 05 e3 ce 81 26 1a 80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 e3 3c f7 e5 24 fe d7 81 e7 04 2f f9 f4 b3 5d c7 A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE 27 96 3c 8f ac df 73 06 28 67 d1 64 df 6d 06 4c D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 77 b1 ce 38 6b 55 1b 99 5f 2f 2a 1d a9 94 ee f8 F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E f0 83 38 8b 01 36 79 ef cf 0b b9 b1 5d 52 ae 5c 20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 c5 00 9e 0d ab 55 db 0a bd b6 36 f2 60 02 90 c8 48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E 78 04 88 1e 26 cd 53 2d 85 14 d3 68 3f 00 f1 b9 70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 46 cd dc d7 3d 1e b5 3e 67 5c a0 12 87 0a 92 a3 98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE a9 fb 44 06 2b b0 7f e1 30 a8 e8 29 9e ac b1 ab C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 2b 6f f8 d7 a5 cc 3a 28 a2 2d 5a 6f 22 1a f2 6b E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E 1a 95 27 c2 9b 8a dd 4b 0e 3e 65 6d bb 2a f8 b4 10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 7f 99 cf 2c 75 24 4d f0 15 eb 4b 0c 10 50 ae ae 38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E e8 4f f8 5b 0d 94 54 07 19 09 c1 38 16 46 c4 ed 60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 89 af d4 0f 99 52 12 80 d5 39 9b 12 40 4f 6d b4 88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE a0 9e f3 2d bc 51 19 a3 5a b7 fa 38 65 6f 03 29 B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 61 77 34 57 f0 68 c3 76 c7 82 9b 93 e6 96 e7 16 D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE a3 4f 0c ae 72 6c ce 41 dd 49 87 47 d8 91 b9 67 00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 85 6f 59 49 6c 73 88 ee 2d 2b 1a 27 b7 69 78 47 28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E cb 09 0c 59 3e f7 72 0b d9 59 08 fb 93 b4 9d f4 50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 a0 ac 75 cd 2f 19 23 d4 60 fc 4d 45 7a d9 5b af 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E 28 28 2c c7 d2 1d 6a 29 23 64 1e 52 d1 88 ef 0c A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 0d fa 5b 02 ab b1 8e 5a 81 53 05 21 6d 6d 4f 8e C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE 73 59 63 5c 0e ec ef e3 1d 67 33 95 fb 46 fb 99 F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 73 c6 79 f7 d5 ae f2 74 5c 97 37 bb 4c 47 fb 36 18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E b1 92 bd 47 2a 4d 2e af b7 86 e9 74 58 96 76 26 40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 0e c3 27 f6 c8 a2 b1 47 59 8c a3 fd e6 1d c6 a4 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E fc 41 8e b3 c4 1b 85 9b 38 d4 b6 f6 46 62 97 29 90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 30 24 9e 5a c2 82 b1 c9 81 ea 64 b6 09 f3 a1 54 B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE 5e 6e 08 64 6d 12 15 07 76 bb 43 c2 d7 8a 97 03 E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 fa eb 3d 5d e6 52 cd 34 47 dc eb 34 3f 30 39 4a 08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E a8 e8 87 06 82 3f 69 93 ef 80 d0 5c 1c 7b 2c f0 30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 8c ed 86 67 7e 6e 00 a1 a1 b1 59 68 f2 d3 cc e6 58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E 9f c7 c2 38 58 be 03 bd eb b8 4e 90 db 67 86 a9 80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 b4 fb d6 5b 33 f7 0d 8c f7 f1 11 1a c4 64 9c 36 A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE c5 c3 2d 5e d0 3c 4b 53 cc 8c 1b d0 ef 0d bb f6 D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 d1 a7 f0 3b 77 3e 5c 21 24 64 b6 37 09 c6 a8 91 F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E 6b 71 61 d8 74 59 47 ac 69 50 43 8e a1 38 d0 28 20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 fd 47 a9 f7 e3 66 ee 7a 09 bc 50 8b 00 46 06 61 48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E 00 d4 0b 00 3d c3 a0 d9 31 0b 65 9b 98 c7 e4 16 70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 ee a4 c7 9d cc 8e 2b da 69 1f 20 ac 48 be 07 17 98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE e7 8f 43 b1 1c 20 44 03 e5 75 1f 89 d0 5a 25 09 C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 d0 f0 e3 d1 f1 24 4b b9 79 93 1e 38 dd 17 86 ef E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E 04 2e 63 9d c4 e1 e4 dd e7 b7 5b 74 9e a6 f7 65 10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 bc 03 2f dd 0e fe 29 50 3a 98 0a 7d 07 ab 46 a8 38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E 0c 93 ac 94 9c 0d a6 44 6e ff b8 61 83 b6 c9 10 60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 e0 d3 43 e1 4d a7 5c 91 7b 4a 5c ec 48 10 d7 c2 88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE 0e af b8 21 74 84 08 27 9b 93 7b 62 67 92 e6 19 B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 fa 1a c6 e0 2d 23 b1 06 a1 fe f1 8b 27 4a 55 3f D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE 0d ad fe 01 9c d1 23 68 07 55 07 df 33 c1 a1 e9 00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 3a 08 79 b4 14 46 5d 9f fb af 86 b3 3a 63 a1 b9 28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E 62 19 9f ad c7 6d 0b e1 80 5d 3b a0 b7 d9 14 bf 50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 1b 06 d6 c5 d3 33 e7 42 73 01 30 cf 78 e7 19 b4 78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E f1 f8 48 82 4c 32 e9 dc dc bf 21 58 0f 06 93 29 A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 1a 09 05 0c bd 68 4f 78 4d 8e 96 5e 07 82 f2 8a C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE 79 c2 96 9e 7d ed 2b a7 d0 88 f3 f3 20 69 23 60 F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 09 1a 65 8a 2f 74 44 c1 6a cc b6 69 45 0c 7b 63 18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E 97 c1 e3 a7 2c ca 65 fa 97 7d 5e d0 e8 a7 bb fc 40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 70 c4 30 c6 db 9a 17 82 89 37 30 5a 2d f9 1a 2a 68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E 62 95 53 45 7f be 24 79 09 85 71 c7 c9 03 fd e8 90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 a2 5b 25 a6 1f 61 26 69 e7 d9 12 65 c7 d4 76 ba B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE eb 7e 4e 49 b8 ae 0f 02 45 70 dd a2 93 25 4f ed E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 38 fe 15 d6 1c ca 84 51 6e 92 4a dc e5 01 4f 67 08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E 3a d2 08 49 22 49 10 8c 9f 3e be b1 67 ad 05 83 30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 29 9b a9 f9 bf 5a b0 5c 35 80 fc 26 ed d1 ed 12 58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E 19 dc 70 5b 85 7a 60 fb 07 71 7b 2e a5 71 77 81 80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 ff c8 ae b8 85 b5 ef ca d0 6b 6d be bf 92 e7 6b A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE f5 89 00 c5 e0 b3 85 25 3f f2 54 62 50 a0 14 2b D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 2e e6 7b 56 28 0b c4 62 42 9c ee 6e 33 70 cb c1 F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E 20 db 65 0a 9c 8e 9a 84 ab 4d 25 f7 ed c8 f0 3f 20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 3c 36 da 16 95 25 cf 81 88 43 80 5f 25 b7 8a e5 48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E 9a 78 1d 96 0d b9 e4 5e 37 77 90 42 fe a5 19 22 70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 65 60 39 5e c2 69 c6 72 a3 c2 88 22 6e fd ba 77 98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE 8c 77 2b 7a 18 9a c5 44 45 3d 59 16 eb b2 7b 9a C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 77 ca 54 68 cc 48 e8 43 d0 5f 78 ee d9 d6 57 8f E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E 72 cd cc 71 dc 82 c6 0d 44 29 c9 e2 d8 19 5b aa 10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 80 80 d6 8c e6 0e 94 b4 0b 5b 8b 69 ee b3 5a fa 38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E 44 22 2d 3c de 29 9c 04 36 9d 58 ac 0e ba 1e 8e 60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 9b 87 21 b0 a8 df c6 91 c5 bc 58 85 db fc b2 7a 88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE 0d c0 15 ce 9a 3a 34 14 b5 e6 2e c6 43 38 41 83 B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 70 57 15 44 8a 8d a4 12 02 5c e3 83 45 c2 a1 48 D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE c3 2b 5b 0b 6f ba e1 65 26 6c 56 9f 4b 6e cf 0b 00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 4d ca 6c 75 19 2a 01 dd ca 94 76 af 2a 52 1e 87 28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E 05 86 91 e6 27 ec bc 36 ac 07 b6 db 42 3b d6 98 50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 74 44 52 70 95 83 8f e0 80 fc 2b cd d3 08 47 eb slowaes-0.1a1/ruby/test/KAT_MCT/aes_kat_mct.rb0000644000175000017500000002102112126341024020115 0ustar bartmbartm#!/usr/bin/env ruby =begin This file is a part of ruby-aes Written by Alex Boussinet KAT Tests and MCT tests according to katmct.pdf file. See rijndael-vals.zip =end require File.dirname(__FILE__) + '/../test_helper.rb' def cbc_decrypt_mct(output) output.write <ŏ_?owe%&w^kc[t W.m3Jݣc'6}1l>`^ܙ-9hn 7sj\Imzmm%\Xg5}m1sN']a!׶S3>۬eEZv]c5RL6xk6W}m8Fl݅iIN~^ks'by5V6<־m8MѬcfJ.8k.Mlڦmy8K;Ad–Oy3Rgİ[?׶a`J9즥OEjc[zm˭r|9jdb)띷g!|)eۊ-T=,^k;Èեݫrls׶|r*\޴m޹[7Ϗmi9iGn̳ϥׇ|ma\fi!MZ|j5>ٙ#_҄jZ)l=>k,ú'G!{Xl#5&qQ%rmǿf5pFoquNlVuyDҨÍ^|lVt:$j۷P#\%LD/)rR農f %S4˪ꮁou">Ƶ܋+M甧(e?Y_82| ;uf cf\6mKǸq1.q.rЃ<%ȴ:מP-Sivy1Iߣjڂw`cnDb)Ggs;ś>,G>v84aGI$P}q,jLe% g8Sw?])8]o:S2,vjӤ _%A?Ņ0q1晍Ѭ|N e$8884{l<kYBȮ;?6CD}czTasMҰŸ˚pu1M%,<8>?|Dzs+ymO15GZxkM5|{!` I=f 08{u%#6 k1iòGivv1oNݳKD2O|'@ԙX[A&|M. 3c܊ osPlw 67~O(wY43@, !{,o? ǾmNuFl!_ 2ywJ(s\9a<[ AQOb@8Y3sD]q WN۽0Ci7e64NXc˗ 紺!*QEj5Į 6L930cqy[p@cZ#J-9pq@}b;"nOvp"7q$If3cG+PBX,U~БhFwC-%"s&΂V8<2aA3{gf=.Ɓǒ'L$đ{c,fӏ+q'BgMd=0 |nj=I9̈c[}W0EYV V͝!\h+%np963cǥ9<.q='-_9"vW|Qu Sw"|ORc_ p`ݪI|ٝNW d ^y9v65D69$i꠬׮ci!3\!U5' I}+浣`@⡝kW@xr\N nAsDq!BCIw5,ULHPu}`|65{\v7FlK!ׁ1Dѱ_tc,56$Uv1BS s| lu% lrb8)_240u(Di"}xo< `DZL+)72O^Cxk*FT@U!ڡC!`5\ZX030ޒ:WĎ Yg}`&tBȌ8XqLL箟SiT W8,kJ˹3'9~5[S$͸ _~2h 1k\A&lxF<;b`\;S6 1Vt8Һ43oƽ,s\1~ R XaDyze[X6Zb$ze:t2 Jkxr%3Oy':>r<=.߇̳ .ol]=|u0~J; jAq5s]vم32Ljg_. 'B7!ik= t#p{ J5D"q:Lz]-S6FTg'߽< FU|_bkޛ:t tʦL &{n} hqvo'B6JN7>/݋7ݦa3F&;10q1x9L6: 8,_]ݙ7|u#1s؈{깾!Jj%t qJ8*1QtSu\<$aPiy PL2T26>Df!%!qENZB`\N{ƍ:p"C՛twŘ7uφ'mWLQ8-A|Xw{\5 ͥo{0C~L?0 T{F}SRwt-5v5$a"'AĠP p<#sN0g w&FkWSFi B VBC"s\(ȑ  ,nZhq Gy0N+1ruu8a C_w"l:sNrtBky]ݚ2!qùuDo; ` v w"^p;rWy~ ew$߲BB\ i=jQ~_s<}!&p,j ǕJN;s|,k7|$>ZqJ$v _m G.M~!tB* +`\fiRitm6]lںƮ]헷~p{)"֘57S= ^÷T) q,ݿqV7ws5.rwleų;x.h$Rr7t$ Zz3H|3|N<{'9օ7SIlp|c}#_͞y!Cf~Yqq &47l~[AH\Vr\f3lgD%>T&q]h Yi∓zWA0,u7`BsKuJ?6qfA6q2ʙ edSc?-.flh]qV x婬v`z m'>;n@&9`z g-s2oOq3:v(as +Xɾ0;`aۑu{@OZ0Zζ .]!2j!YԢAަm zc\C}܄qf&omVҍ2?<UoF@~5,(TT@dP@9j9.q~}dceE2{[ F&VI@hy eB×Sw1!4<r?=.G/e;6zTZ <ʉ.Qj L{RA%>ÓUIG=괂w@9 Hg֡1CM꙲݇{%*Qb ž-Lgeh+]`́;WBjv#|l[^qzE90+]t2qF֓=f[|õ[)܉: eۂpb: ^ d쭉rB{N}$Xv)`<+e'B8Ձ"L#\¨7S1n46;(N`͘a}+W2b3(#H9AT f '!l$6; ʬ{(QuD݈^{.VW/Kc($1csط=/BUA/mMeǸ!8eD@X(]1.LX~הIp"6]V˾X >F&!}V.jcBՌJV6عl^@5_%aVT(\,YSn~XW^@ /ۊnRk EMnwOt*Иz°nO)\.*ԗطܔ׼kTg'.5#[=<)HE>p^ ŃT"2˟TK'ctBg֝8QNT#ٌXn~R.=o!Υ{`a+Dq15$Yrٚ(V]an'㫜!ϵ.Cu76T^!n0.n3Kƺ%;? /l>r ̉fl6^73Ȟ}W{ 8=o˕; 2{(PrKCxXz)׺*<'H*u?z:Y~Ư5>b8Uq.,GLžQN(bK 0Z/҆YCƉo XspEJghn8_-U%I x'HհoA0p3e]I"Hwp9Oe(ˣ' M(̙h4?>ow0VII)6jmO:b:$^l4Q>'sbz>Ke˨X+*yF N3 W> 4E '-Fx&;EGtG$~:(ȝ^fT+k/V(C١` JY&I.q -!;9駁LD=vL0LʞXѕt7V+yJq"|o=%"Z>J1ձ_=Hox{`3dh]N %cZeTMXE+bꪭ;W<٨[=Q7_6pgSՋܙD03S]m)p@|TN$Ug`WȻ(jb|-^q <&1 pwݒkf1 duMYfWe6&4߼k<c(F'C5@fJ$0z@'' /,JI^4EP?"8QxmXAzurZwbC]!05A5qzsXS)8` ,3>򊯁VŇnB9=QV_5xd܂Z@*p( ѢE)[X%T\[-J5upcG8-D9ڃ94Ǻ Z!st0J`XU_¹Gtaf#o`:l[w74U4'd?<֖TLt+¹wP ?r{ d[=zVBYwSbiHFc݈POUnn'T+T kZYܷYAST Ċ!YXdQTslEsޝHU uC!6/>{`y*Vbkr _Q[zRB:^`%8a=Y/V|J&?N X(v$Cب,E`i;l<%H5\h|So /F<]lyŠ >YnT9= ۘ~ a]i8tJOJ'{`#4%Wk* Ѷ $GelPFf|hbwHX~*l2[~+tFyM`3 EznORk&s`;AuOa2~~sNPM\TJ߸nBM `<"PUSV=]pn\b)+iïo$؁c7 ?X!@FDUW,Vir1K4r]UP[a$e,N{T`C_ea~ `9l$uv[w\.2} ,ત8YQ(;4ssXR#eƜ.gsѺSRTR,&B@WvU~ DgE71]>{kYua ]3iJǽ>ʟRq0[YNMd$CFZKNߩÒ1`^˪z.?8"yjGUݖ(N|5Z5wC>Q%fSյT 31 ׺+8g@nJ$5N›aT$兤 XʌL7~,N-ƕV nbR Z)U))AvޜN4?h4Ts1{*VBz!!jקrnvVe4ң>Q"7?)t Juڭ_o=n*P&Fı$hpe-Ėx#6Vw#g@*@XJfDs:;P0ϽV }r72ٚ,ŭd[e*K) d $yQD܊ ,Xl덿֙%FM YUk˧صoeO.dxMW &I lLQ~B%RD+UDpf~ǷIKfmnܺIT>7lLBjivr* **'-@" GCcXP t&ZG3cAyZcρ𬪰TgbEN;q~o5&X㘓v;+{e=Ll/Q?J5]طJHxmdju\kBo8~c;8g݊խftCD槪=0wN8=GӃ+nQ6*2qX ~n/Bx Uӗ@QO:9NX ƨi^zT6{J)[ N"䟴.-{(G33f؜'s`y\P>v|XIl_,DDDGh>+hc@Hu5sT)p0 ρŶeuʈ"vA-i)U[j:'ծ^yŽ7cn&.Nts>uEYR/;&WBϢ^S7׺+TN=@ _}na,qժs8CFM)ֻ־XЃtUTe0B׺+ "\':nT];Xrp2t֕W݀K\`we7.*pEU$+) )Iz[h 6q9/=cMRjAأ;ySDe$71=9J(oT_SΦ˛^4[-.3] }Ȏ6モD,ؙ1X,^=]>wk/VZSIj. m3Ԇi)bK1'w RUފsxBP.*i7ZXDOgas+Kjb,;uX*];ZYm IY\h?~yF;Yz8.آ;й #;V$K5 [& ϩXXwD9Mo҂o9880uR@%-fns2 ay?hXe-A9.$Нp{[{oo6kPb$u*™&gƁ- zH}0ΛS=ipZmV]-ƍt-8ATR0gF^ݥs⹙XbR7 =_NPݓ28ш<5{+Āתd;]+UA/UaOu-vy#%nΩV<^Vr8rm}U:yfƷR?T6T7-:ڃC;r?WHMj'QG! ߩ8bfxv~ɟBcYQ~W(Q/hVq+}t_>=<dNZ+UF1mݑ)m\N ¨tK-Qf},"dzrz@RD ނm( B62Y%4c%ҜQ¶z9at߱|#qgz"95PU;w˺4|:rء2N rKfq4S>e8q CW@]lqs`m mIOHG ̞Xq"ʥét~1J\J13!O8Y+ naIؽ_ { +[$ εҾaSo^7 tym|/(TE_]u{r˶Ĕ=(+P^za"RcTZT<˯`GXgVo8j fšV8" m[^agt =ATʌp ɾLjK[un.'_ܭĮkKi0JzYjrAp*vqCQ˕we-Ϩ-C6$VC6K?vlG v `|>RY%OR.Y ~[f:UVڪ:5Xr%.mg?@ )F^2FSuR!*2r7AV#'dbolݷmIı2UNRȀiq,T7^S=<ʔFNģ챦ZkO׺+ض==ga£Z,+Yz_΋L!(f ܸ2%"ܻ. %i$-h!9I׺+]Q.S#4尞ArjjHC.5‡;wr^K9h[fmQ1D,0ɼ(MXu4J ;AmDG{` iiUi{O*.a}[u'VTWRWǜjUkITo.O' ҆d'DS=STo2~Ċ%X"Z`n;l|W*ޯzyY`o"~Zd} ,^Q֫sK-hT7Փs+`7B6ՊU"ףz2[/O0{Jb4 {`q2I₨D `U=%yOŭ^cgPRJ0&x(ѷbPSsZٴTSSQOf%BN1&5mO)fΘ$sɪ/u R;t;{?*aopjBC[k_)Mkݍ3olm,(VY2yszYuCh=vDT SB׺+`eNtai H[aέ D"eYc]Py Z[]+?"ܯ6| 5ҍg&l=zKl%l!;=gP-TRAyqߺ.!w$GD5cgoRy n29$]+j,20KJy.K$k݉֏RqītȪiN6FM2Rjt,EۮS?=z4eqf`-~(m'T+-xP&YTntn{F q(ɨ5-VgN$(STg+Cݯ\؝u* zO>W(N)kl>(:Y`n{ aL^ZPəX3 Μ;A@k݉ })\'`|zOzPމlf4'"JUmh7QGT4xdu'V .=lNU5h2P*cqCzAC=k`Y">KfLJf]`w붕pUJ[ iՕ>_i𶏦e[{o֙ f6"!DGf|z-AݺT3()j)sݯU2ZO⍊b gP0ò%N)ͦ^eA}20$<(&oS@3|qN3{붽yIԟ>0b#gpSvS$~biuZ>*.cuۂM]!PZREzv 8@Z%̙=ϙ5q]^EVű׺v:~LN:Ĝ0iNvLs cz5VI]YW|ǣ|uUED:OM>;VYmFK+\;mdU'Վm5xPǩƐRԀ rF73"@]뗽J~@`"TgY]: %\%|  |*},l,%n]rg eÐQzdn;)Ej+$ L,u 5[;}w)h=KB|D );\H2yn;WB ;䨴ry {`ohL/sp>,e[ܓ(L*ۆZq8&Nz׸nX'R ẀSj'|oy>ʲJ@ΟJ,GZwbLΠZY !UH|!a |Wv nB][=}y;˾[2cYSy+V$x=ZYI~9_SMqo]o%8+2H7(U"bO sҰp]M`Jv~Ws`[,MBBF 0P+>Kx%֞ +RF)>`.&''btӐn4[T⢶k]l|;U`YMM}1JjjTȦdέ:δHpQ1g<ʲX1_ǭn0 pV#+LErZnvІTھnO#NK/(dm-Sz['0'~G':<*},5LZZ6S_X=tBX P~en{qQɂuOP}+@bj?P$N:j,Yfձ4S %^tn[JzcVnS5 :N9fV~8kdX֡VĊGC%I/QlYλ-0B;h0xm~k9i0T6XQ%PȄnݶU3t@Ҽ,;pBvNVL tR0s=1`e.MU맓L0|ުrwZhۄQ$̣i0e{ 0f{`XMl'Y)>Z){fo6x]VZMZ%Djl2-=B„&B*AME,C|]z*Svm^]i0]i8SM2]ySL88?7_K*qBua7已W()A?70o$LYOVFC$ZIA0Z}JƟˣt\!u֥vYϭۖ$?pl'';tlWuvm{Vף|@NőJ尸u]pp~n[DE"p)_6zWJP$ ؎ $ 챪W/^xJGUoqn[}s`So5D^| gVdKm~l`XR]TK@CmߺmaHj O84z ĀjVh IWp?:`dVڮZB&@>b?l|ye5SrDv9UKW0z@j:!$XnÝs5Yj!jJ.u@g,ߞ}3)[;GO&1Al},ijg7p^16׺^Lz]$竴 z,l?' .F\jNH9~ՆЫPioxAйjT+qFrXU9g1ZgTܨ>)]:UM}KQ^{fov Xfnaw7Q#U5V;^;] ϵ$T5Sqp(m*ets*n6X]oFUְ՝;pɩQs(%̢&7pG{`*H$_+U|a;2m8"S3;Acj=$J=pH|G=kePUuignvQbFXofФj}rpZV ^L$~xy3ܾ!LWdgU:+uk}sb9YU֫{pEn[fhyY7P([(SW+e7R?$ OՔ2'ܺSA56Y)biȩ2Ik駱T}yXxT_ЯLj9z/^Ne)ưMM܉?dwP_HRKX&bQ NaӕD.۾uQe cDT|%c1XCbD-TI5$hNNB 8z^P.b`߸(ڣ # .Wt=gV tؤ`Ol9u=˺ dsU|ɿpWWz*yH:W>g!DJ]iRP,،4 +7h%W˄T@=n{=20frrS]{3+A4/n=J@߬@G*q[]%aR|n65+Z|EJSg,f pǔ*gn\\^NxZ+II)wWOܩcI䑨WN-Gf5Y{1* 0Tql챧5=!\x붝:Bu=T\15ucLYb2(1v1~ G=K-%_2Ge QPg[*fA%݉s(1OUrON?qs=]KYW %eD.Fuۖcp*ְLӸWu4ʣC"9_s`;vY]M*5Cm,t«Ⱦٻp0©Ҩ___z.=uT!?ۖΚף>AP&B*l׺[MQhTWVRSBz -KƜ%9, fV ;y<;s3QĊ}]R ԝy ҟjX wzZ7G̏0κVlC0T P18R(_ gȠ>־cA]%"E H4k;'V L;oC]YfI[N<ܢt|3ˮ[^/W[/mK*p]W![[niI GiU{P.. l,("*EOB ZSʊM7.5bR⩁]kjg(ńߠg"{~zIӁ V@D&p)EĦ|i9]*С3 tLU˒n$uیt^ջYZV  xVYӢ )AetUfGX]j}>mrjD"GW[=7k{`a1~#YSʡI]y%.bt8_=ض<%h6欯1{޲%**Ediar/Mma:]3gb+{`;p^z8JB[׺{n876^P2(9uH.qԪ6*χRρ(U?ےD7$Iu'VOsϮtI, P䢣Iz)Y{-8UR~M{@?k*;={(}fߺ6upvj~2>Bd3Eiq¨ҫb57yӅ>X}_s2D/u'V@I {Lx2VK62{bPݑO9Xgvƒur^J!b覵L)IU:EU,E- `Xcrv{TP^P"~g u섢BENu/ `69~"zTz1h}}f-%8f^ߙ9J@zʃ,;lW_)N=>[mwTu/+YF[Wr-<&Uk,S.1eeYyT[RS{ywJ:5iv4*Gc+Ժ+-J֫txH5(*zgTa!~ɾGG_kA-8Vfۣ >aUxJ(A֏6E$(^&ݪq:H=ny/VIe|[>?% svmUJ /UL< >&T:5 TGpm5.8ϲ"wܫN ;<̓AN/8bjSw'x1Q,q\X/[H1z̐h3CMVl>L%tm [[(2NzH:&Af>L>cUq;Țm[:ml>"ݡgS[{gjҶzWv9|k`XSE*/6*ɾ7[ߺ|Cy6<,_{e]x@jeL$Қ; y{g1-T#V`LhY3's /|+& Ҹ g} uEl*Omōvu/HusD3Ua%=LT01]-q "l1lIkѝ` U5yoÓLEVO~[mIMR(hLS$umjd[m8 s$"d^4d%HDE2NBTl!\s V`0]9ʖ=.uKmVHOe[>A bS嗟.5S9ّR0Pz~vaVĊUKlP|g8&iYq,8|+ρu*nK$|Zî޵ /d)_q6s\ݜ[AR3$-ѩ0TPρgV7§P{&Npuۆ0#P"/PIHjfEKS3%='޻&WUJTR[I`ZwbFe x@K P.:(yWG KPsw}ÍXe$>b"#_vŶZ H֎P*es&O ,e5lĎuEGi!Euw\ծu*u-X~Cl!t ~YҭMԡY}J>H^JtooפP'XG,N7dn{Tu5b0-(8[\Ջ| "!fޞcb%dvV8cU-xߌ붧0ye9sjq:Z7 9+ڕ`{` 4۟]Ċ,9IN|RLAէR+R8=.l }v͹4qnva7E~BjRݩr̳a9IƊn.NQZI"Lz"V*A_ݺ'=OOq nKHF~z>?dTO0nb]]jqʊkrPpuN6dg6GZ[zb~zXD55샹9Fc*@kJ%mߺm7E8Tl/wz G*-VWz ˣ Pcw-79I,{ݭN[b6&7qZ?c6vOSi+hQtێt 3ꘛ#M<mW.qI]R +7j n禢#WBkO,st OSz7i؛Yoݶa T*@|SL'3g+%~=-MS Io$ڝ=qmt ᢀ[pq9 _B2$ƅmR\ρ>ս[a S.G-aԭvhz$"9SuO"Wb 'HT|5"[Mikk\lEׁQdP#^kvɹkHn^tN<V.v[m1{<n6@@~0r~ E篿S溵T$f 35N8ۏn3 g]--ՒWɁ/6˫ܤ+rsDY2fkY̅⻲떧2tpK`cwuۀENjr%;_9u~('`tRg2#%W@tTK(Rb[nupoʁI8muM8u:ו &5E)ddozYtT;)aI5jͶݺÞN!4.7>&9ilΖS- 1ʶ87J]R9byQ+U$FO4dn"?4ڀyv!*i =e'B66%8=n*n6hLM/]VZϪJ8aULk$(8X|vJ2(G"jij V b eY g\M(]8.iH2K 0ׁ |/Xڮq^vShWgoݶB4VB҃ݾN`8i:{=~ jܦb]-+pjB|!m0'GBDZycX֩D(q H9N߿<[ .]h^}U.؃ @?9aJl$ EAe@l͎u+YU/5છn}u2vrUk;+ݲT@'fQc"1wp:yܿ~NŒ"Z܃RsrĊŖA uˁ򤜚Yr}Wu z?ԣ^0վt>͎y5:eR+tg͙T%#@GWd]:㣪 <(=#{`wT_0ߺmBYU2P˜V st 'JZߕXqVR|UAʫ Ozrq[ p0V!sTu$(#3^nYZ{*~WY508̞ovJHb1@L ugT{h~S 1&vs:Z}k Qe^IH59ݺ%Iru3*2+54\JNlDac5)[v%V6g1[ɂf &"T(2sgpϩlȳbu Kqs:is`z{/oޥRWp%ufƷn+HφrXاVVjݧUP)+A UO}H{`q2՞OҁE}t{;1[mlTa׶왈Alj.J\43?-IJJ`#V=qDoJbEdj)SqKFA)S]Ov)>l,_T*Kr_@F\VHWu#/EyQj㥧8A <<Ѿorf%5RS6uˣ]-J5m0 Ο؟tU%"'I S)(4՗޻L`qc٪Żį,AkhyX5>3  iV[턈TQ/3Wt"?ɠr~FZG;({?OcfI\B>t.U. S>T,ԣt8ɬ$6<b>%DהlI~ dGuO$bku'V[oPB2asgޕ#@*g0%z0X$~{~NE]u^m7,_k_^7߿O\kwi߼?HP ?6w:G0%uk-hO$eMz'ǭay' >!&V՘Ky$_)eV,w(+̎֯sY͉A>!r35X[r6CDsNyLr o P[®XثiFwWvH2x$9ovMaG\1]y@6ϣ̢5eIH}h[\~`e໧zo.0YI}4-P2 ?r(XwZ[̧sգ7%ܧDwsS™`~Eb}t8-r0} i)]N:ը WmtߢO3*)m1 ,W3칖<^}G=!#1>(ܓ쑹5aVzETsC"A3' - nTiJ1hy%7aV=t7(1A&)-Jl͒Ӑ0Dw{Iec< QUFݞ=p.z)dxT%)J> cR{ Z "ꂺfYZ:IfyZcLk掮&'5gV5""b܈ysj;:5D5yeSd4CgcEWHd wFhI倒AՒ= }(#Iπp8ի"+@@ )Vedo;UC8QN^T.Y4/j()͖㳜4QU.Ge4F,n a dXuM ڨpoC`bUy1#rժk3Ψlk'fƗI<5˱* ^:Qm)roJ-o;06+?-+]S=G!|?pѫk;Kw]%TDe.ᨍؿqvC1=JPG'#h= Kv`S0@Rx.Vpj):$mseY\ؙӿL.Է$Xk;A %ГսSxiy+mmU6KmR+pȖU,X͗pnv(z&@)O/_qO6@y]H<&WM %+۩ZoqAx s"0i;t]c^VAn!;G_랈=TIҭRSC7`T,6aSSr(M:IvvhIG%"Ei]oSho3[ZꁾizO'z ɐ %}q8 pf鲠FL:Ymv((ଞ5@θj]X_/"aǜcV 9j-T ;#Np[2}$QMTk"^}Ddkzk,58 >V;q`Hb..XͩDCY'36] J }3rq v`ڷѕWhWW"x C91B8do4ZK=rd.\u͘ n1DNܷ,eoLBgifp+g\5ܓJéI?H)qX;~8(՘󭢫Ɵܛo;.)oRXU1!_`=i9fR|:W4.I%Xmؿ@G/|y gBaAW*Do$u Tmul'$A?0]ـK{≱i?u0v"KG*`ax;JQv9t553ǹZ,&8~jp_i_Eun[*钌oy-nѼm@p`;Qa] &-9UrP"=s5!Ѧ򬋧|!hjW$;UMK ԾFiYco2'-nPM_PРo\x-62Ц.Wip|ۡm,,>NS7etQC#8a$Tmm|ziΊ?Y,JrTS< =vR$L/4|oHLzBiX*_NK6&tHRER+@x@}ا#5K%<:=~['nT] !h̨}n8:5 .u9*͑pLy4cP(/8NS!I_=` a 8Q/NSQRҪYŸ92g,Y=rnGCzd9;O;t.i|JL"w[+9L0FWÔWӫ/z:R,+۾tL?M4jR~X I_H\Q@$z$9c}] zpz](P"*]j Oww6DбѸC{6T6( P "MXp%tNTRn3<C0b8#&+tԏIYótpm؀DyAR皹*5 :CxUIΉةڹMZl]ًuNZY{B6VpUܾ-b5e @^o.9mp,$ARaK~TJ <  z&[p?Gl~ĵ~ DcqHC 1c`0Di@݂WRQP+oAzmI k\ϕ z 9yt:`p'T 7q$⠑MV0_Bu#senpΧhl\7`9$7 mN7lc,pQMQVDQxy{o?нSx$ .聁J \w"ޔŸU*iA7:i&NNkq*4$e=tfS/F XDS{}ٮ.HUlu+9txL5p@'ܖhد V6CLQN()9њoG+E\5Vu1AS Mh]Ī[.S0mm[{zCxvʸc]ͻa)΍U&Fk04Kĸ a!~CS5S.]8L/aCxV*f0p]+2%xcO*!-QBT.ֶlU㯱CTRs<6y?:9<{U A^Nz{ˮxI:-fcFɸ43F]jB<7mNm ZN;$u"*vkNcn05Ԥ%S`?֌($75xڤY*K\Wʭmo; .DN] Jžy%⫎(rMz~%wx8 5 #PS fTtվO>N3TŠObJ'J @礒NA[=vŋBӱΜWѬPpW ]ڷ`R@EF).]BQl]rHtA^m+'58;.Go ~պO;Dy )^S-#2+G܏ g mTS$gԄ}mUpD/ۣT-wʮ>SX!!NRvT/|WlH, v:\yO|]?%aW;I'v讫giRgPwzk=2$0)Gܪae *iF;lP"Bv}Yk`.f_TdwUS SaF|k8U# ێd2{owNhGEAj43zǻg?PPQ,0BaƤͥW\a$=UFƇNjNB38q"pZ ܗ &#V8niY;aDUkD/z"1r,$PW0sfG܅CjE(OJf6n@}/xZ+o;z٨f^ҍ@T$w-4&ګF~ sy1֪Ն{F\5M`v"}- %p9DA%fQbe5ۡ!,` ,Jb*nMd)jGLvbݨl)zq᭐ -iT R%UQ9co=U8O:vk8A#=,5Ht|}$PSWjطY@*ARlW+fy s|e?))By! JHZCTbz,;5+a)տJH7.7L&yR>t=G?%Y{G)M5\ϻ1? ^7g[]'9]рr$}.:N*)I BT^n@HqB(ͧ9ewX*ӟ1!z!cwISF] @}ՇPbӔ>\0 0^^beȜ+c,_@zF,\yji8 2:tH{c$=gk}U#!5OMV폆UʹhnAձ6r?7o;4GmwQB&,Ij]sqMspcn Uԙ«Nw$M%.{9T[ᣋm-a?)U _z'9!^Zs3,ϨM+tC,MOM[Φ;5v5ے:ĻX"TXuZY8gL֞XfUULL.Pc[,Tv.pQ:6aS1i"o?e.U\V)1&kGA*"L*Y7͇񔺮}m^uP>*mx JΓWִBdv E^l(!HZt2rj3&M(.KhU%nzi |6DWa|TEѣ [Ze[i&}euPG/>GܐJѡptCM? J WUv`߆nE$leZbY{_ȺZ6S+ InYW1sJޛnDY&̶Zb6DKM}UTuUK-"+ѪtXڕDCLU" ek0#L%\0n)Ftp©m46D>]TlĝͯjݦF>2 |Y>+b!z-㹸Y.?f ot@ǚsU (*z6D, uPG`G$pqHWh{"le䒜׽QJpʼ2]]qi a)Dny ]wq\{wWyzLPg-(w&;!EN~AoK ܤOCt e[Uen@֕P_$;tIL3o89OGU5\EJ^ O[uHt=jDl^|mj8](izE&. R'^cV&'~T(d]{ e.`5.]Ʌ^ju5$Ϲ4k6D,Օe-ڬ(dmˈO$L=v AAKрnk s=2jyoD ѭ֛bz hݗ={;B\rʫVQb*4aFix/ ;с/hR As`ggo[OC;TzeIu\&2sA&)+omV~-JHN5q qpfU]kCPS' gyj eIgf"vAbCۃJ [xnDuZ`WRG&,}mT5p8~W^)ܒ,^[W j%.A!݂DgaV ?[1SWw2DF>l3pUYw. [C L7 OAOVH&H*LJMBѥXOտU%V\C 1ɼf@hW V,;T2=L <87-!Qz'[*fz-zq§! ^wJSԅsw5W#Ʃ olY<+֚x W30KcL QE^Q{TjAj{c:WIs5C PPY\vM+vBPb`:&XNc @yͫ2D;AEML/JUF*xդ68A%nJA, DH%oWc,q0kcuMP݃)79=Zo$i(},?4~%<Ю"RQ<Ք`Tae JhnE^KՄ]=(qɬ6Dƪ.5;[-?ps*j FLx4eD*λ0+OnYv-4k Ѱᗇ;ܣ3+UIջdRݣ60_JYѫC.W_rJS)uHXZc}G#md\:`YabܱċGf>Nϑ4,5Y.u\jul=k#غz*sO9e߆h'$1JNwb_9{99$b,|}"큓cy}bY>)-Z2|ՠT12@LuGiU˼^`mF"k/B>ꍼ߆ʚqȺ^^J=k֩ǖ:RN{eLS !)هx$;e@\z]3A “SŎ>V'wVpU)`ϢJ@ R2 eaI"Gt@ΔƲJ.<̲O*'|PȢiC)' Ͽ76' @+'5ܢ]ڟpɪc'r,Kv˾-%;&zV-Y{v<@#Yc%K$J.*ʅW\EiI> (IZ=wA4Ӑ? Y >7`P,zl^kO,uyqVC4J5dί WRE*¾y@zn%4>Uu!b:~|ǀ"Ndjz+,ĤJP0̖~co_M>@XINNTJe7&ml4әuK} Rɔͺ֞XFT'}:P!ZJᓫe}0N~TSeBue8RЋ~V%HG08g˜WǣH*}C&^kd 7j t1fvֻ['SӐ?./'oJ!6nWCM7&_dqצ a D%leuD~Z; 跱Ч!ڷzuz.RRm޺28`o]hR1߮;>kVY{Qƪ*9T+;\!?ڤ1D,R{=Ҹl-Wo`VU @s@:ءug~"kfuK[YIoJPثQ(l%(~Buo0aa&P<&$ܾu''f '1m|tf"/Avio'X5s}[1QBF0|$I$ˌ&H)7Umx)oCy% KCe_kO,{JA9=5Kn<C }+9N7D/SpEOS2@ 7oC>"I$SM͎Q|=lix"Dٕ9!]XJQc8Pr9c!U>-> &^BMSvcك=/^([9CBHy]e :| U''Y[U1XTC1 ׽+Eu!_֪RTj( n}3QMLj2lq*<'d~"TjIwHj za.N0+ 7 LmRW:ZztU U]vL/CJp4{]uW+KO?,#O|&uF;Hoi80RBhCTڕt5vл)_0ºɵ6B: {Ɲ]%v>i^kO,oj. qZ5锦T]x#Awp ͪx!cTmT;,5=_Z(ť\g0֝'j8l=$QD}Uw+,H oCƬ U3aUź;?B%DѬ" uo֋/ >E,)-iL(Er {Js(fؗJnP?jM'yAsy6DL^ըJL1ZpYyGΓngbs(; ШjD'乕U,*Ҫ޻o e**t!??p>ԧSӧƁ昃l-*`kz?XdAT{S\ɦ4D <@FBs~U~=%qu`pmu5;;Է}Vb;Gi$P8qO-)*\}÷!݀@ TܜVECj?Hh/$9E[2D8=4 `N:M]~W|MXioO^X//se5qؖ9%;|}}BG8fTuq=lɷ#(+#PʛYj(m8e7ey)b*lY'|;;!KnN׽*zxXfQVN7:grЮq^m=6U,Ks˔Ww+8eu* FR,w՞ۡg12)1y6DL}4oF7kP.cGǩTtn'shJ#^m̉PAH{sKUbLj|tN٧!ڷTF5 QW6ثbGHl$'iomF:q55&GA)wc!{z }"h` е?W[7f+)ƪ`T5V[.(ɇFgotP`NBi&#Oԗ}PթK Q.f;e'V%SUSM=N֨sr( ^KuKJsj{|"[6KL8lO M8~ L*7 -dwj|Vӡozo2StJS5VZxd~}KZ=Jʩ^:˩8M[j6" Uߧ|w(XC*Т^8Sg~Mb`3NXw{ .z~BTvT*o,#8p؂U ,0~< =轇G0 MH Z{bfaGZ?:Lu(PMx2}HY zc4Xtz%ip=l7+f+^"1u6e;QzovG1.UMe dkH-HU c(qTu/P+NܓsX'_$ʁGw1MB \ҹ_|"^V<<걇pa 2}{bbJt*eѣSN=skTacH)gMC4Ds ;za2.pPۡyYw4ZT&4أÁ|Vl६GV*ŰX\q Qt0K7XIDٶR6=L +jD53Ϩ7K:%20[gD]VoJӧ픦&tô tP/ ~Ltɢb|? 8ۨ1N#,eո'A?߆<>ȵIkĖ.`s;|+XN-G#+^)~*e'OyiӽqY穩1 F4F*5=r1k#oj[e=dsWCO1yB$")ˎ+SM ^) ;Fub 7xlGu 2N!YJ^} /F:,Enj>$0Ђne$I֪9&;'t5U[qI|Un/6DG*G oݷWCٶ@=USZU=Ԃ)Vrr# cReӁ^Ƚn3NYAD'qZ`['|" j#]=JK0+.%x#)D.@ ߅GE֫*UU* = &qDJC؋'[!F8O/Fh40Ԫ=GSCr 'E[m[ԶMܠFiVIRrJRYL!Bǩ=:'D\v$GWJ:m *I=\sEep #JǩOK=e@Jsm RZ]O6DsWj?&a,B$a1k/OH@G:ڝ-˔aRW8I M!OmcmnxQ-Iwn\Tsu?T;+Nu~&t 9!&1tbz*=JflO;P"y\j / ܸf> 1/) Gž6 qa*Q*y)F}t'@:8vGy+ayxHS#jpu?]棲Ɨ|&ZvywuimxY]AİRd}eNeKہ{ a`c芰_0O H`/!G~u51rc+4DnwW8RH*0ı4Uz0/^|dC{ӫ`߆hn߆@4WrgIvνsWPۣ* QT6< i%dw2wk0Q]+@J`///6Ds[XbC%!HeO=qr-J><ݒ~tyDՓGUUS@.T5w!U?vn$ap53}r> 5f/F]!SHڛG_`#ShjVѬd2񖯵B+%bbìΗ#߆@BW]W=ހY-?Tsu?$ tśMEeKJ1:CMzWg^5MK}0ݒmWPX'ΣoTkuGCڍ^bQvu/J`S[Vcl1XƸ:'WTFĘlRle/ o=T;E5fwŖS epPz Q,﨑oUSm:Z^3KO@CƩbJXVAic|oH]d$c2c /r> #AuFƶn_@"Ց^kogC32`{ѝս#]1'bXmvšf/ul1eh~\8e@|9B68UO5Ui}HH8c8[)= <7KF[z5¯8L?xu?BTǘ(*fm뒚>o++4҆Wjjc6D,Kkȧc/+-_Av\4~u?$2!u˫NW*0O_ ٽai/v7D a1ط! .EumbR^5\ 9W]`K >[Wy%p|nY(LUP>M8n'4D7 @i^LFr*[׃]ݏ>Vjj̢#t(RBHl݌m.4SUusmȳo-b% ܊U䥞t`ɉFI/v>q'AMKTG{/I`./C"Azz2 ͇+^mTcTS-[,KFõ+Z4Cm MqlV F+H׃}YǴW e𗺣 +wu?Tt>K.ԫ7=)}h)k[o2)îjc&eJ{dYr%v ToB]pGdӏoy0STEzi;m֯:h=: z-7ڷY'N,Ȭxʯ; I󺒘6g P"P[:w%|J%gS3&*86WC@}ȤH҃Ua, А aJ?^t?lUzE%x#҉VB\̓{8+n N<~t cmʀ d_+[@s>&PD=)-C/λCyxTlT!1TCƾgWUSԳj#bCw 5{xOW|\Bj98,#y#.N:̜r) DAgWuB&FlV9iqя+*J@Ocd'Us*||K}ND"7Js U% 愫~}1!vZep+zk~ķ3 ֱ͊P~go`^@`:ˡ&f &a Åi4'/MM1j!$ &"Js&j(*M+]! 4;oUXzV`jF24pՉHdr)ڶa)\`9JZ/ib ki* g `03f01@ LGOU/3XtKZE_-FcK^Aŵ{*;-" ,FtpMW!,Mє=bǴs$oj-3h6pZb@7~rN)S) ¾9ѾL }gcC$-dwPZSEL "mDߕ`mmnUѴcywg /3#da3brZZ6as?AV_i09[Ƴ׮Ɯ&Ēӽ0|JoSUJG[ώ޹S {pXa.ЗduJ߁˼Uu&uTDVLQQfEhJ=T@|Z?$޳ g}³uG[QJ@˯pLhZƅ:}95O+=`Ԑ)\HJr1ԻuTAn b[=mLm 6aj]~yNWdԸܞSks%3umvWcTÃ#UV}RYܨ;] D,gaFx37%xN_S f9`H/}\Em']%k(HZSUyY#,lZZf|vuΉef n&7ڷ%aBtF [pr9-z<О^pma,z#ɤFp)T*ģ6}Ƙr3ƫ QW}_HVkb/(+iI j̟4` C9Db*P\fQ,?Tsu?Psg!M rӊ`ȒLD=n \VQ2e\EN&-'@Z$4/ݕg۫A,+9:ú1S{&7C`:q:7h0_zZVp͝F/1M#X\Swu?0љZ X78>11ng) hy:=+`ƀJϳD*j"ME )Xq+\b?mfϺ UN0 ͵40gVyw T^kJ҈~;2ʽޏ%nӧ@k xВ^|Iw4Ol }_ȳTm1Xf2!6(HxSL6ӻ Z E|dHR|Z^O33Ԟm"w%|BuP9"xpXU8L|GK[e@^J{ ƴg%%{(Җv"'TypF|jw Pn/UKv9,hoGoIDtS\=j2=Z#!+N*u _s[?KsÐ9X8&M̫}ıV'_- 9ý ; b}NJU\eI%&?`ݎ!rF4,]%.33LʓdFhZ&ߏ?C¡ݰ9A irM3<2,"*S̪V1h uHv$=|ヘ0i#騡-ʫCqg*bA[-"iA ^/s@ȷ7~i 8A(lWWN裛QBt KSVIfx\gC'~³mԙj2lMnmG{pu?5߫ ?EoYIJx<`~A7rhyfgyK [H1Y6sccUP2M躷<;²\ TaPT *h[ƮС*!';g6tGXE_'LUϋsCQ+jE^6:SE 9/-*@.k(#`0j<[˸:V{pq2'AO[;UB{Ɨ=Ec߻@NUJGRA߭џ Wя*BЯsq JS9=3FdV8$M>N([l2WnNѹҞH5k.c֍6ʫZ`*k E& \vߗojdԁlx]Iw p^Ъ}JtKW}k{q­&I&LcjNʫVet/HBeA R4<,;pB.mGK@dv]ֲO'6w4s H5ڨG2E~!)?8$N^ RgpEd_YY ߁lKJg*Fr eNco-tY k&nƋh$KBVz;;Fh;K;EP:* x<  -E0=Wc**"䘣Sc E! ~rBvNܘ6ZX 8ah! 4+xZm;ia]plK0^]E!S%hQRvu#ux>3p7P2,|')A4{hZuTjN.͐ *Š0<ℌ8epSB-)D2A\rZZh/xO ?l`$ kk ;֭X0M KIzpLoo-[":ZQ{&R`&1{+KrMIKDwvF+A_̽KDuĽ_ʡ5,6!}䌄\sGˤd@e_U>1] !ޗ!nBV"ii=  aUsL:6dQ"_4̷{3EK#'Z &5|M>no-;=ۄ"|i-.`-Hbi[5{h]r Q1OrʘxƤb4uM_. HC\~c0<)--=[D(v _!ߊXc$l&4dz7ۓ!> g TDy:J`z|8ŭ@t#{:FT V!\4Q71+}֙*{XmS`>2B6sDWY9 ]@\3Q8~-*.͝FW!a::3_ݏX־\B0=-zZsJk!yD[D(+ooow 8x;r".8d^t`Qz5497v1iZaG;oLNHޡ# ֚Z0_Tsu? bU)klQf#msZ]斌~ô[ۯ@oF:\sپDNʕ0rR}SxE1#9ъZ}5aBN ~a%aӘ O *l_{TH\^otr,;hŒrSˎ"-Jt#q8 _uZV==Vyn31`O&+e*0wm8c [,:WΛ~6KADm\ng 2eB$rBk~DT&2 BI`g=eP(C>8p'-ù2dE}S>FmT$Dwap%z}kY :^־#.O|r÷{ ʮ͡`@e8q# HK=z'OZfӷM%Ivv׉޶ǖpM b'*_+Rg 䄥X+D;=s3{Əs˙*d̴v?T0"mF?/9^xI"$YQ2_!zdB7D_L/s(z*:V]`P)iOE'~2G7߄B.^%du?sq}=N*U#n)evSRI')Ja%Ud@ezG)[1 lSCF{u?0fP6Hөla3rln0 Ow̨8hxFԲ@(aN7cTo?^tji/+!ޯYk 9"!*$/m3~w HgQI`,jS^utu?TRC%d3mYk0GӍaZX ]$qT)ޡB-맏9^ F(t2Dz4J'U6Hw4˾Q~}HCee Ue1J<[>!z"8-B㺾W~u o-sc4/\$ c9ZM^LBu׏c{Y9=?!kT+b`֖-Ł\7fu?"uU/Rq5zhQso|n߳@X +1p-Feeo-N6\ֵ`PZ:JW_.绳,48TSU{w 8v Z1Vw -$tk28ĤsGkIRjPL~bVij|#h:E[GC춼߁"ވKQxC;7"7>mqsQ>5GD!-43Z)k 4&FIa}J%`e߁؄"(nPJ3fu?(rާ66-µΈv9}|)yBl 'kB,أ__ΡC>w]X8ªϲdsH.HB?rtQN?9v hK T \ҎF7~den7sf.v(;puz}W'yU=܁c^lF ~!j2Vc0~P*V c'EfbhuYfr2Fa >H`</ 䬄 SPS. uֲs#: m9WZȹ==9SydTUJ+S0{_v3I6ڝ%`Qv}k]i7eAR՜yW\4=hb:giͩ= ;8 ]^;UxGǘ*~X PDcgyCHb&}aq8)er,z|ʫ.( wy8Ww0 4(;Ta1k7{^;,M(p~[S˾:!jA*|C?6EWC<<#FnMYrby*>TVs4j#ǂgc"m_@Ϛ6:L| R WC\WtzpnŘ$( ԫqyUđcg Ĩl mm4b8DbwwEb=l c-B1{b%lԅj5 xR?!'-PAP0,9ӷWf|d*:+1tx[Z9"5/y*oQJ)#\dNxI3;|hx "LjUޫ_ޖ~:>m6f"[}*:j0N+4KC{GO*(iʱ'e{sTg+-*XM{w[˸c]/#>\IJU o߸&f KW7N~B[[\_5rB>`UYKDg3{cA;3H[O~B2+gf ,w}‰($?DXWxeڱ;,Tl30+4]G~4nqK{v((E~rP5Qڲ7ڷ9rBZL*bF^%%EJhr+wx̄o;Kա%~귖]ݏM'+"$QT%UQtFїp{{dMfޗV3?o |S/4ZL)PbY+,]}&OmbD͑\D)j:'fu=>@'<nEjN|N߁ fh\Mj&Z^ ǃDOQV7ϣS$"vX6<2a?ѫݴUb0p`_oҴ* 5R^"gD{ mKYa805 uYh@'xXZf:T+t)TN6=6w*`o-Qo=*@,S-#NtL*b{;p9oUUtϝ]7ګpâ`UCGyzXnl\|CYm#K.&-/^R}r]zSޙiRpq^ݏ-ߒ~͸p @$ҷGz:}T| VSXaܒP?~B-;Ӷ`]Ɲ WcESJيP,1VO3p$"a(?U {5Z}1a.zs{ս(##~(dܘ-I1ړ(W)Np.TmS(. ;^7@8 #!X pOUoeNpUVi;^-%!+rz1imUݞVh@MDc|V :ѧrX؈~N<@xK«J9,rR/f?BJ]?u?DXϽ " ΛLg׫h- ^%K*'~D,.߁o- <ֵT v>pkn=B*}XU_hiRV_uТg9s" o׍sI|}QCnp6i3EW3M$>9Z)!f Df؛Lw4Wâ@O8.iw c&YWx4Rb N~(dnN;63vOxQ#7H?2(:Z=ek!Z/}Hnk AYMHܦB99Yb́сPw ,a!4!R2?eVR'Y)\FFZk%vI  U=laƃ3ɷ߁oyFtCeW HFo P*[#}3m~u,]2X9ID+.m 7suv_O> yÜDZqtȝWTJF!HpPu8$*@PN~hitBCF(wמmo v5:îHOb+ʱ'yJCS+Yjwu#fEB^mӴ[dmfF22" ;08IKACXy\εO-Kn[>pC$2TtoaFm7ғyC;+Ug~ pn> [˔ӴڪJxf7h+8ns@xa>Tv .u/罺FG[SM|[ٷ8uNV綼V.4q8oޜLI~2k2 J~\PtyπgaMmQ[eGK>nqNEa:Py^%4TnqU@jN^(F}r\,$=Ś -2yow 'Z@1Nȭ ) W#E~/)zΝ"]L5Ҭ*0xi"8c҇N~r:Ӯ_mmNxnk98"$զI՞pY0 eIit-_m y=B~]vЦōIvhg0jLbZgbCPV71 c\7 yp+L4w Ƃp1uQ}8׋t?c(XdOd21ʊ0eu[yH2X^ߌEx@ȷzܙm&.qQ\|{u?!Ҝs߷>S`QTE̴S9.[ @Ɲi1kE H<;-sZFVׂw6xy| -&'H*^/NѠ|ڄڦ)qS}N̟aH%ZuqWz`\IԍeXkQ.Zөt␅l]Ջ;D֫sD?uٶ˃ƿາGq)!Ds6)z<*?y ?Ć!뢽"kjRa2e}IPᚱXQ3 emQ6F,O, @ +zMe šq=%0TDG8`JJ HÝʇmêU)SgsTg:-]{X֞˿FR r)@eXo?37f[Jlnk җTV)@өSAw($\JKc-ҡ c}T']=)]d<@`͉%f,aTSSJڵM( hFYx~1TB>qi6t-$U8r VA{8t7"U,c(("@srw"5h\y m˅#Nt2Ds܁&q o4*zz[vLw8ח0"lSOW:nliXuIBi"[%|Eza-oYJ #F2\P8NfbW&{2[H92Zjxva~ l: S*`wX79^hveb_;&"cgrBQ)4,&XGGU *\ HT5CnqVHpcܒ4%/楟]. nrg;Nh65QH[QyKSYYdu޳ A6)J:b[KW;.|XtzفfbWկ\ s y00יP^K: ,T1  LʦHZ5ϓ,n zB –8Ne=gC9ѫ^b8E5atFF,*w6T)Xc|tTcnVEX'iタu;[J$i(.1ꥌbqI<}=""lUD 9ۋ}ebrma:ecq OwOW[f+喎5z<9[heti2yB[T"20m;O50;=i4^oQ!B6 6_WE#_-:{Y㨀(0V[X:/=5J^ &@oz,֟\ז8657=SHjFE5/”GqtNg |0RB`:Qq29xo<)Ngr,GOB>/qZqYc3JbW(!=2w'L0`$g™+:B{/Χݣo{xX*4یʍn%JG9g**0XcDQvɿΣŮiNq66B<3;D5 *"ai܂lJ8p>ֱ<52һ`NeXD0ݺoՏ:6wBQ)emE飯-̺>"&ʧ!0vZ͙\F@wzk>,tU:CaBe)IìZ6o1 lڿv/ŝAo>&݃I*܂Ckw\DՀRyd>#OA\"Gحu=X=>aĥ9TM%G lyf$RGy-E{ĮsGyw\/ r1׸DF8`aӺk NV4Y}$NU9Lb81l[=FR`ԇTw%r~_q3)yM3#wTvқ`TSOX$JƋ+a͖ HrzTMpWݤ8 aZyO̾;70J6XbLJʄaAUBUJT|UŰ F0(CNmf8 /8q]E$CH'bE\0#ܲPdj{*c}a(=(lQI3r=w0tLG}:zCOK,$5;D]-(k1WvټW$G4̑q4ĊM$_`@S]@Wx>oZ (XziEe{g\pXQ-հc/9ӽ9'-h7zXwm6R`D;,vc[%tE 5htNW"5SUz')3 &2"o:w*hŠ@m3",AmWk︀ľr i5:d<Ջ4ZtP$$t)hQg A_y NU(/hۄ#"=%./C,f{ |dz}7:49NHqmd`M PPx%+r: 8~Q8ARk2YʸۘiEUPP3sȭ$=v,U=NQq ];ݰڨմ2hкFfqGvQ1M($L1SхW~ 40hpL|{kdp4hғ[me/1.e9%Ê K3!*|9UAmƪV=C<m SI\q+ -f(l^] ?Ғ"a?ɋ n3m@k Ej=;lFaꬪZmEZ[OWtd!U!tQZ؞L/kX@IN'1B@jDA.^3nim(i~(e.䠬ʜhvp0fA1 J< kwX).LB3%}75bZiEI{% 07+11VtVAT0~(2=. 8w;.QaoQ}{3+샢 iWc|TxJIZ@6Z2ᕋi+i1;jzg ތ=U?(RLN!b Eţ*2Y;<[@GLz%jB'mwRnQ+{#=4zr{O х4=⍦5X>InlkF3ElU{x&0j բm+$hri i`MKFむ洞 Hyfi %k2d?Bo^H}s%x}n*xop` lRwg\ ^87G]%z[aGk[tnK1l +:.+3CbnYkC8 yMOg\RvP ׶ΜUm/i L1tTN 3b(:Ռ,egTh>6 0ՠ*=rCw\ ^RmTRZh6^ɠ9Ŧw8l%mU<FSτ$V(pMDh!(Yl1S bND :4B;3_EEk rM UE M5pnz =6 i9x0lYx~Yp\qk7J_!74"}E99ޛ+(dqKC%m%ff3K)9:[`8Ō{zݴN&FU J4(7>;.^tR&+6%N{ joO_Wu4G *n AI,P `ŚPVDnأхJF>F?φ&s졇0\13{͕S5'UD3}3xɣ.&cbJ69b(nZW]g~w\,PFDe^걽yxP(,FTMuc,9]dL0 %v?SQ ّqWq`mJ.g2["eUDbD\VjMgfXO43RoVve2ǩe2LK}SW\ 3o4w[c(4M_-oD}i/B1_H{QJ"BN;Xؘ\FiSׅW"=a, NbF`wwPb RszN|IzO̭ls\u0cVgL[&M]wZǞW(lm^E Q*n:n6 nl2 ҺJ/DkvjZ1(>.+kOI}#29~%^&2g|hS󆚗zJpi$=LQS.Bd3^.^ 7U׏n!^/Ur2|Hi8K(W\y%QN"W8?ؓ^n/?8\P!>y>n٫p^ϸ y0|E_%$C[x\ PZ"AH=v*07Gau ?ǥ'YNUUm9X(\%VC 26ڱ_M- TŻ+]kѭQ2xTRg|w\*t-(V=qQ3}omzy;ΌU+OeP;I\9m0wLx?6z~ BJB?CGFC>6qT"iӻ5Vհ K++F)3X߰;+g|[('s"R~Pyx?ҰaE`VH*E*51| ҴrJS‰ZI( xUEcZ+!*)3Li&!cdDh+;N#fYQ9T\>..hQt3jHbˍ<`nӛ!{4-;lI|ƥ}1 .hy es+lH|ĶE _)H--Nc n'A=VQYDyHoˢ\IXW}um3 bbd;vqe,cVh7f$:51hHCIl ̘P-jUXcW>HiΝd,b-vV.|\/z9%,U'q6TO)CS+' ET[[>yJInj<',F vR[1<&8*GB<~F'c*;ri=ڀjZOh]q9pJpty,jPjVPljaW椣AO(i1DW!*X3F3~|Ƴ78:CU Lm{?ּUv GR Zͦ uU"V4sU* u[^d@2xD-rlLč6~N΅8W6:a2xZQdR]WLoq$Y#DV4t+QRo!RWx30E?п@܃zC7h_ܹ݉.@2V>xL͆ ވA-wf!f/lbfXC[@QusWFڀ;oS(^0K2}7}訴}PM=0_PѺ|C@VƣX=%sj8\"#*ǑJV+ѴFHpadh`b7CV|)*S7(8w= 9CTݶbnιNFL`!*5:HHª9~1)~Q}N8%lIZK|bJAm ѿ6㉋V6bCdhMw$!KkyB|Ϟ~v.)!N,8kV9 ܱ:͋vӱxvEa]3r+FHxs̾́k<10R*\=VxӉ\ wV[g`L[YE\!nңe F_) %gSƍt,-F?T^6=t3j1q%՗ر,+^Wmyd-F4e͆Pl ձ|9*0tY+]}h9W)2$qu-V[Kg+p/'h^c2 "0Z_윥9-+-1p][GUurSZ{Y\梺dRb}Lʣ?T%8=4ƪST%G3R|8@']نu'?=`%}{%0Jm ~4HaM_'~N9]H0e  37nѕ'F_8b4΁[kS.;(L_5]P ;Y@KjqGD!.y :)(|ŏy8#hoţc/vXvgZůBv12OroC̊@G[=QD%XVL8, 2WQbh37_' 䲗${׬d8kvA)fG!L_Ik'ZުGO߁]&xNƲIz[9omNzl-B%䭀i_C5Th>:y͹D2O%I/']Wj-se^'zu^ AiUōkF'Pz_GYajNч.tw`^pndt]/k9gۡTB^]b.-v$z#ѓ H4vTLz9"~ h\( '6.X9><&UEMY|.BOA# B:'0>U(97QA$OR[eiCl(:U&Z+u*?}vҲEq^t[}`tZ +$p0eaڑ5#eL VaP: fK8!X >ǭ$!!L.A ޤ~RRAds#1(heZ =>lG:g4Z{]jȐUceCV^Tv|ş:B2}sEC8 #W\ЀSkО\M{MLޕ9Y[0 !P$^jCb^e9vf(_:AZ0+g'֟!|:[术!Ovng1K\,0]{&(ߕ$_fEz GL;8EMv7֪0@Y}ǟ>V6aQ>)S% wy~/mj/1kmw0w5pڻFe^);=͊T:Y4L2ilNLN3ݰ.hϮ9^pVEu'yk-x%pbw*%nDv8{pTD5SbyrfvsDF)7wqBx ?\Ԙʤ7[ԂVw?^a&\1 ;уhbņ+= L@8&ͼQG˭~lq#" O˦=tNТ*v*}lb5u8gsZbT K=ۀʭP^ a#B+ ОyDeܞ9jԳEh07;Q~pg`Z~ڬ;&Vg Պ26d 5r_@\%i9V`t'*pRV߁kT6<.<G&ܓ+W_ׅ‡3^a$J:)/J&3-8ЏdT)z)mϮ TP4h -BGtm{ӂNt#;jL+E+q~=ec6:y*5"B besy[WbƟD;#rŠ ڡfN AT"k6{1D,""2,DwڍVqW?}n縎{38}3BAnQ!-Ǫ4dl[iU Ls h#O< ?H {ϐ?c*/C)*^ٿv1kgc WqyЃSbb%23W71 [!z =L#sܺ}ypVSY^nݮ"a%Zb;mZMFl/wdhuG;q1x==& о|\xκja9FTbQP ^+ L0Ux0^ͱF;Iq$8o6Ay :oJW4ٵ߁!1=e;PUY8oZA|v)1#hӒC$T$EV~{CxUIP``fn8jkWQ: ^[.ђHکbe/FrKZFS ;ѫ{:&v~D6\rv4~Y| Z KEj\U(LM!j",/l"^&ZȊ1&$BDG1e'߁=_T)-k- Y qs6&Vp_9DSp9cugR{sJ%Q%p'ZN^](eDPŁ7oT"#9a^yKԖEKfz7] )߾@ +n1Ɣ Ã+ I- "/5<1AZAq.Md{W* qcTS~GA«+zZȘiKekPoOCXht)ݹ#|T˻rh$M{=)d-f7 E )ja0GwJgCr8]B_\|Qw`ڈzbh`RXW&k...OXBGDKx-. a'u$~*sz; qfc~vN|%AOcsWq:QwqGiz\m]6H e*u\jbpsa[`' $ =kPWi" ynrG'DGxydUvfA gTAG|j6 hwچ:#[U@borZL.@fppn)I8\"v~6}+E4xiZOw`';NllG.zQ+9@ O RV>ǙG"^R)c=uITEq~ ,w`!VPZV]z[9omA m26\uv|I==\Ƌv%ܝ'C32ҋT:05=(;s ƪ:­ #VƎEMcHo*' xQ AgM BsCQflBQ#9 _,-E02`\ҭW-*)(cGD!ڄ>[>nF#Nr⬉6IīǨ`ŴC8Zt h}|ԟ|$m^,Iz*{_r 2c*\}_%z*A=Q,ukcvz[&=qQ`x" +gv |d8Fϐ9Jez74K%Ѣaj1+`hm*ez9ђV|O'Aa_ n8aR\Fy =>ΐ`4JO{O? ;"H77:~L);h:G YYã^-Bn,  [Chf(LҠq#ҿB%qxkUV <_s\bp=U&+b9IBԆ4f-_OfUx+w`-bXҪJpr E(ygZB\5$/]Hz:)]CEM\(JSXJ\y0rX(Luʡgwdȏ}̚V߁Ҋ2iJ O5J~1*xκ6f>^SI9CȰIA/ 48bX878Q1N7}9߁vbpЛGں>w(~?B*E>nqNkl0hTFϠj~1]5U)A.qǗ|FΡQQ8z7V:oL q.QAOY%qlcrj{1,+i f@F(x+q|gFαo a @<ѻ$#J+ (WeDVx{kU(ۘ?VosZm@lqFLwӊVV!7j9)[ұ9F,t'<ǘك ]"+-2߫b`4&6Π[ڹ}Ƴϕ|Z$MRC-sAM-Q\8tMGٚWWԾUAϡ+߅ss瘪I Ao0vQk3ũMV,eEɴ};B%U/nca(WxꣾRϮpU\B⑾Cȏn30ghTHiעa-ĵ"w+yWW9J-C? e` <;0jI>-MGa7Fѿ[nTNE<^'2H]t_$VGΨļP k;qim+ԅp]w`^9TpdJ Σyo֦"V9h Bx,\s?mdR>s,HE̠/,18 zF\ƿGz3Wd܌yuTS/A+fEuVK[vjLk*Mzj-JQxG"!l,c#3p '[cX诖EWZK#EaWڤ#1>+iEOI2.Ai?D=#W Ƕvn8KӪNRfbۊжލ~r芊K@ q * =Wvz" pq ztT.(rP֧=K C8]^Tz9?(VAJNnnH֎3= ѿV[hXh .KD&d`Csb[^wZ54@KEm g/` r2C:gυ7_kc>Lye+jKV$F;m7q`݋9E1Ϩ>z [Mw`sy)#?|7;_KD4Mx^|PQK@g6F.Z:aMܫeE#FA~D9zګc1BCPӅ/Ur ]VN32"I(mqR_Xdp Ѧs`^W#{gupxQ.@NNK)x ]y&9B Isp5ymGb nSxtW`ZeqG*_i}qZ݅IfJ)w0QM4D`lZP2FJiFmFEg'Myy1Q=qTqX4Y|ѿqظ*ءۂt+CH`4pYyOeW=ؓ{Ó1Ȥ/ͧ~oS+ϝqB\_7_(9!kêpᩌ;-`6a#{Ld 1(ʛo?;sYi-%JR1W7*fR2U_YDi&Ƅش#(,,x1\g-|噣Zɲ:{+N|1 j %0;Qh!Ui"cW*NDӠдz \<)w4dFt asl `V%E96âyҦu3Սr"XM pXyBVÖ;S'& MXZ{=~/.@A/T+͘߁q3z)rHQ@_6qEsQf,j1#q4}Z!<=-\ݨ:QSF6 HUmU& g޳gxfbL+hA}s;'JHSN<l=]|u'~]=s<>"?H/ǎ=q8NW$`omͩju+00fR(A\>+V4:S[ho@>/Ѵ63-.j<6[ltciz;A=sOnf k{֨@12h'iM}s̫\D:G[g1~5 TtO!Z8F%v5@ =YVw`D?Kz3Ҫ|bD.7no2<"@΢6ﳴ*UfrD^ڱO>'"+jQ<k*<+;0`[ۣs,{<]b:N%@/2Z+d)^4/b)93nZkǢTڛҬ30=C%) *;E}IՍGbǣ' ]6L_,'-M|֢UτgSfXW;kmW;0v1 NݦYDqnެ>bNb0RK J20v9ՁDh׭;^DNjE+m<3?8]jzi8L;F!"Ȼf̅,ܐTw[@:B݄fvx5²n_奯XJH Y5teBUA Z[-}WL4)զTו(+(%yٵX/+R^JEȟElEVcA v9>'NM g?-Q^`v-(miE(W.YhrQd<(Vkxg8٦oW7li"@LM\b=tp%%;Yɑ+2^aʍ-)]r$_ζf^~*7B _mj dB1( qnEh\8\TT`0> )AxNK*j;+̶Ʈ=>OfG\=C LsQ Z(s(!Wnk/i6gTf(춅n4/n1}B0ne0"qjqcjhDD \Naflv j{X9 թJ bqn_^v ~"MD7G "*'f<>{Liy~gI_t9ȑC,Q|6 gV+>& T~F5n h+ B(! SFX¼ . O~kx=fL-CGP99)nYLelCr=r[ucSѱ#n w G=@ڶ Oa0jZmw`<{-7ILh^2>7VtGAXKdw[bJ2AP NvG;FG!(Й (=T[Tn Ѓ;=puT'TXRGj ѷ*8 $wPMGY9z#Ε re3w`0CDK0VPL@ڷZ4mD d Sn1dс9|E2'ǬPgߚDW30U =lPRFْ[\kA~[$,٫BڹH Wb9x!pD9ʞAc\y`F,7پC%Quѯqz&b~Yi} +;4nK`bN1 _벸Q+u{&!6|jj%Ȁy\;S"G`uEcSr_1 ](-y딫zW7'n8EAU1 A\1ѕ*%efg X}ګt  S Vc]1YC!BhO߁s"WSۚ"(wweC^k=M.Ė2[U6yY%h#[dM3&̔~;y?c g !UǕcRC,x)gi#t=ѿ6/ > l abY}X'k gQ)u3\ ԉ, yI?sX!,K`rQj[q[[k]iţO .+hVKc!řx{-BU͚=zFvawܝifW30NLLMPPJK5 }Ս5Eʴ*kC ]@fm^LvxmѷfLF7Tч3EX"rF} Mm5(nR:aS 3# bEm4ƪ(asiF%;[ze*Gmy߁1qa|]ki>Z]ݨ晡,Gq+s[`$VdVW/!2Y"zX=М^ 9?]&)C; 7kKb.-U&՛}(u=hZg*B Ro}ژI)a"*'>ܘ:;sbZ>ń;v,mL!0Ż_gŰsY!NJdʡ(g'(|AK}anHL_/];x_[J媶hs%i3 jƦi 9c@?U`OzN #چdCD 1,$[+ @;Wn`zn>-] (O.3]84P)jqe3dK!PZelу}Vw`{m l=s}`n5s\ ǯA|NYcq#ݗ(8ظ8O΢U;x:3>Y ځHuїX&y卑wն'lN\82O8=(\ 2 1%0Z_q"Ra=W7 !NOQhqƕqX|JGgoRY%>JY,)Q.Pzcb-AM[Ԣ_~\J6wwՍB*o5,܉Йx5,A Tuf2S+[HJ6NO6Yb2mvƲ/ιQX"#IN9L iLb EJ}2C Ӗ f sL!Tcդz0r末%b/66#y#Pla_-,@ӻÃJ"LhY ]9S |NGC.Hj FBN ^y&XlKJK۰,g{]ĉ8+ǜǘýgiʫqpTi %MnT.%VMc7q,ʢrT Z-Ѩ 45FP\T~1q5›s#z<+]U(Pm=:`aHFg~["hI;`Va귤6 i;_KkO UJ1YmL}FRNǜq;P6Z+~.XyGH-*lj g^hpfw*vByu +u  6ij/%ϴ@Kl^ݨ޾h*-$Dg>~,_"i*m+s:v8qǿv*mGYAYYՍؚ%[DLOqp7:~CJ c$SQVDzymGjaK}v[N3->ʷ6,rv%$"+%*m`$+Ov&M+Z7ӏZyF|{D8)t <;00PH#"YBTU57?W7j:Ιܛ?-!<d ]Nq'n!_.ui*ݎW9Xej?;0Z v~t/\Yڍגœ`yJ@9'UA6%b3\U#ުBVϴw 7zuZ2jmP 8m4ѿKJUXGP9hte&Al ӟ# kTt*j [P()ႅvo!mnT:jk2̖9\8e|@߯0=swaK\rs9ڌI)./MH s:D}F*&SxGI͘W7 Yb=}} 7Ar9 z:> !\T*Wt8v>K ^CC />wtط;00&Vү2^ݨ* ^,әc F6x1-ztDc{Ҽs/嚉1Z{}~ZYvFb>Ovk= [ub2tQՍ/&xf8 U29D2"s1wdr]Y]V-Y& /^Y91v(Yסb\]j2Ͽuy2L$Sk/-mE;`r؞.aUCo$'4Np̞W/㮜`(SZMj z/=4N"86\E74ESkê !藍loTPvcye埁Uwp/B ՍJSV]Ղ|Uı{&YoGaɭ91-JZS1}je7;ZT ,T`8*z(D/@,{~Oan֦X|m?&.}%n .@c+_}Lt]HA$NK~ʿ)'*2;]n-0na"ǘN6j UĦ0,Z}Yp&&{SELxMu3Ai KK^2g` Y ORuЍ'+6]^x:]F`VYVGG*&x`@Ƙޱmy`HԘX qbh @u3e9ݣ}ȰQK=ȑKZܖ,39CX/JՍ2 o'QibAȳ?Z۫D۬?:;nSvd kc%CϦI.+D @Mzו= Z@v$A L).D30v-RGlĭ_|QUW7*dUMdiQ42r>x% WCXvzx;MsSj^ $%% fv:ޡΥXc0 {ik)L%#|cFI `\Rcn3 $al^@t B2ųUiZT;/25!gРF4:[ mqq}ISA!DϿW"D`hh*'JȯvZ1CZŀFdù;g"0L+ BL ?YIo]\wS}ΉiP;`Leq/rthU9hګ% 6M- U>B(QXLD~\.wxn+˛s&,5A] H:0t!ThF Ҿ#h]V I˶*{즊Vc*yq8S5YEĵa=C goPo1qPh58_(!v2r0+vL{Ls]Pa/8_rfFm䝊7 Yg;j/Q%ĭz]xoCh$_(BL[5^U2͉I-]~a'vϮUЯر(9B߳Xdh m !2Fq4%^GZlDW3%tw)2pF#Xe-*Iy,0CkŪnhVi4EQ@k`[Zܢ\jioj<2>*[}J'BR.iMN'z! 2ʝ VC(Κvbщˬ=N,vؘV425eT93b=ī#A\PKQ$ڱlot/ cbc_e_m.txt[nr Ur#$,!}c2a1HaTQ]5o7o_ֿonۿO7//????7_/_??UC____OIsZW_o|[{ejl;/;_*e;s17g¶y/v'kWcgnYo͚%1z3đbn;'RNhCެl)evV̭wڱ lRJVk{,44}}sqͿs~>˵sI#ΞR}="soΎҦ.;ט|쫘j'Fl#G|޹zu[c;-nh>6}R ij+ec')Y}y%jǎُZW[[|c#DmicH8;k{D݅6zm5OYͽsdƲ1!WqnSʨަ>;ޙ%'' Vw}ܣ⇝ɥrsȫt߹MW8S=4uY9Ymf1B(ɿsץQ̶"̏RWO.>Y,Kt&wS`'l #z}Ɂ`j R*`X /l\7\3niy͞ ! Xqki@~&=LI&?cx|]Y8,q~W8ŏ[po9 @yP?&q'OV2_r!!H(8ڌ]h~ W-8l=&39W֊[3NkmI3!5 LwN".([ov`wó͹p䎇ݔe3 97bp 􆾾ԶƤZ'tߕ\ < Į|*~KC9bȌ8q=5%CCg RXƁ)!J@cYa@B^.#M,Lxف}psY R.!\5˸=] Z-D^gU_@XxPt wLxc5P?d̿x{H\%M` @v%9X%k ^i6RsxF̰⣯,qݾ{H9hcֹvf93}0,,96mF5b=a'8\(7;t}Uny'=ܗ'=gU;h攀lbz Rq`p|ioVj[ ɂkJawdFʏ}7TLop۝C2% 迓;_ǁY2۪@ؒpnζ~)`m\dښ{[AvDp.s&17eBӂXEon+= P1O>0A?!~ϲm]ηFx'*VLx!IŅL!u[|*€kaza:0v^_ɋT~簯pZq g/̜nkc:ϰYgĒtiU=499W!r.N!4Mu,ZOpv[j+w<@aW7x>0^cN{ֺ Sj`FP '>*~0&N}X,ŰG0ĀIƻC2905oQ/`ޘpkvrֈߴRb@{[! t$̀o%`mYgՄ:8/؜hPah\C|P\z qhLJeΜc}îC9p |0lsq/M*@Xt6wdItrPg@\[prsq~R׃dWB?!.<3Hkx-r7!8⼁6%8;!,s9,dbs *cvNm4M֞ _u<@۷d[)R54;@9<;@Q&`wVAwaOd3qI> A[ ٸ |a~L[F1@Ԃ.rN˻rx>t%\BpnN<;M'gd`'V=L hIWѽ`U! Uw'Ήۜu88nr2e܍|ΰĉ3Fc>2}G;\͖j.ˉ[C18=fX&: C?oCqWϩwlyc%C AtE#4x?g,ÆO*@_; eZ uQ?RĤ l!a"y\ftv* v)uӕ)/P; 8 B?}Rp?mr%JgYs{& n?KoyM䮇SA,=?-~3mH ށ #(qo[Rf5{~Wxƴڞh eKCz z3B~9_+qR'nGCόޚ8ԝRd:![UeY]LO~*q'*W+zΆn|lSoւvC }rk-$K5C)>U Fq;_=9iAVA0 `V )>C*!LzL6/5a a '>9LlƬ9ѬFU~o4脸i8U3:G|<[cq"KC*>@-cd(VzT'1U Ux |6km=]fOF4 ?E ӿԙu-f%vv}Al6`V<0iacoxZ Q֚cǏ!k84[cie@kYlaP!`I5 B`0g/*Rg^@Z`_̍kǚ5&$!>/#Z`dq׷~)<* V A =Gyɇ\r\Yd×0'VRPr$Vls9C=0z77\t7;BdZ{`㡁{u8Du$= V赏R.A侇>iP׋ T7?l>l5jp>g4Ԁ/s%2\*Hd_=cJe7~1{=no4=de$b83utdR].pd`u* W zkr80GĜ~Μ7,Y ӽwv*D yîx57[[qQɎ!eO\zV< +ز\pϿgd ͟).&}_m!Y YXq`/ sHV`[q{Oe.)ۺ}_mzS_ rs'F0x~Ak羇)RA{B{ffl'({b+6&?Ǐge й5%C Ϲ.׺RN9Dj~+bf^T:9ٹ, k !ZrlfT°5{!T|; `СpC6 s8,I(B64k<ûvKʯ"Y5#@In{Hm+BK)AY:oIq 3ДCDhpâއ~)!@j\@zv>׸#V܏%KR]o.wn۴MJp_c侇faj dy6m>̯E9;bͪ;v8.q*jնyR+$(7n9.g '0آQgVJV0NѝR䎇MeH%8pҢ`Kpm 3AI$qslTt+'Ȼz< AWB&~EDDȡr_%/Nqu\'b/@TVd4 j.^U;K6T3QXz1] P:X 4Qix Z5m@a J!azsu59NYÓ}1=yT1ܷ/^/eP,j S9Y`ؚ%@,;2r,Z!c݂pt̺O8ˠSo4lW[e#;q{gwDpu0d/sdӃSkĉ`Ál&)~}Ĕ~(RaRG]WKR8@;rc-S֎Mo\'ER.ڱ)Rބ\r;(V*0Mxya_rEc 9Pkѓ+yWſat j;k>NbB'/ր_kpV+vcjgD  h}ΖQ PN18UeVW@`WV.`\c2epV(ӝQ\DW Jq#"WsI^;wEbp|SeHA~C)CzV> |5S]]9MOr)E%'~{˫c~c@(pYF #31c93Y[i`g}]90OtŴySaߝZ٠&{^sLζni ^5'.Z/NCf5[`m 0*WQLap⠍vPD'Z9१r&eQ.t'pjLSXda Vs] 灂.S;]Q;bQf*{;$pp NWbmT^_aw(8eHI#vcjvOmx3g`V@ϝ 3HBC8zLndfKT|){W-FfflqVpwY&ŵĻp,*7B7ڛڤ6][?Y%r?} `]S|Q@Hd 7R|cJ"uvW8e.&E79/rG 2UOU*I+Z™.01*sE:9T7{3[h+K]aᭊS>d;1T\(hlamk_5Cd9- )u*7`JEJrxȸ(sLkw\`x^N 6l=0Csk޷D{KD&4áUTOsggI,Ӹ0AS9 ʲ+;+k9+ Ha Ɯ1+RJ'B5 \ݰ~ϳ8>܆zgPrBY37=TEORd\]$* s]s_Oi?l|w;B,WctuC!edoq̎s8~j30lήnbcs 1oڌn*դ;+;`e yҪd,`~oϭ%ѐy흢r#a*eE5ncAzkI)ANXĤ-~r|}rW:dǏLݛa]Gh4?=Yą\"-c:T;;=vmm嬰)ep䝝0FQSgq'gourc+Y#?0*({LY㨸WZT)un;WY#+dNZ%לS-tq/0d_8{L%"/Y")zpY[nj^>Y7 +:fw_@cX0= խ0=)/bہh@)v%*3| 9sgw|E{Up\< g~ :wf鶘  Q1 6(XuWFWdkv"\p_pm@Pѭˌ=]1[ C#hDˀ– wOV#k/zꒉ%10l2eLTIUk> B)gJ@`ARM`J [x#:`)򥻈\p>ǔ'+CvvBʀN !6aPc=7AV2Y^j fw|V: w'M{Lfq<\U乸S,^)fA}Ke K*[| C&4ܛ6^$ 1DF۬1aV7(O XfZ|D%}[}>eJ{ w^6w@d}~<@>SyU KtҫnSvCl$ SE: 1R2BXHV0S^݆햴Y8E\}){믗H7C=8/39*U=' K1<%3Q0Fe١)Kٚ ,1wvW,)nLoV*C^='?Pl3*<_klb%U4lFydwv7iI?7E>헌\Z;cv]J93C)>tbPr 8y(+qx^_qK >&ѥT=VuzjuԭذʭTpgу/;D)<~H< 7^jIo@9%IvE >>!JI} JkUmtxQMulS[| OIwv7cDI2*$zUH/FV2ۭBƚTYnx}-N䝀ꪩ,"9 *n|1YSsXR dPR 1Gӡ3S=jԭĶ"qvhU%x8L 1<)cʓm~LRєD$[xLR{~(ΪBncfpu i7rKUY(VDIC%˰'}G6JWP^e{gX )&G<Ɵ|bSa.X h<1vꡠSVX v0gsEQRܵ(ۂz+M`lC,1<ő ѕɋUd=d?DZC Uv(iY쎯lx.o`F:'yؿǔ6 ʦ68b6AO[1rԍfŊ')sQ.r؀8Ll;q'9HUMxdgJE1Ra;=%\5&ks@r2#Vp5wDXi ɝ1ق F{+ i#m.,K>KE [aY?4iX-i%<{LE* ɬa CZRhS-Wן XYܯ:eo"TTn)UUUcRwvc1LLv)Pg[]k-,;Y o[Y"a&}ޒYU4!d’U\?z>|(֥WL<촓wyJ(c[eGvc+\|wAj W<%xoט,EްpO^ ~ЧQyZ.lŔ4ABIHت/|ŏz=$8W(ykoT{ Hwk`2Pjt%.relm֎g<`gW{Ly26EIҘِmXIp8:G᜘_61"\eY9]:St1\_wEOB\ 7W'VHt ;[q]9˩Q>42JgQ,,OJВڏ`D'N')qϿ[Sii'-5 {+J.K+f1<2I)m|Gv%.bnW{K= pBrwX gv SBCjTILARxeGcexg V^&[->I+쎯k6 MNcVj@PzpT{L }]fK8*wܻSih@k<) e>fw|ET$VH`?RsL j) +O}SmW5ZI 0ݤ_[=8b2`=ЧU{-N7&RAn.3ϻ89_1/, e:CUO{LYSDT :ac}li9XsKEX_01U8YAƕYS.ZGg n$܅T|pniʯ͙DFkzTk eʻcQ.c=}N6qij(HO/e7$$5ڬQR5YnL]luc91+Qq0"NܣMrf( A¼w![8 ->>!7޺t2>#$SLWM)S;%c^oUU[oovH*P%$.?S %@*YR(jCL8- xV1݊nZE SĆ .?T,t/2!W~v=Q|J y:W)%^KqJ3럀;+ !Aqҹ½ڀj1e *hV5,@3C8ealSֱ鵈1Iw+!˗@x1+e'k+?|;xLLV, t@d,mߢm(rwSY&edK28J1ҍԋ[\fuQz#S>-aXa;{|E3x JȔ͙Ӻ϶~X@ē^/(pïOtξVq/' 8zq[:k >T:1,m]dvcITnj=+;J 1nQ ֪:R4I+LUrȚ֔ǬOA'1BKn-a%dڸ5)3Z!ZE1?6fI "9(cjISaʕSl$bO'ؙ]S49VqDG|gw߶T{>fN jK">D}iSYT[#RwwvWXV-T`UGod{,5Av;"iУOSU쎯ݭۆl ]C`춞ggvc8jK %gIl鍎僲1!@̓8Dp0JUZ=\cyzeT9"2Fq\s rTB%UY)A Λ_(<(mѓZ/Ue=\ŵݞm!r99I8[8dcQǠzĹr8Y7ֳܙKgKM@A4ǝݭN,|U'uL霻1e*n—4ye;Osws_2*ΖzB~*_V.:$ۖ4U&8Eem>+qփ"$z4{ SiJ*Z`ZfmcR'ccʴS:'y1`Uhwإv/jے;3 M$Jjػ1+#r/+F=o70؁'҃ܭC)OĜ!bbv6YK~ȭe`nOV*T+)jc(X pa9c$ΩDa J)1jܫEq޺m$x'vTػ1e#ݎOI ~r?QӰ 9姵~ ?%5x`oS>wE_{=PNj7Zzw8;A{>d-z1jm%NXsuF(w)nJ@X)u=ǘB{Fe~*\Ԁ6:IAePFm 73meU}N<{T jqU31JՈwt`>V.E;+?Ԅ^s\>n*u^|9c@}7{z=Ҵ Jϖ%׎IѢ]pO')B ݜ< 㱺s{'ed`sOUj[}Ѷ*9OYNwgo6p[UV'bi15;܅!H7I}# ,fA XMiEƷnaodSlM<SjFUvc{)Yv5K!!;+#jjw,I-QѲ.~sL;E|){G%bXFBpЇu ΨNǀQܭfN*Հ@x;ISk#I2y^*j9`9ZNL^kܻuoQ 'z=T;+9ʫkR ՓI=]NO\-@9V~k|R.5Uogf&'f'r"@bx_cm;|q;3\hK5EW~S[1@k~gw߶%YՂm@ݕ]s=V ` 9dVV =w]=9e-B¹zY~} ܭRl4U}FS+*<4_;9fǙr/zhłt$yS? 12*0ϫZLQB-7w]ҭ=h1r\1FLyS(`o &OvXwT> J #-Somx Woӧ6U8{2>ǔm@e9FB ਙۂONO1l :[}9*uԭaOTBto鬙G}J[(h%KQ)Rc$JBT/{z[-AQ ZAV"C!gvcʢ0 )ٸ1L>vdCS:NLckm(m 0j=5+h{a}sLQT vT[;+E''vE\I\_9F}w^]I)՘_mIZdC q0unEscn[ijYRfl%<?>ǔ5V)\Sj~e UF8F$IѾ-=S&LLsaTST\mw붟ڜ"9]Q>9vvHi72LR!V + y݊[mjJ3~YCn\ 7NT-l[)fo;#.Bg&m7+GՌOq[RJY^ jH˪ƸX+m/@ '׉Q =B;쎯ޮ+{Rap}}w2KIUsH<nvUp4!~* sv֦*UeNJa-CQ4̫u\3Rz4[텗ZJq-&э=ƿJG=4:]km| {]D0,%gX sigdvyuJ!V=4JA~w&u>sb3V&Vx ;+YOsCB \dcj8Y,uRһiI/'˪9vccê{UEʘb'ض˓nkQTL$$r+ixE)ԥobX`]R -:+巳W$g._<494ەGw6#e 9 GD a%Js=쮯X|62^7S;%"!73i42INdv#`V%G["/_N $_1m KEcjgؾUZ%`ͤR:1w3%N Rsx3ݭۖQ!`f,:$;D^@NAq)#kTe7g9ї7EQQb%мsLTnY^VlQ}ٓҥ%Fzo"]M#ws,Q'YW}G `sL!(S%k.u28TYԬE'L ;"+l&m1VE_NPuEntzO/rˍ9;Zb-S 8cd_aIp8uy8LM[qEs-x(c2;ߗW;we )ԇl=bPIP.؝8X۱H[YD9ϮE%Vn[qC ZUiA*M؅I=5RMj En9[jNBʴ[n&sP*HT{ǔj_;v0cqNB2L(KtlAު+"գrn};+ Nܳy@I֦F%{?OۣQixḼ`XhK]JTh6EY[yz,KLȉm\9ō+̊[Ru0`=Y y+///nNчJ 1r˳A^S$^=0JH+P9(04_E,秋@f<Sx;kw|t0U0ݪ٬TW/{?*l\SxmE䏀7Ehjϝ5xlq)zgw+RZߓϴdcʓIl"&9Xd)nmq۸ӃropyIZir;+@+&?ث =] ޺ @Wt^\wvʝk:B^v5)FAmIܔn2sTQ OUrΠj cjѬɞc$p;·K}F!5:9wsL 6=oJ $b]\mTO XeE٭i%Φw&'pkLN߂PބeS)ڊt3SYɤw|b3FH`)ڻ_ݶ$45ږKi~N-rD^YephʓsbhȪwxU;m`߭o~d5gNRp.K5c _Nl թ׬-2 z %tbƠԨ7v))| n>{{Lq2zY T{;o= BSZҤ^!'@ 8D~DO^ >a"Ѥ5P2L[F vL ]jU 2wn6yHb:cIA S(_ ylJ/\'_#ɸJaI18>2~R*0rJSOD]*uHC2%9ܩIj * {ꁣYov5L8Fl]t(c*+=B}dU?޸1&U1&L5/]kէ?V] @b:/Qc a[ehv*OT8hӲn4^r,;+0x$.<=q}wI ^9tIr2c?:7O=MJOzg^iؠ7IߺmvQXOفdi w\ChbIVngA5CZP(.;;U-l=m]דݺwzg%j+=xTluYJlZE3,=9L+6e7(;ʖf_,R> @}S|B}=2Ibe>#ZE MO.v7_\M?Iګ{?J_cc]3ev& hu~6 'c]Ovn؂^QP1J^i!_9, ,qv9a^#c+UکSG44 ]_xwfV+"[BPc 21v ø՝m=ڣP7Yjz]k_r4LFn}Թl{QYAXX(͟[a)KHg*[z( uדRIZj.KJ'seN$iCc̟YBU1XMkԹ0STF@߹yPocFܮ\ήmSIR&H#a coPK?@ęEn[p,}z”}KV8cyD J ؇W6j9.)Ǿ-[=+zh"P!*k!`cjvxX6S`N5siu(x`%iVt +)Ha8ovሁ%54jIGwgԹSBcڡtAG P $u2~zź9Oum(Ct_~obUT3VpƹhKKAmfrĭW81w2y4,ԝRއ:)1ՊlC*d"]+F"OEu HHfC[]$t2R/J}aԅ(c[ Z:㵪'Q7  P`,\{2 $H䧽q[80/xDp5ks'2/9柧8a]D *66tuolI)j!g98znv?,ڦnS_15;euUG5s6ϥPO"]u붇=hPt$sc H.lﯞ,!(zYwVP@* oa5PYسW͚U?`o*&wvc(T7L'HZ6UpPg47jfI/q㷳WXv %gT;n/ 3<ˮZʧM|,YJI*d PQb4.u*v}L)?xy%y=Z;9LsF{lpОWH,UѼ+VԟDY[g{*84!o,sL;[UAzЦjc"=e\Gvz~)RV[]Ŝl RE1ٜl1v5*c:U*KJ*XIƠT1%gWu^"_ycY FC%k<'_}?+JYo="wnB0'x~HYAk\Kjz|m{;ɜu@ }UjO Se=,o*󲓉sluzeZٮE93ZG{#$&')ץ̚ogi=GKFٔzǔ:Jx|J99dR9cwe8XR9uXā.c_XΪbh_^= >o *zz{[Wa).MP%uKR\gw߶[v`Ƚdz'ö 8_]1z jUu] -ē C*R ''[~"TQ^8 e9(:O ٪ CI#y`)/FH* iQr0"<:Z-쎯PYTxjSD˛;}w{A-|&FQ*M[Rӛia)>ZXtU )Lݷm#QFzII(}}ufQ>MR~Twg1;,,U 8)Q<#]ye+}|VhEkXk;1(ئFt㱇UAPl m*̺Zdlo펯#_+%hK5j&W[sL΀W8[S,8m܈2ru¦cZ 泐Do̭ۖ@Q\EY~(c*SO)s$oqkymLI;H>*?eK*OEͱ Ż {Laؤ%jksC?Y%AՈ^œv ՉCkٿ1sW$1kK*~ ՜e+lw.@"nIքy:/}ߘa)B5>H.=ft,Dq*ѰvU\?E.ʶHJ< 9c'~]^SN]%׍Z;f5h<~A`"RΛ#xty%06?iW'D|ӡNfіۏ݆l*T0Q-/=b jKzKSm 򣭕N)(a #K| 5\ҋ7Y85P\@_?O{`qհZ*U>c.=r# 6k(j4bg]%̑J1C%kagTEUɂ~3eR^OCR,xlsϲ b~4LjS\o8*xi}5?U;GUXs=nk `cURufշ3JN;/f}>/xzPz U[|+ $qbі@"EGdpU-\_fUACߨ n\Y˥;IZb+qsR$u|76O=zRS8fZU-a3 hK^ U!7jG ^aKV'$)8o92z!YJ`gZH,|B\GNJ^{8,Jp̨k*3_>(J@+K#XOIjHMcU]t_|BVRE 1J|&;qJ9B9eUJS6bt~s!b8mfnXDgeJ'Dj*g~V(.ZT"HVVz`Dcaх}pqCG*T0ߟ6S64U2VY%dId%fR[& 'HdGڮp:!qȋWcQ?ٴ5O9%y%mJB u'l4Q:qq'>? T<3>m{hp a0eǃI opŁ>]!I/3O%'t lB=6 v!7x^򥵳+-vGb{`wǃ-O%)M0'C4KgƵ+"I|Fm}{' & XԸPOSO|DÿQyTSw;Wؕ^do~K-J٘Y]lX8MC'ONظJ?I*+CM3gn }gIE|)-vvlG҄wne"AT#r uhSx$ 5Q٠RײF7G@# \BTc(}*|`l~x$8܀Ԯ&L:о3zc',p:B`73{3aq;:0IA-pY;7x0@jv=lwⶌ`M_q4p>?!ӵKyicO7OtgfjqDӂr9}?,55LM1$E6'IBmnRU9INc QųEV)U)] >8+r8z1TJ_a3A+[ᇮ\S`?R13*1U5=xO{=&_Vٓ:wL(T:¿?\!mp$VeAO)PJPIXFk^~BWN+==5Hixy2ioy8APҋ?! Ӷ`\Q L ӜIJ%TZ{ peO|u$BkR~W[.ZՐ?PO-4OO"e' Um[^ ;!S&3bjz+Ui*'H';\igu 'M`8F4㇠wT{fMԛx Hː\U'uQ`gtlڀZ-yFIƪǓ;8ߟdG GoU Y_k';:f3޳QOJD=V/  E%O^*jG^Ouܷ NesgGzJ \e_O(?;bAjЖ ت$-%ЌJ !i)} .(#DuENP[:q+T,|q@WwQ o,o,R6@E}c]Of1O(>^bM?qa-Ȗ~`s1yU!*fVewPljh '*s jܬ;8IW@%YM%0y5aK xW0*Wd ;Y`9ȆҊ'OVu]܈^ϙ Dwcꃅn],BO5_jήDw KN*Qε 9%o6G}`b$d>8 5BQVo~t.JpEMu̐|ӋSUU<3~W39 |qÒc[ [V!](Ik'ijh,2^an6oL“+< MV8Ϩ}B Ժ,0=BM35] s8WH[~iO>!aUOa6u`쳗|mS9LL(blz9.e>InUHj.|WMa<>|3EJY=XIga vT65M7Mv4;R?qt9;92e[2>1Oi'd UߕUZ*IzCбEɩ!&֍НVc ւ:ԛ2WC,ΙWUŖ [\j?/$ .* "'y29bQ $*if@iFd*Jֳa_ŅVW(V54Y%+ơg!ubv((-5YhI;}T[nalUA1L+woYx:(›69Q5c^wR/u'a4->} Ehu0q9loQ'(]Alړ c¾)gV-ɧj`=u(9 ^=U,+Lvج݂yd*gAOyl6G6`03/{$TV9rc ?(L;j\v&OIdsPV~p6.鹭bz1xsCVS*6[(<^K`1*+ϡ䊄.s[OM:TdOD Bi!*Ԓ\m9MFq % j+ sR?3^SPn$mԾ)YjмS2\Z4}_WbNW&'.Z5, tW|;~' .+=f7dt>mT ]3JW2RБ,v0(U,0GbUW9Q*J4PX/y3nAՠ7sA+'Le*DW9Y18-V%% R=~B,@$VQ5UY-,0$7frzV_AZ!!*\MX ʩV,iny'<-6{K5lJO9 <8+X'c<WWwN`L-R1Z}`՟l]UO)% >C9AQH8B}*˽f4+OjZ`S5R/^եBZO<֩Pof3,,b?v/Qw;{%.8~jV ڮS>@}<%6^O0Y˒jLIG]Am@0' o=~HGD6r? ,ѻQ@oRN*1*?P \I%DvvFX0=iJd HhtM`hPC e zco X``h1_; &Y=2V'H*q dԙvRxmźzQCDUDrPM(M O'\{h=&tJ%SȬfxb5HsQ$v{1tCQXM=Pte%4!n?!ӕpzl=$?OYyg6&)~OWV(8߸O-' U o ab:5IG9AHnͫn(ARjkŞdKF1ZIVJtjXȲT{?!u$/g4iVv`v,*3""ŲiVQw8c$R`壘:ܸ+p}p0-Ycn CVs5-,5+6;}Cv%5.zdƅosr,!%wU3V/sg{|wBd3V8;SGԧ]QLh_'ڕTu24_n& Szk{Tr -47H, >+K@qTU,GSaY=lqkVM,1Sz$( Yz~h!Yb%KO2TֿKJ/ m;mg!Z.K}TDeg')RjM0:fnLQWd 6JX=Wr8d_ _Y~T;/c[zwEY'W WeX-Ve1e) rCC gL$&07f?{RISbTypyܲ 3DZ C)R=bOa*:^`brHpTW H 6 yov!S9ki,UZfp`pA*ownoF)kZE c尥,2ɮc[nR3qTU'fR]惊*?J͕Qm۟=LnK=l3(??Q Y6#br؟:o&͵k,WzjlʱJPA2wVnٰƻ{իb(O=KR ?!FK]QܝѫH/)*oN56b hi2Xc$$vht;+Wi35RfT3_ 6ҊBUFA,c(v)=.h4ku-/A{w2Kl7 EY P <[6Wҵ&7u4/! tԠNk _NjEPG9]6?0C^S. 7yR .5  -iǛaBǎS"I+Or9&IHmU8z\B%;)miPwT$ĎTأsUU9Ԓ=k'*-s*b5KQg E<2`sv+.(0šݜ4{5:Pd_a|\sィO 7! l\UR[ҀkoӥхN`h]Uv _&pDrJxXjX%땒{o7<Ch lA^Xk`OqYΕxn`e\ vU:'miPKq=95)]z7s "fTlŐS[k`8YAJx~= Pq2 W̊Y͘wm .* T\Wxl8~/GQĩ*J.b:ZY 3Io 춽UxZC,vO% S$Uc@}qQ9RRfnB\=WcL=dX05WJ%>!{g}՞ѳT%1V+GYS-h)zpl/"sJy}U%a-ӧ@Z[$'kb a_ qC:̀^%u⺠}pqx [Z 'Noy&gY&c踰Rx^~P7MI+p:Ok]{:"tD5AXI)NĞŒKiՙX؃ 1`8LugCd@D ,*_Va`e0\N+OMT:7s.IWT2F-c-8b ;[)3O,FK3BTVgTɚВoȗ k/&|ff7éu©fCiÎ;Jr ׫t2J7ONR"īާQ7tnE# L@FV ^YlZݒʔFVPfMd&NA8INIP3;17蓡 +D81;0 NW"pA ꈜ@dowC 87ViuRUݪ7ݟߐwts EGy$Y{Mܤ"ebo_=OJvpLP".Y5RIA6H9opLAϏn!A-T1+2Nj:/)\F^QY 0WWCm"$=+UQj)E O3LGob |)M*'Uբf*A?UW3UQduHuUʋb߶%U6SZ >8 y.gF+i`ğX 8 z`⧐=X4ο2ͷoOŬ[$)]RҊFz{fv7'}T[{^4^9.Al'= !ݣ(&:ΨO prA2h2'6 ViQ#K=%peﰕUSy{ &Di-l_Y0e$Uh1E"Vt Sܢ"#@&]'Jm;TW\oWct N( QdXO7zJrkW܋MQl{yU>$bSo lBQ"&-s:AT,L??$ |C Ϣd8C" sP3 B:LhMO)*D xgoo٘}d2wê9_xD-aKPo0ۥ*Bn'd&CnU<8Ad98~Ӈ;$p_zP`&1UoK?2et) 7?+CPaR.gJ}0\#vHItxǨF +BhTIؤ.ʥܩֶkA-L.a5ڨFSxԃ^_}W[,?DڠY;eUFD3Pk7W0"iŢ`J6Njo!pi$%W3("<p]֦Â>Ig1zU&  :P]Xʒϛ}}CXiK)8EI- 4ҥ) ZRݧҵ`WCg{@qgtT<7f'{Kf}㉈vS 4KfsQi8$ȹ-їqX#wx=篘(Z%Gv) oBCX+.ҕKU8tzK57x<9j I;<ļTeJ8N~7t ֧LѭwZ!,E=Ǘ)YLWS 32XDIT%]Zå qVYrӕp'P'O^ͲWͣW#gTJzQ6QUE\U"Ưo0ې I?] TMz z98pfiQEb}Y545p1鍼WG^A1io) [I}5IˊDE} =c(@Y2J _o~WUI SfuuA#?O?qHA0\qr? OX1UsxBlG7ŁӄfP _LcM{g [!21<Œe`÷[p[C- 2pIcũBnx[Yuy0.,(\)Hol 8/P#-Ѩu(#؟bF8.^FmzZO7o32&XaMuQ\$tSL;Vz2mPcI3ϩƣ'65Td QxDc;`4hGzi'M]^Yn d `UBn ]p: w!|V&Co'6n>Aފ7DFwO:-uIvLgMngsPP=oyy7Vc 0IMQJ~dEucږޱD]1^aA\ b8}xcK5g 6C8!^Ғ]MƷ`/ᢶ^4M+^*90F.-WC"z72q?*Է`D*Ap174% vMAqֲO،˜/'|O3WcjZyPJyeZr]O{U~/l^Sp"&J4SilSINI#`RW˵~y,TlfbT nD}C, /'v܊Pe5mG(& %g5^_ƒe;AI ZHZ،{(CdWZk Z~5Թ,HE%ŵZo< Jd$7٣&@[͈?S5+1@s4SSxΩԍnXuJ7RBkM1~m`Cjzv9гҝeɲ}>죲BnK[55ĕsBi vQHSC/޲Ҳӓ/? Ib5NAZ3\a~{E>B\O}?&Z=T8w;'t _4R|XV1Gx)g"Zx Kҩ8v2ZVr|M=f< NHZa f+'%r?sLOSiSJ[D԰2DX֋j7=2CJനc'pqf$ j0ʓM0tA*Z~T=A =U-w`_{ JgwSfwSii:I?MO Uz x!veW胱%+w)QNW)qMV #)B)LGmG;,z`8B,ۍ]C'%aߖ *+y(dȍG`*<l=-`@2呹U$?Թ_/ǃR j*b vRvx-:)}  jʁ1 o>Y/wxNp$Tgdj}X-zf0؜Uc+0xc^ ]]{Hx%w }6U v. %)#R^Y4}~<k'n^@r,59%\"v^gm}9zG{T }EͨzA2X"Gp8t]6ۀ Yɵ5/UqQƖ-v{e?1b7/l)˰} =%֗^zJ Ɇy_Jd~㏤r2p;[!N*ZvkԽsr]VBEW-]‹Qu ,'DPG=9w8>0 f6%v.k6Zi'EBժ>+OwǗ)C|q_5Ɇ%]cÊK1~C]J? 1l)oËSHqf%{[v?lb/n9.enj\G·R`g% +$9%?\XW{ˮNl}}4-LunNUW٢w4(74ۧc,U# 0˞ѷI[O$ gFs7|5?$ <)+HQGp.N}GNf*r=c Ry4d NZR٦V27pWQ:ޛ^okbRWP< ,TR6IzDOU\e8sJQo7ǐ>ZtU:C*x&(lp\1*%,J;$`P! K耉dwU+﫹$UĐ%l Vd3n>NʴN1=E`7gfէ{' Oc7(X:`jcQ-ʍPMP*;[_&KX*8+>CO k$|ϓ%*$zU*ywmg2BJI]K17s{cS{p*X`bPǽyqMJQf WRҼUmX SyW\IzT9 c?l//ES)< ؜Yp3ʶS aStT3| &_ mJG8FdN.ctW#p@#=aPV>E/]%s O RY6/q25m+H,Js]o☋W:d,`#Ӂ74[#B #7Ix16a3<9TS g{|m&Ď}VOuo*/)mgE&zgc9޵56٫:wUK2J50}tm|Gk[)v3Ufg%Q|2UXQoAt*7+@9hVON@ZVҫ WMk.d) Uv)x\~CHm3$q ns,S}6l˜ysd^j:ܩsX `!*V9?OeQMUN-n]]7!S?c`*={GUZGwꍈgX8k(8ߕD͙3 ox`O%,w]ip:}QNFyH4]QƖ6}wW!(jZlӂssKS-9x_"~C =_ubPfh(ISZzmVZ_jug{|Y̪Sù֣';0keelۯo$XBd}awgr:j%w{<٪!@iN6UtW#qGmԿJ,㟾m4Nz27^q JGUnJ.I0Asby@wuuh Wm="Z,h4jnzo7C>mzjFtoYU?y hzi_UIV:,ª^|(>>!Tw͜K[acT[I~UL#:[Z;˔ OJ%زTjV}`A`b.VJj}9*Ӫj1+Uk6Yuµ%OUo-&:==ON1TL?OU3cL?EWbqQ}y"v2q(s[&fw{c9r::m L_tl+b,2y}-e˾vkpAVMRn 8ޭ6kZnvo'LlrTQaO`89ؓ #}N),DÑ{:ws & ˍ Jzm\vu?" {A®?uD׸j'dB'&|QLwX*(ⶒܢ-[iunZ ɢ9`o.ö!hUaF+S>4[O\H;(|$uTřF [ /<D צ]>@U#.j&{i|]LG5LX\ $uY Kn{pq4+J>nPWS: X8;Rb_=V:7>U,:0{tz *9eEˮɔ4BݰTGISKwjs?q mSJ"wD+oHvw.Ɍ8xayByN'|hdD/${?*VlףF v k;LW]Q@^!%sƈ56[Ig\&~:%ncd yRK M +Vߞ|z鉛"rW+c*jxsUo3Ph̏wal}{?`'lSHTDeEw{TEjG/ʪo.[*Ҥ4r1H7<#h_q]Gcklbr;%"b=U0 xrS5G=~B:Qa=MuCܦΏ5bo׀ sm  LaqJܯ&6h;*sU9Vߧ}s).0@ _a v-K L N3>J2)稨{-&t=48e}Fޞr$CZ,ӴZ1VoZL`ط{Wm;`Z @F"W*1]| ߊ8 BٲV?-1輀CCUG^wkhź9*|!x#X2FJnl@[0߾㧫ϳ7 EG:Sb2g=7nEq@%eẠ5|k*\OЄxm0lZmb:e(?j}qP 7f4J/ImC5Gm&hwyM/{EyB7%0.^JkP\Rlu= VGj6CVq&wMpAmwu?EkImĉ+ƍv wl&ڑ(x-lCl-jzTNio.GUL]Jx੤lږqźo?׀9g1!\s YOWe: Sڐ Kћ>OrsDР*)LA[6+ UT$Hr1л HD;&ZhjQM#ϵt?YSE mypk FjF.כzvZVw-<;uʜ~di+Aq"} q}Ͼ\ZM/б- 2A2aád.$XD٭~\ʻMIKXk[&c띚^ "syT _}2:, ¸ܧ1q(%Ȩ=( ༄b;7OL^TЋΛ y0ONO`h0l!C}eWG>`9WWN,zLm1|q귝A"uYˌ~w]*ZS<6\,̤M ^UB{<ӄXB8wV9ekPpg+֕׹v:S^E٭W)*i(Pz!*u"vDcӀ}&R[OAu*~AeGE*Ačֿ׷+_7˂Ek; o.sf5~P6ZC)Q3}A#([`,nӯ'|wHbdq#g /8AD#ꈺQ/zYn[K*Dҋ^m\T2~a^#̝~+|zj BDS_*S;3!l f3bJf]T ꘢5W]4w30xjDPTjVFI5 #d's@-0':$0cKٱa50槞OW gJ:TF}Pvdk(t=еv^EWál*6۬G'ڴIq-vU9RRT&JD.NH)錫!4+DI?Z_Z jZ#8 ll`_k .pu 6ß LRl tr 8%N٭1 A?mbFTF~AL*+LLL\Cݧ9e}#ȇ" rm?ӠN#Eg.blǯX͆A.)n#khI.*z&a\ 972 `a *OO]ʞI&%7rIr`QL7Je"Q3}zChDZSqֵD7ԥl?^V~c%TNhkU\ (% hwV{t}z<3H qS)ٷm`݁QDF!*rOCR>F6*/>);X<:BOA7&ws % P,ȵ1F+#hmZ!2¼~DȊEYFҋeY>Ak!O'~Mg2R] =1aZtC{Ҁ-,8ݧUk9G#DGicN1q@/egMLg*aH_wpͿiu] Vڛˮx~*3.hs!T9e]|{-G6wF*,nAP+͌Zw WSjS?ȁ8kL©`AA|\m `h0‰pwY>?՞P?ZvW\2:@CarR:0'ek|,ŎF't*Gp]<-~*Ͼʊ̎ҍ)jbtK#$VQQ/kO.^v|3 *iP2XuC t(^pu?D GqHq ڐ]DmiT1Ј.a1-5lkU=x{SO[ frrIKJ\mmUqba˄i^aQ1{ tPK(*8bp5 |17x"*lQv*\QlqV[&mTw]Nqz ~:(]b&)/t לkPYMp.ԯ+̈^}C v"#W42`k+J\GsN ֬^.&?fn֠jӦCXޝ[Eit Rw)7aqWC*:~+䗤$>Зmڎ/\S6(W%]]<|byW_)ç2%q;6Cb":;❚Wr7ﶜC!YE$kMRV׀;͕NY) u΋)[oQ(Ƽ~aaʓ*<2 f^md+VPП`ko{c7D0 |z~!^HUl48 .}Z{9oY6UYi ,gwx נ;5ՈM)#$ENv9ecTӹF^BS$):ۛh짴-rZנjW?JJFO~ɠ#MS coD4~0Qth6m '֓( ch'Fg˾8Տ5z'p- o%_H/08Pd#_. aTc+I ?2%~/;3j_Tj#i83KaT Jx`v,8eU]vM]| =;æXmP2R&zF 2{_fIFh.}@E%DAqE5WÉa:3y\-&bi^ ^;0\dG@[(]d<^tJ0x^b,ȧAdO2exqJ J=EȢH ) &^%5NӞgr_ƥ}6*T^R\>3\n\S6et1;W5IR5 ÝZJ/+sV&˃ Jl IS^K&qoIhiEG WN5LҞLG)wlw.uE0^Jر*Oط-ZsOG"XHgmP<Vzn8=Dfkh(11Mm.<.PvXdZm Ft0@yV(&y&l֖d}j׀W4WJٳ~K[MX/- QyŌYa0*}PWܔd”>ἊT`pdsP?p7i!Z'A=^xܧ}s`KmŒ)X?RAEg q$P"P79\yͷ~[m,}u"ie\ \w{㸩mbVh'vN'S{ PHM_yLNRAyES [`KwG ٠1yȊDuz!sҝlwLY06FH$^ 1P9`Cљ[u? #ҋVFjhOţ)Tﶋ0Q9ّR5OvB7M'W _ŕQ#EM_8q҈q* hAV1܊O+ U1up ~zio.KESlP&C::(\9 lSMDIG9G'"6O/j 3]\FqlJvX{5܀^hO3rtk &.j(Cz79 z2|;a(97:Dhiݧ}s.[ dYL@_H)Svw$%T³ aS/Jgӆ:a +nEE|ƯGחn;v"nzvnQWoG'ފ[l.# ݁>ľa,ŊQ^Bld1D0}{wŲ֕@_%x J,'~GcZpبث4dߞZ-18*Qk 7]ݏ>D6zr/D"b!#dS^qZ8':j@2fw []83" T{xbj T `Otz̃נƨ\.fBwCp l{;͢W&_m(;=z+$q 0>ь3g $Д- T:`vbDQSti=ʳWm*ڞ+($>m0wDpJHV';|AUCwL MveA{zR`]qǢίm7"|W&l"p1qތEx [yb0 "#LsL向U{6atتfZD8) \lpwf``,i΍Cٷky[Vʦjy05E&Vঽa݅qbpVho:n. d=*l}v]'«&ޏ5E`'zLnG/M_ +S(PSUQO\sh/M ~tʶs=Nuf=k.B! c v2ۉ#uvb'4|i\f;vKOZ)T(K bqZC7ٷko ~2,26{5gnL@`pPQxI`zo7*s 9 8'VR a++!k'r0[8 ieH.+S7D-Ra[яQpRҏzN0)1ZZHyؘ8xx>fD;}7`B 5)Xig@CoX`R/^Sgm0oLY.!˳o"cy,[WWXuch&N](y)V7mTٟmy15еS@Y$TQ0^+ 3TÈd@h}6>ȹSl}s灄_>s$%(n,ZzkتdՌ~钌FT"6I IPΘkCZ'=;+GՄ62B#RJ UOfW|bAzޚH Qyjw>H@w_6B IL RG8m3@/9h y9[ \{cփ 6S0L2'U6X*yQnE~fQ&ӞmLMM%=|޿s rPZ[$zOk8xl&++:)^i4%--#V^:H^@ziwJ ZE! A>n "P:-BEWFD\=־| w:`-B΅iߊ24Dx1.*h .aRpu^S6'Ff39˾8" \ݏşY8U8aEw@o9@1E4Ќ~AZa#+לH#ݥN Ynw%|M6 !ƫq"/ynybK۱֢,}e(D/ - 117RN 0phQPua?Nj@JWQ,y1+km^@9 ۍiK1Ƽ܁ziQ>DR(ni\[Hf7cfYXCLgkX:y儆hhF`7X“=sj;Wܨ}.h ⛡`Ʃ?s bbaINyDO*+,̟2 bE2ÅhX; UAeI\&~[e}+e%l1'׺Pz=Ǵb6崽.yګMX3l|J2=mxM{٬t>s m:=t:H%GB7ٳEzn⯼C Z&6sl( S[b*z97A{ bB*t-t ј]X蘯GO.=\hP7w(fq ś~AE'8+#B >xl"Ўo6*= @yxu?*!Yh}rZ 1bcIr}z? &xoĉLd^ߕ*Z[ߨqޫݲbJE( z4 bTVC [ in)oEC<Q'vq8io.c<#*2Y8QX́p|t׀;jƣ9d➐8-#~v%4`3hP:fSio% 78VJ[Lժ5B k&^ΚNrDvO)XBry8(-0Iڄ vXAO\&ܨXݏw2y:\b{ttz? S\./b:,@gH@Q*9Ko`* + v@ $[2)g qLg0Po.8&!?"k,qԿc$z\ )`ԐC#6D;*} @Er|ЧTW~F^ᘑN3zчCcV`툢o?i{k8F(͝.D>fH0LȊMl $C!)3zQHxS` N%TQr@YFf5xZeE.\Q v R.ٙ:Wb\o~ɰe"^*IjwF16h}kqUX@HxjRB uoG\v *}lպR(bYxU-$2MP,t}k ^. =<: J.GӃbin~(GLS6Ja۴mҰx{ pB4 9T Ʀ OeӲ09ψقf;~^ vu?\̌PugWDhy{spc^F'MF8I;/:&{:ψ|q t`- 8 VGxu?pUǁXz&J~aUZYq O{sʐaKn` A8Q79SƌxM(Nvvͧ Zm: j,l`/DB&l<oe \ڬuh$3U){XM K!a1Uz"5+_5bt:Ғ&Z)x#ܓNj1E5=`t ^<~Cz<U4gs~?t %_H9$PdJ{Mz)ϥ`EUCk+)a??+=:QGT z=y:ۻo+??=VT67%YkrE}~S ClH\?K0><)HVB xc۵=3)An@7!vE4W^S %+RR~F3O8lUi{E{Gc1N _i L.y5Q"誀ڹ,}7®- !p3}޴aX~E>Wc;g4b!PF|;Q8{iJxxם)77ۤ (baT6+#" .wְj d/ l̏mo hh[tǫeMn5PզWq6mɎJ-D.j=V ^giT +sɃ t\*~{ :)k&wMMmCRU/ M14a^mI#Ҍe➴ +*KE>5%6))ƄKxOHAlO+TP*Rx%-P+%B-̏be'wM3iRpq8,s/(őyy,z2̌hc͉`zTaTe$mͮJyI*} \0T@VW֋7]ʿ3lj⦛,zebh@DJ SDf#tf>򕕹'ETn2,m#`"И Mt.3Ttɡ#1EzWr ʁLk5ĽUr{U02&u!4xob *x.)$&AeL1/hƝ*7M1=ןKBN@NnBlpnIP)0Wgy>P:c\]Uy_9:"5; HW^ y4YZT9UxxAeWqwR705[W1y5LJᄐ @ ]j( e߼sI<="<8=^{0ŭD(ZԙY yVj Z\e)r+GZ̙upi Ґ!mt9}YISiQ$M}0Dq D<`2E!6WD`*zNGQ&LC4OMAw=#.gL°׋\1'F+6;9JU6xʿfXSX weLTtĜXSFL \*ۼZlKQOAq{lFPd Ϸ,>[L $ ~o-"'ưo4l,LHmSu/k1jIq]` `THE(,qJ,#c-rDb !HqDВӯSmG_͠}f`$v@t ou*m*^Hrvv$9gv^_KaD}IӄUBL"5^\B)xZ~9~;sS5tޢ3Th\gs7N,> %(; fXN=xɴBF3$..̽s>{ɿ#/5х <|TNяv{Sga\9o6(RU[kLa O"&Y+$KR"ڐʏ s`S hrJ1CVZKƥEnB󂼍ƘOaZK ; = z~-y,}A/M''EPrcֶkꈧ냷m "'nەrf\Ĕ $}zIV${G7h]JکsJ?ˌcpm#%ڇ2/HEFZJp%=xom\S,^=4U^}xk}sR"<5 W@33$ky{I8[޳_d;GV}W,_a$.$F#Z)zއz %nNWf+3 9  ʀ5",ܙ)MFV50d{2ǁCDުvJcEy#'}|1$â3=Ĝ,*wj 2HpvmiB];6W4kA[046ﶹW.`Њ0]?>Н. m2j ~/y}Ұ<;Kޠ~:Ouj7F'YMiU,}YI#?7J+wUZ&Y+Q~_Km4zKO 32*na<VE(7r"G>Uo |?=J7# >y;L`/R8\JۻJa}$>;^=7q<C=*c;?r)kb2ѩwz\{K 0KQy K*76ȩLffw@ܱFC=t՟ FI]֝qnP\oґFO"v }qb/0\7bXa,{mqS 2Ud5B*B-' )TjrE[XqV{{IPe_<l-};0)āefثNcK_RsՂpiLH2aBxu%~53voKyT'>F-Z(m7F%S _b5ؔ-nF`ӎ8ce")vࠈ>gRBt^7OjحqH0aӶsyM MD,}ծѻ"q)%AhL$Yi)K#O=L{I8-t.4ĽIl;bl,-;H5m3w͙ow,O+7J5̥;a ^$՘ǰ!* ث`5W>ڔ`hW{xm]S+D941Yu3̹+ߩ+[z}/y\jG馵:;b^E D <Lf^]+t*>xַ} *vB))LQ="J\&z8 2=l*Hf&ﶹ71z@jBWʀaoOqVdР{bhP9)r>{ɓt}!:Z뮎L6:aaE@fXAӬw(+8sdRXg̳Ő\iv 't Wr*diO@v : B2RFSȜSq7E^OqE]q%&y]ni|a땅?ẈP)*t;^+͒{Lԭ:3-u4ӱT*MY'4o\PR\[՜kc'.9I< "FOw<8ZHrSQ,_Dx`JA+6qtͰWGi-SS(:av>tfj ؠ}%9Ia7'dGm s4@绐`h(~n}p5Es0Bby#?_ѓ%6s!l5QPx{*WE-h\ ʒ`5TYSB -vXbA[YHќ^B9+k#E.\Q{=wÛmx?%u#W0V[  g]P HDy>A['n@IO^Xnu&z,GP[J+#T ~5 z/O)#јXSg=?Ad1Nц3hǔo|/ bE4[&S#vSiCyYQ9/>ڮ26{_'w  `1,&v-9c]ߢ剤/,*p|]X}EVƄ СЫaǹ*, (Rvz-6w(*TD,ܞm$fj̰3c\\iJʢC&tSGx.wS $#0rktc~ з؉ҔxrS!z^>cBrpf 1-FT~6 5@ s2a-/_c&3 -~Ģwւo\')saRRuX3ɣאoD9j!H &{އUb~t0YSQ,aW š3S[+6L<}Km="%4"RK/^*"wvQbPa|&D#P51N 5N~c0.{aX2V.ѺjD\^ߝ%ɰKdMM|(bvf|wFxņh'7˹B3.'fs$Z([)Q{ckI,8qp Yiu :L>2$waJ)i[ۊf%vԟ{D>)dqfRV}uW;WE甲6.^)m6 ]1"t2w !#ۨ7 0 I{g; ]^)_ m* Upsln)"U2B\7:k݋Fw([)5Ng. )Pd%OG)j{%.d@ $!# dE3yӃ6Wށ)<zu1 qks [a[w%?$EFeo+-qpQhs!-z\$NߜA<ѕ4(xqUHw ŽP_Jy3גypXT~Է TѸ6.t)ӯ@slW f]F Ŝ[9d( woG8}^=!nJiMQ_5 %'T* !M' ?XF9P/FŠz &̱E.)_LHrh~2/f9{IanLg糾Qh`Z) -=WÊw@3a&n@L\fϕS6YC. ٝpcF2)xl܀b)oCoL&`9/ij5EJTbTaq0ڽ' B }7NQ:tarNxF!T]QϮ`Veu^/H ‘>`37qo5Ee.>~}W"޲du WơIDoEZxwz˝{3d/=F7dpCMx~7z^tddS4Bb\$tdIJ|vDBkEK@(((ތ|.IDkFYVζe,&Fh4 4Ĥs؜ZoÀEn Qpn z X"&eqH{[lM;'~(,upLwJbas=RL4.:ZzDyОBW׎)֮R$9]\.,fRH?c4 oj1 \[^˶D@1j'm: h3CʒYܵ1KBd8:Ao3+ ֑/gzF+X\Qt^+G삒BN'?S湠T0&7Ž7ƨJWpN0&"Pĭ3GRo )aOAm#?5^Te dJfyę|FV@T;Wzdƚ7b{!fvd\ ӤtĊ6"pW!^J}G$c zR *~ ]'wRNX5ECͱC҅ ŀg!>(@bs{s,,D ZBۿmQmAH8 1 ΚdA!'T}0Joshht]iTDM{]I3.=+8|˕:(=s@5ּY6i9|s^ ڀ(s5捥D`sV>߈cT  6DQѡ6 u2lt*HPcXU0u-UD]VOb> %3UFNʷF\R188V_t\\/i2sAmb` ωYӿyVĩqް@MhtG^XZb̙IĜ5)Rפ~{Z tVAAk4rb]څ+*~+WbDkP𐋹o+Vd|c]j }keۭ ~ɻ& *17CJu .3 $ WwjK]=CEpC— xEɻ/l0c?NCzNm eی" 6>jǬt4XՑZkP Df6sH(xkt0" Q9)gZCE"}.6NӂZ[l'f MMf;+}EM+"PX̠ɩERCrwa4Q)SyPڱ5z -2b֬z^'f̢X#$ljw9zzԊɵ^!."0& WɒAYd8^UȠ]>p ƘDf^l󽦞~3 \-BZzJ5=U|K 8 b9  :}y-TMIX]Ěӕ)9fJ0͘ʜXksb8S}PvixSQ 2FMi˭"/XGLɺ# ~+BPuDڨQpɯ^=鸄TKaQ%`LOW cnďVT>UF_F{݉e;%yL>.85- {AR&Ҥcn595 MMHϤ^Zfۤ]u:8]]Kqw{|†ז)4%Aq1`b. 4<ې&~#_QB0жi3ƭζ8V06PȷvU@ ujW6Lb~GfvGk "xMH[g^úQW4*#JG1:_qYm\ e;8F|#uk~`| 3tb.R ̠WABS8i6a4p[=*ǎ%(>t"zz"XE6VGGpә&QO r N\\4mX sbʛ7fAio^dYbMfУ($>(+&psd舊pkl*f'V z Qs??nuPI^ b:o-1V"Ԡ"X)e&/ VPH15y-G(m\Lk{R}Nε‰cǠ~͵i1܊-L.΀ԋ+.ΰt nO}:տפ W Bt2"MT M1Ul­F]'/LP"(8W*{ۄo֋K]|%tt$Ps]@m\]z0pۈgny}ŸXQѯ(7^'@I.1CLąavEyefKZ$ \wsMu25̶ߠg(P-J !c gPJUb,qSET(UuPf/p͉xy5a K{,.a_+/mp9Z{WnKrkҮ'EInR5ѡC Nz[;z% (6ZW[5FNBu K]s[k1k6 ^%d"b#l^aO &bExn1t@EqzɴNAREYQO?{Ls:N+Q6 Ļ.zY(`H%yӪ5vC?*a^)1ze[m)spks^Rv'`jaqZ+/(][ijbOM{Mv}Y^0Q'yc{ IdMX&ǀj;E\fx%s+-n /F,fKx(:$UE^n5*w[e0 \rI @Z\ r*h Jvh~K>lsLV0<X8wAr] kX-5A$Z.c8t?+vU 6$etZ1& -$E׳8kNG7I xkdӻ)i51%Y0"ÇLRWs\\P˧g{`D 1.@Ůu64!NGXB}\ I۴| Jx0.Y+p. o.="I縎xtSzC]ߩ}smZA+egjQe2`tY蘩d1B0eF5> L,v#LaLL]g!Ãs&ԼPWS :~+"W *+H,IV T>{9tshB[HU^!=$2-; OzM]'Zwj\+ ѡgrBOq`~^WLa[ Ja;Y@.^rPH |եl ^x@"VA#XZL,skRM2x{H²ks\--̈́-&S wwh"?h)P1PfC-O[m sɫ(po GF[q9.:u _^׊CKxmY!D:fJEӅ}z=CF=Jȿ쐂W$\G}>W*F->RVf颤1@[Fmі4^|kPvhCA)D5S+P.i L#xOOj2 04V(妯=* ^9rb΋^Ktka8Zi"Ubj|u=]Gnvl-o缹bVFFkUQ)YSӖJ'{W&;hm `[5˄:9R}|}NLt]1sNiY͵~٩hqPЎ'~ްpљ‚HOE{MIۡ誳hqG8:?јCJ?<0 lZ7J՚(U9q/T8.Ql4Ѧw^&w{tWe;Li"J .{$ߧs-.͞GTԎJBh:89G[8^ w s?vІ2E2o^#=pj]R4rb' G eWea b0ZZ3?)PBDg"8ʅIFF`d.!:>~,z*(0+Z-^ UT*-w_5+ G+2[) +ȥWcx!Y"ҙcait)\i ݔUR;24t2@x"-Eb-k!}c;'yc+z(:SZS$Va112ZsPebRtkWdLK3]ZV{?DV0k*<3Exb1.:QH6P+1ezz{:z#pLn $x'5jKMq뎪?F@!C:1 ]9u{աܹcD9#esi?)T(a|V*~IA,UCoԭ4Pk וwz&5b}Q:{Mԏ~-ro=4k Ŧu"'iN/NxAEB8 m)ԊRJysaEltRCWZ1E)k ]2t:Eshg㉓yi쮿4r\h2 y<3RqV׀ dBJyEޕ ڌ8f 3JdߚW6ǴFdKE{X}7whkM!4&8bnkY}#ҵQu_W5 b(<;nuW,O =7s!cC㡵MsMcZڕ0rP7 UqqJ;,#8Z'^o^ d.r=blhP1 U!s: ĕzgoBV](aEi &ҳ CGl4 q?wء=55O.u^ebȡsŊ-G;O46*0Ju"J7F{M𽂿ٓ`r21^vu~* =pD2^89oU/@zZELGlB1_8QiJЄsdy5!NG@~J&2\AI1ġ@G639Y\%pf;9ޢX8;[iKo<0Co}4(8K&p-"{JT^ʦ2u¢T^~͵{E.9<Ů#sP?ΏsF;)Y38s\RăKdr8s:.DVg)jUNAx_Pg,XDNqMzZ u&3ec%;f7AQ2eZñsB{_MzJ* Pc[jF,IvGRF8P<{M CuEbZq\6V(Ph0p=!/|'GZ }K'hFmPUY^Foa4}ym:ܚsCiƙҧI(3ňOZalTTd09&Iޒ8dYeiLv ?;{Mr,BU_ |ʵ#̐kzKכpaIZ'D܂H3.!6J u tP,b̯5~rα"omyw/ᵑfQ ewL6ztQg]uW6*k2d~(qcQQlhSQ_%2|z /a(`Rdbk>05GTW{>k` a =`M./6; i$I<uVk:_Eʹ^Dc8DH/byzwu~D(@!̍<0e`)Bj).Y_r|N>[0 Q1QA 8L̓"dwu0g}X$s⭢uhC@6P{{M]_g]m[9]J"?WTۥ#K>͵'`נ BglF20:kIYP{1< Vkt->Pe| pMܳwa HGŶYP[1$/}(FY|5(~nK[¤e?WP}OHEPuzXa y̫z!Z2RB-8o5bt62e)lEBM}]츙o —Gm}1$+M NjU RBwGN,3pMSD=jF)@ ?B#U[)'c2B3#_-5OY;;8IWj{G^wK&}񽻺Q} ԉ2ԒiJ yŤd,U|}vO2yl~ NѸčn]xnL[ZDHTtģЉk/# U25oA5y &~WŇvRX>ژ?\NyslƜ[CoNPv|2W>U²9.5ثP Oyz4IuҏQ$phH߉%wuV\(*F2Ac',L~<`e!;A kB( o~P s)o v=U<<m]*-lW0~9?<5d V,TZV6' Fua\?OsdVыrEi\D{XA<f36`UK]Yu).0߉%-[$GG, %S{uaOQA84rR 1U-0-tm^Ʋľή50pX-:Hlj1M&M e~:ӓ!G `1߻Q-hpU!Q͐(fDI) ,)7TDݟ 5㰪Q{z=4G|lE(HTR(\)ݧs1 Jq݉aYIAQlҀ4GL<<=P5~HtX2ﻧ;ihт|^nn\z4-JʷS[?!Q GŅZ6d!r;o%sMe6*DVoExJs\`7ZmoZAY-Gd}K}oѭc+&ql}?t윧^\na='b d"G]6}7J 2{4;fw1 >͘rttX&S V1q,<}K{!̓sZ8zmFJ?;qd\?OZH#=xp7D93sǵK'޺} ;a1^`> P7 rJ=}nԠt&.rt|;(⤆ɊBXjVxp,QAze?!aVQYz]W'}4%m6Ս4)G\`Q4 g}- B"B_'|yXW2kp_{pa'FD c:J㢴O'/j,WA)qYFQHP]gsǩ\*DԝibGӌ7?8} =BB}ӿV\ʸh9m"@u 6e-;qfdzpTA) jmQ,qh Un:ʊq:y\iܧsIK*]*zeVp12Sq(h2vLP ΕΡ/X-"#rbUUKڀ$~UpľkF [v4whfA]QrOT/Gt[|%>WgAkQhѢL+Z" i_r,QDZ` )͵!^QVkx_͍QB$IQX^5AȢ /- f4:)|Hn=@$!㪵wFMw DfJq2=iݹD+PsE'yks61)ywjʽkuɯۆQ\UO q5=Kia:=]Ν| ϟs!-֟NCXgrXm!qū } ӿvr1WJMuץl=O&fs1-:UJS^ÃҬU>UXb.;QsWhT\܆UQֻ6Aʴ0~!|I9\fIwK(mM躚(!R(](!0e =k!PcLd'\pd²S595-&^=BMd-ZgPBEht4?OZ=[Z0m~w"eE!Adi[S^<ňM+)P-{x&(\$}澧F$ȧ#5 U=nrVI])Y%b r w{MjATLirm9O!,E=¶ET\i;V7C4(|Bh? Q5#e\:]SN=-4{MBK IG-1ڹ֭bź?Z8VBb?ݨZ=υ^gn< bV ]dո}ikrjQR$c9[@_м2\2pu޹wu?Z)N`<~A{U|Z+E3Q>+^)NuA88[xىrFE}7ܖ7b^ݨ-|] ]bt4΋p5-,We 3%3nS#r^E; Pݟm}a.m](s|sʘK>zgbWC*5؁͋^7eR(\b;n^`pW[o6=qՍ@Jew-\DYP1dNͣΠ2n *W{1~cG2kqlPqWǝ>z'ΩL(ݧ&#\Dhq,TșhC)kS!oը5yx&τ*0Cµ;]YuS-om>q5εXBVğ"NE~=IsMLhrk<^/˝aH2^(E-kfB(3ɱ'320X1^8n#?u5V%hǐNPbtQ *>9e]0GE{_KFA_2- ?u8B(Z\~( 1PڤF܌ AhS(D"pTiT8Iw}ac!j߳s>ׄLs:]Rsȣxꋠw$rmsƼQ^a/ט)" .ض^ 6@(3z y^|KTZ ,6};B!s2Ub1`0=0-]yu,LY(އWy7Zap6 q]L24D9 ^SO;}>u%K+ygD /_&ݝwW7j *Vk+ ƠF!Y:-tf]"oZnzt)Z1'ZCآǟvIpq!YoF- ; ͝S:TG[(9'bSzv4+2cŭdvG<3ʨpY3n@J[F]?ÆR=3TE鱼F DDi}g0s4Gҩi /^: SGGWkݴhI2;tcǚ~;͵`fW,vdD>Hg^59rbQ6ɩ͘NطEl,|"ϻg DmĈ:K="W7jxLgs4C?a}te!F5bdk­^R5W6t5‚)/~%s}:NqIumreCKۥ~gH>)TO (`+Es)DX 9n/FZQ*\5]xJUʋtvc>oQ4_59h/:*;psݹyQZB S˨O*(xO74Fa߅1i14D5 fXԾY \NFjU`/m/b7E d]8.%|mBCw_(pĝQVE9=RF_X0!aOA ۃs NAT/ɨtSQ3  QrZUbBߡ-TCE\Ykk܋f~N6*g=O/v@Qmҝ'0>5ڊ^U 镮i !R0]]4r^=5"LJ¹)ѭ/ (?W ګsUujڕ@Hq ,XF}R{1EiUzp皰r2_ 1i5׷~xT#}y@tlĉs/JQ#PbW66+0:CHKlkNPV(L&+e`+y[nFc hc&ޔr؜ lΔf7-e2|v8EkQ<FOal{oOsd]LZ/ιQ]w!Un&ڋՄ"Cx{OT{:(U#I\4N$UnUq#nmZ\ \TDnN,wFtBA ٰ^L{ڧQM+E%& O).RFn-\BPA9VDnTHN{٢-BTb"y*0"hԀ ?O&n$H֫;N^㉘ ̯lAӹFQ.A;1#=M'zވo(!ǥxjϩ\ztU䤟A=H(MPϑV\?\{}0ăV!\ ":I Em{Y{&p^8MhS9cwR&VVEFQPaJ|R:s*Z"ܪ-2!腌6Bj)/{MvNV+4ojCYXʮ{I[`S7g.F4%?OޚՍBk˔#d~G_̜97\<.]uB>5)c>ٰJ 圈~5Dk 197׶FE{HW<w8fv!rщmaqOՍH9"ц[#+O #Dey\A a9xܵҿ`AT*ZK|27^( =*43Z,}SMzڣϾ{rڃ0]Rh>(MMp; JDxUʸ="W7j _9z a| -aGcWCH%i1C kʕ?b?_Pc\VoNir nBoU*2[QVyvE &a*,u =T~Ͼ\S;:BBM( [pq`WMU^je/E1VD,L[Q4H/B")V]Ts*zo߿VA!'PYOU>C%d+ j)U$^ 8 1d:^JxVq,՞[V5ʹ} gS$yFfJV= Ifyn2Ht&aOE{xEԢV&pyyQW^'ΉObؘ\Qo\{M ͻ1^54eᄶ~QX?Oo1)*,mVh:@\+j\M}Dk[58.97JOe SO2!:}ɾ$aor:gM,zC^NJ+p=_( J-@V(}`cψ89kC"LŠo^Kr,8|&פ<^UfOw/sb*){K}7*RmAE^Be>F2;"cѐykR rNB [>v䱭Q7 O-*waC1Img#d!tYCMXn瞈ɵB\#gDjyzᇜ8鑉cq/#kE:[1Z!@\“7iL䀌HQĈ@9[bv|IwOd" 3et\BEM[δbʅ:El͵ Qq()ٙCџ^Ig[}t0( &+<}4 h.53c.xZu gFD0&]1LipP;sM޽q|eh.>OO'h1tt1GʹP\'OuLWmC+iketzг0XlzY \GK>O& p 9nZi#B1ھOkO9NOzbOrv'`Y|/פSPƥ ȅ;=9N^`<\MJAk{kNԆ"EE#d=^#>uQ@y1zƼS)@gƉBOa=NL-vCޅfmꊢ|Vn2壢 AT(g%AJ֓}皼{mJn$#5d+XcMNLym;6Сڿl0"Fe}0(qgu A/!{FͰ&jc&@ dr)nYnv3OQ* K#VGnF)50lYAe B9 '!ŒB|cך KkP6 ')yϻ7NJAOEtB)ַ:]ݨ4 B^hNsML+(EexŘǩ["f*g,F"{_7DGh#Į E vb;-dj6^x4c ioR. ['M;³݈yuqzD{n oW%iTyޝxuD>dl:ӚX =ST4WZZfcA畡+>kq3 Wt,J⚛>ǯAD_d\鷰gΣ+voK҆"qZ^"(;:k#(RnEY S ̸Ԉ盆_pbuk Ս < 6 bBc3vo:]D(=*zM#msdLqSHbIW :4s=5ټR]ݨUhyE=MO 3ŀ@'ώm@.2 \w?'ק)~`@ 1 JH= }YՍRR1x,I!mҟp)R1$6%zI~ U8Uf[7To>>_VL&FVW7 _-(F071_8 c21Jeܤd>| zۮ 3BD|f^HDJFnA<0NwPH+Gn.Uײ jTҾ֤utf^_Z?W?h!Na:7_(1Ջ}C$Z{,c2]~8 IFm,n!RO]pK.RGDym0PҲ400l|Dq~fC^Ss!ةSRPeB)WLq1@ hd_;y'j?ӍR>V` = l)RDщ*@yqu!hs>d{+z FE տ̊\%, !EtOڜt"A rqm~%UaX }^ 1TE+ri30Pr/^SOf g>+7U:ST/+;U gн;Qsr-Vgg1N$&TcXdcBu&@֏m 1j΍S^ǎjM(zk]M4ƾJX;xQe)nՍTש Qk8YjF7AٴW#&OD ! Dx>O~QTNgH)F)1Ƚ1SFBůkuY$W׻v D& F.8\T?5dW8iqM&ƍyfOUx lJ] rV"_6E @y!ɾ*@cxZqKJ)MN,R\$^|u @{(T5:" DW; V R^K ib&kT[T|"sח᎕M*dvnw4ctd߭GCysD+`NlK{o?+9wLٕfE`Bh=ըQ77" Sbw#ՍämTQ(Gە!dj 2S^lŀ8@V͘g/]mrk qM(l~Oy- V"U9eEQS-B:NLq(>{? MgK9/ nB'TG$.\fv[in_O7j%?h2RbY1aĮXN)bA^ɴӠO?~{MxmXjBFLwJ2+:G`hf]E[o .4D مY[.>z~ P”>۟S39+']+bE}NmWvOuĬ+9o=32+t| h-=\ =r IIIe XV-Z~7% FJ>"C1\8 ؅3?Ťz#ՍģG@-<;W,,{pՁ0]vY|y6 '8%sMjQLc- .lۢ wnqmH*E?GOL<bB; 1f5Ve| 1rw:Xk ,^1k9mW7 ꇴiQ[1%AP^h3#e{z9ka$c\~~+y1vTέ!_ݨgaQfA)^[{]rmhvB^*؏M?a\4 VG2oꥴCk_ u Nu#c@* *Aˤ%XiWe>P/OX<{?EY%T+߸%򩈸, Щ;-ӿ6#$sH kl.;|(Φ (x"h\V>yP>LEQEߘ; _iU+{˭!_(mj6\г\+Ѫ'c>x̠KqZ.<=hKEDl b^{D3 H1A^nTeVAaNem;ظ*fE^,4:Yh\F x[YO oګ٥T /e o߿VPPaNظ[b=+$;*ڞDފ皼{=vEhV2"d"0_u~S8Ȓ8R4qc>~+?ݨז@Q%q)w8X E;OJs&~{9osMK#݅k!aAE;}DLē 蒢4\ ?7_("ATaJJ:}ڵ{ב-,.uU6KJW$ݙ-po=mW(毞suLHA8<͏< # -"@w J5 tT}քpi'Ǭ',BsŌ Jz:lpZ^$ U{^lVP䵔^u( !3(: (Q@~1SQ^.!FI6XQPU +h} R%IȀHO4% j7&df:Q*XahEwyu*ZMhWRW?E|ubfoj1zTs\OIMQ@\,kj=p-7HeqΌVӵFV,QŜ/&F,`Q0uLrj$&OVW<#Xeosr^I&Wrzyn3?Fվ91fGPBOFZIt7IW#}ik9E!v?="X_84=;ۦNnT{أ@;6ѳ(tAЧS(7l]{k+<{M0&/Hx(k׉Q\19 8c\d0RzNFi9Q8C L͊%}/KKJh7eţ&H!E^^pG9 ꅔ6dCo ֐nUSY@)ss%JgPTQζHGP^TE3؛j#F/'b.3O~~䪱>(A͵(S-EfJIV{'V6)p*(;:Wlϻ^wok'D]E?^!6TaGXd›P^F C s&j23yuжE RNYGKKs;v2Ǭ<6IoKQVh+c:5=9.b30u`jb \YŚrOy7?kR ڑa"ʸt.'%d'BAAazpt?u WG`MFZtBf\RA dxN` Q޹5}-B*qM~{}cL[І7b^(c:s(Ղ$kD6ygjqkRCUjFe쵅~t[(px* ܮ Uhun>h)\ݨ= DZ3;}xG$#N+wL2 ENx>zI1?d TFB\_U(&z Q I_K\+PN wKD!ɐp :C)8QS+iKFUWmʕCۇlU(~>M/W44?)C1~lkR* Y~fy3xӟYb 3Ivګ'Fc Hم[:Ac5A Qn A ,Y?Z !,wzA$OPKQ$u|:/ ecb_d_m.txtK7˒݇ ;hdl"yh[ i"ҰilnI s}̪Ȉ2#Vk/W߷n/?[?/mOn??7?mo_oo??o?oo>yO_+w`.1_?B6яX7ڼR_uei;_i3Z|ZZjp;{mߧYOhJ{3}D-9RZmm1wZgF>j-1c&UֈgL;rvK6]+=[1NiWN4fʡP\ Kxi#2mCY2!1.5s6ӖaZe:vad*y畭 ϴo]qv\~\K6Niw;6o.βK~bnϴeYvL<>V,Qi7mɭT?"_ڎ]3u tiY1,-Zg .9] T zbldK/ZN{Qo;̳f6lɬkXߴw)c"os۽>vϚ33!:V.>7$cwc^S;Rb 0Œ\6?a??MVgXҜ !w^έ)`MveJCZ=hsTf>xuH۠GZ.7&ٰlZgSԖml}M7 Qm[/_| ~mvNow窺Ʈ3lӘU݆|3F暉g;0_5͙Ui;z>[lmHmyX=?`0H>6ywŌHavثϼ!7'L8nmxP_jlVUٚŇHtR´x^쳲3$r~~`*5&nVz}Hdpra{J45 W. $W⺷vvz qn M@u:݌8|ns+do*0gp᝛8|gxM3_]<4@'Նs= 6vؚ|hN~Xf)fVawsZ9,:ND.!#G=Y;u,qy Qo7!'Sk8Nܶ=׮C* +ϴ{v2#c 514u|ǻC2kY6x줺bJK'X lyILh] .`]cKӚA+64N _|R{6?"91%>^"ر20V7֌Qv7߇|j 4@f{6 .-~ /? A r}jCT`G}~>$plGg,g_5uXeP"*`@!ާ7ַI Wl8(Q Ld ƣx`&r7 K /v,NXp!fKۅ 0?Jy ZV}YW.vc; (>򟿪%`' ˗Dpmڨ!lߊKÇl/Ɩ<}92\#! wWzpzV(inXuH͋ӣy>0ăWyᛧb0-W2c{y}H(L&Y ,1~lЗÏ,ARd^"4b,Mx)?VFum|˴?q%5( SFz/޸SXq'cwkS6;kaD:'sm1X/6-5NT>5HICAWD'ː[W݁+Qx(&)| B[07ov%/3C9$~ b4z7篊:6^7Ž/߿0dIf3yΝy?xNh_U!u{ېG i`Qa^$?>5{O&L8-AͼuHI ul&w|/CKpsՑTd/m&}C|жsYdm]}*:0ZURueH2g%2m 02z'zsNl;X-)e0op(ON}+ 0<~cG}C̗/܇ lg DUHW{d=Q-!+mw) ܲVĶDa p^@KH"1c_)?9&xS +|7cW1͕K4-0FsV)?9u)T*^n+67d f{൫ϼYBKewc_3θر={Rv-n]&nWޏEȋ)N bBwW!$XhY/9tǮ>şxyDp6 p?>A={>yRqh9 &׎]}1dƆ nnC2oCᦥP.qA܀|(|UwYCu ^yC {^6&t?6@ '=A=DmkW!"qUcWW%#@+dw8!eW:k470YSbVc~KN=\:o1Q7FeU\pU}4Pk˯/^|Q͐fR MWx6v7jX݆d^Xw Y=Vx>ÀD1z#8ޢvDkFV3qo_d|_LRY|{a%uH#hN8W>#0]8+0!£wvBD/ö|!^} `.݁cw> I@h(%;o)ހpD2ҡMZyd:* C(jv _ `yhs{ϽNP%dU&vj\~u~|6yf,6{.YoyJ˹ΰE1l_~tRl=-AljW 0)ۡ#3 ɼݹΪñ wWdwQ9CUn2`V^-f)9Oއbڈnvxfcf' Q%3.)3&W!搴 o+X83oX_ɇUEDp'.\Q:=5-c/JpX;P PW!%T ׮WF?<]_~0lcg3bf @ļⷾ!` l}Py3·'BmD]{~-g7pk^{eAp*vbi9pUo*ߗ~BG7އ~H- 2k!c'GP>oꦄ;d- ^ih//#B7˯1GlsfW&ȤԑO[p ~{H/]_lã6>?_%A..CjLb i,Y'rJMqOThW׮C2/VSE|<$:QĊ[ y,˴+ 3jY~@NxtRk,D6l>r3p`= ==XSC,b"߰y^|uRq Ij8Ёoვ`'k:lx-쨹?߇|Utu@ -.V@I=c/Aq Qե \|6w)a x 먽T|7yw3Cy`U Ad :F4!mCeu~%yq6 Cft59ٻ>!(je@905f˻70;Z` ,͞tn@8kNh J_ܫ۰Wn(m,7COsPڑ-T<' wJKJ!6xTS6*d@h_dⴡ3k $O+MONc <_%>0-uVp\j3YȒۙΦs`78)Zu(<MW<[† ]QVO3|}S:.tqlB:xBL N9ۀԁ`+s~e>>5e)uosX[P ,^1-9Ł1ga.9P]d)/rpy[j}tB|>ר1k &Չ\c3֥ׄ 繮cʸJ>LJ)⯋mb?TEc.{BpxC]^Op3|~qn;C8ㆹc&' _ ڨ?lySaAyggYT-ړ잶%2L97”]oC_~2{3-e@3uj {dcG8jlV̦=b @{ocB.{Y9v)*x&ƃ'g`1h 5O=)nDpݺr\qTz!qƔR5<"*vq&<n7eCip˜ViVny>&U뤿@uL14ʘ pjp3vWny.Suq<;L^}>'MBt +,(v9ubL^E k`߉c>Ч p#ß؞ xpU]wJ~rt_L?(=t܆[ G:~ X +v~3 7Fs_ }LY5(O|XF^\'^e=7[©>w6Zzc]L4ֽcOUŃ?!} Q{!nK⹏56ޖX md HDgvC#YuL&<1P8iFnP$%6GdS{Sx>+@FV}s&s szc;Xފq G2T8Gz߉ZaA_)W.V) !c假=A|io?6ޢ7]4!POuch#T܄pI40=򚍏7(ϭoǔSnx,ZёO<>et X1wrSXlbBHx7W'eOBSM[ovlOs]J2}L}wV隓LJ\b"?缳hd6Ǟ̚Fpdpeyq'%>1WniI+{p1Eawed+i,QVWԉoON|KxeAD-`!pc ȯ@FEZ@ĵe')^5gvo7vF\L xU"dv,Rٷp?Y#9@%la)|g}@q&dY+]~ϵѷwa^ɘ 6`scc˽+8:W@r,3 $R5# *2H:]OwBڮ6t>;6Wiw(;"/٦Ɏ77ާWv1W `+c (0OlTTN1j%5I)`eWOJЇƆz]}LMܻ=8aMMK16Msxw2@Tg.Reܰtx_uǁTPFL Se21݃N3YF.p3b0aГ>@nc>ܩM.:rI]<ħǀ1PmEWqۘ<G.:˱6uIPH$oh:K13|c˼)f(Cu;)B'K>72(c) _e*_|1A'QÄ}4W쌥,2eS!Mx&=v}P)''Z)KUվjx{ O:Hg>BJC wq} Ӭ mͫB kǔٰs8;lK/%/{DؘK3%yӻc>4 !A1^`fxIзfuFpPkqO>HT9%nQN.:KR] ㆈn:4DBr j\{ ~-6_k kh,BUtv*R{1Ʃs u-n:ikl:w$ں×m9W!jFj/6:yxЪ,X#!<6~ W'pS۞؜4Z۝Йt77osa{dW؜|C;n`. @E07{eAzQɡp <:j^}>&Q@p;f)iOݏL +y /g> 5t&ɥ_ "л9IȤ~U <@vŽV}0<\sΕ >']ǁ2-&zO;9pk~LrNj):6(nZ__buLc- U YᝮBL|NjAA^ ZU{m/X]`cihФe؟~'#Oz47P{b8_wyZS*]U#{H &>9 JlZ}90"B ث>\چrOmG9ϧ>966;3t,t%zݯ#^5) κ9ur%<$SWءJQ;)_ l`F r|ɡ_i-`1r%mDWsA̧ ݐVy&< JwQ;Ş]껏cjK-%&O8>ݲJРCvAwu碑Ub>\'n"lad \QW0$cy$.*vRHNb ̟ˡ 娃b˦o~>X,gysʎRrE+œNZ,td@Y#Y~k|S`O%ؤQ:S3Łys%$cy7)M+ y3rn6']YyD)ij9\5h6v:9i(CقY;*؃#sǔʦ=jeLKuxɡL /='ŝX㊺XyZx lCiqa]$-V~s G\@܃;ٻ)R RO@u CajSLSml^:H1;z/KNp'^]]rktޢ${nacQQx)Yb+C/jt }8kueVyb"csy\ VM wKuρ|+`4HSc4cjKZin5hUE5+ɡeвQPx'z0Wh1x>*[53x폘zw!ݕTdN%`}*o1ŝdYw;GR!`ü+?eY?AiwBSA"#3jå9[z̓C_tѠrA`e;T^ԧJjV:J:nѪ[ˉN'ETpL׫NԼGI3ںlx ħafɡWG-!Z !ijlω+c*,c 6P|<0ΩɡEUJJ&mSˡ7$?SiLoBM|jvUTeΌBzW(}LYuG/WdJSzwR*(GUލuSƥNW~7;# /wrp*)zcU@N1v&6x4+z;?98+ 2.kԸH(%L={u7H+Aez|PajQ|3A58ǡClAii?y B"挳2Pn۲Rp O+cy:G%E/KGqɡ5<06STNF&F5 JDc;-]cAܓͪlFFgⓉc{ذ: u$BH./wx m 1=L~/_ZzYJ\O^g_ߠNXNo<&>9E|/n.m$/o$UkJ і39klbx(_'~z85tQg6G4:c1Zu<` ؠE 5C/Qªv`KƧq{Si-~P3*Bhl{OwR:-%Cw L( UU" K`yj0W^X>\Ol>'.ezHD=U KVs*ٖӧՔV{mLY5t,:݇R};ɡ/͎lKZ;`1u!B Ѫ7= ?yuEh`BZ!)N'12$`"zHbF®F>?r襏P?`Sb˼)cjNK:CN<>9N(Z@CTItIO>xyu(fz'7lR&zVIv[,/:&w(6eݦ١>}.wr\nIYI޼n47v* TtII{P2ef%,xSKV:N wH?Vb*|r%(Yo}L!q+3KCbaؒct"b!1  NiT{^zSۉ &%oMQHPmğr3DOm ,Tsy@c*,> 1V_]0.Y"|>ɡceLu6 1[y l|~t\܂?C/D r ]>W:i|y;~>OvlxV` M"wz!mxa]w5IG2E}T*-T$z̢uhB)kMr#m1AqpNOi@NxDuU_fd3w@Eוx bQgm;[l_7L\6)Yr laW 5yLy.OR2%Ld> |I}?4'kh4mkːCG  L) y+cQ\ă'k9Np#wrW?Wڒ@NUGoD5 ٻ7 q?yκXo=jV 2cjb3MIHߡrrN2+ i\LM|SK-r;AHQҢ8~7$i&aI\?VtFH)U9.߽ɡ/H pgK5X c)Yw5f`CM%+QA]cSǔUZCeūUw;'{'sӖLE?rAkN& l=neQv'zS$!.ʷ[_x6tXz*b!Fuw\;9&[OG2~8:0 &_/'A~;8W|'~C2E[^E 1>M)o:ܪ(UW ldWOW0Q#}12: ;tҩ~6tמrZ#*:ʛ| (1@6~tt*Ŵ?ՁU3xsϦ6c!'\ǔU1UO`hϼKRJٶRתcI0.jL;>C}nn˚j}pcFrk&hé*>`E?9 59#IX:BA4\iL|S.sA}dL0XrSi ǔ)AՀ1Шz.m9WtQV5fa;2ot=3sIki% \́zb+gwH}SՆE3Y}L;AF2/%I[5SwOp.pΓYZt9`'*"ఝM_SDc$LL3<`?RF5ItzƆI1Eڰe0h;Usejˡ/kWD iUAԋ6ѨՃo%VjzPEõuɡ\\DV-/e!R#cjAKbғ tSOp-z%BGu1幂F%&=f'syU\V NyA-z lEW`PwR''QvP,Ɣ&c QjN:rP~$Etj7|7(yi'?O=.jsdr_sG!"1uv!ѐ#LGms=Vԡ&&*!0oX}[VA™wUV.s>ϥ:2g1Βje [2cjSK@r@k ǟ0QP5XScUQ:qIB,Ƴx5tM|r蓓Hvcyx+ׄ%:x=}FKZjGJ9>2.u]Dy 3ufEV~(K^E92Y+fB(j҂2|kkf%1fݰj%Mtr "WvY,xY(A '?1i}FɇS-/&+/6샅Rt1sOeI?C˷,Ay8?ʰ/4))H:ԯR:9kU0ޣ}Addb~k(ie4U?%a@/쒶MFFi^L|>GsDɈ>W^=G6P$N=ΩZV! <}1X6{eރX44y@a.at% <Wǧc TVqVx4~oy|Ja3iBhB}?5*2(VO %C%rRH˗"^UJm'(tSƥvPL+| ߻9s/DIײ>@TMb`T!MH/Iŀ ܿ}ɡUw3aiu*բ?uSA_YhsTgB[?89Q ml5 )0UnzGKџz'J)ϗ`6X;|).S"tM/"BDV,`2JtSenNcͥ8_TһN}$drJpUP^|1}X~wrUt3 ^s="jFE3w˼)ϥr:=(hjq '>բA }0|P&P끵?Pq>Jc̙֨dENRQ^66*XX)3 '7]l2[fݟY_uSPln",yBSCZP W` KS͝_x{SAB@FnWk5~B>e(01]uX sW_z}L)s[?\O+>g㦓C_{ Ӗ c"/~a:\*&H=y_7>Y-Hg\Ȓ>>5~}ܝ)eÞǁz^6 N$'+S.@⻏7h.ɐlva9NBoOd -&c*H%Me:сV+ZurG1W[PYqb:2c}s9;RXu;) qrٺD>j6PMLylUૂf ±C%b^ `~ZuGkwSp\窶ʾVAsO@Cn%W8շ:kD&_ sSkF"jrznsU%,*CXsp+u~1CաraX?O33HlU1EnlwY(NЫj^[$ԋtWrSiԶQLI6Ֆ~&xN<=#q#+GEQ*ćH)N5s{?xӡO `< & z&)_-i"PƫS-32%oDq=^quLT6R]LRZL|ry Pi%5m%lģL̳KAE2KŪ?U5Pa%XTp*QL4 @"P)xkt ՚N6p1+ ƧnџzkkJg=o NޖEP廏cjj>Ŗ[ !,Cm@ = _\R//10Ebp;E8ЃF:feH(@>k= MzR`PI콩Nd-#O} DUS畑uw˛_}LE'b8 < q@SZ'f~V}0JyN0hZ|O:޸:իnl7Xz~ƟRoVVCYᎶe㯌R4JRj`'\;s.eְv#X.O+cW ]d $;&>9ªY*&ֆ]\_|Z;-$tttO#uy~H2.]\|"N~Ys"xʆɡ_k.ݖ'vg̡¨_X)ソT5f$V}r Rlƨʋ{m9}Lm&ХP,-{\$N}|bReV9\黝c21CǪFHlFP'U+tɡW~l|fTq8*)w<6U;He(g\-JǾ2KH'9IO>+olV @W+xnzc߉?ϥs27 (5)M--q|i2xq*l\r[ 3]9$1V9P%Z@,Ws7t3ZB ?Q#L?,uT+G$/!ޖzǙz] ia91eW%VОyWfFut?bΠ1N=x$ &Cv Rnv "aK[{9 f0loQ YN;\fC $$w<٩ku|A_m:( A /]d+I 1Ռ\Mɸ$NMvK!wuAlcXwpӇZ('6Q)Je%:pK{|>ß,';)<H}$T s`dnP<7g1$ 4%* ,R_Q 8ޔBQ B:ٰ[4v@th 1٫tVI=&p{jUg{Rg^/ XVrSs䥃%d5@̠3wSrYpͰity[Yδnkj"/\`$OUj 5nGͰa_Ye8Օu ))wBybUJSwާx%_TX|zE:?=JR;]U4sGTUEā~f|16; Ͷl$W6RfJc\ЌZhgg+LayG7ϟk*IKյ滛p*]=*crB)yZcé;AYUv|8K*ǛG>W -z܌??vB1/CM\@t*Hc*]jfΏf.,4zm3y'>@IvZ%h4uJҊM)u ,*{R{+)}4@`b5%Gp2ݧZE;BboMOm:' uSO*9$aĚp;5K~;NuyFi`~L]sx nbMieWFi>RخT uNChQ x*XmMZ-rcԵ(_QY QI :~ZA8@u)Bo׮̹ >]3 0@4W]ryR Z.WS (C[O3 s'V{*V%BqB%tIr.jG']>-界tyYi))twqlkK)YnfarOWx. TSh 0#oiu7L|JFߒA f)`~%FooJ8Vrbo]Sy$3 P%M!~'i[fKSvwT[T]rI3>uڷZpg*6$L[ўϟnuapVHBufU68Y)<+bVvTXz V/jD/<7 mR7_}GayրŧCD()9Ny8CXcc̖rMulC <6G3|GMx†;sZA&ZvGVN?Q e<}q>şmOv-y88C|qUbV!aSlH=nl^x<'5̨sHcݗ$'Z;_j=9)QW塸E7Sy=uCBX9T8:Ϩ@,6<\aV|8ؠJ~~u Ź@]@ +5Du)1oS$]JPiC!}8>xÎzϟm- 6K@휎ZQHHFsx(mQt0և S<:pgdte2̦m՛ t} Suo~I4I [ |JGvԐ4dѪ͕>5C%Ke^O!\SrW(]ÇOϟЎ.obZ\zlZ(/ Z>-pox'`9; ŏɔ*L͏'A P]l[ `xKO($4P`ޟ 8Spu8R=ނ=u|7$f{||x6rHCW#PK8Å$/R3bJ^gotƧ[b,1ߖ3qU5hskyBJ0=U5*Я_?(1x4Qi{(DWtzA`[T_Sȏ"V>=\cuz9?J45=]Lz[PYe-9[%Y6F{TJG8*PO(!AN pI9xµ&bH6b4It6SҞXDuTKY,IaJ\p}īD`ݘ6 [Syt_=}=!#^r?oajbJOU_u?sh-ʱW\xL{ʖAE|-ͽ:]:j kV]<ٻ_S:(Ivi/7B3$܂$2Y\VX7W9۶Nj;}?nlAz?dёR<˩{Q!U1V{ Jv^>Qj4BZoYƕ?r)CJ咕tصYWZL 9nԯS2(ib)L$0/*fϻ{A` XaQ;9]} [PnUQCcPtz֝"aX{\߄>b+񻫟W/#U@O!;]S̀ *u(=7F:|Q]HO2֐|w?wBq-@I뀮 p{ϟq>ߕjt1moY(߽sZ<$4+{vF.[IҪ^]5տ4NEZЄ](尴sbԽѪ3X! U%.,ᮈ&h:WNʴ}}>t%u2:{oI@0̷yϟ%tdI.#9AI4p>M؇ً"jBdST]V*h of.SuiGDs5o@]L*QSJr{/tHKzDq_"v4I|;K]Pòq85n+62| JPoC/XH4@laHںO;Q[%)(|"?!gM] Cⴽqڝ]'(ws6$' }a_0SPV>*Wz mfx6}J4*Nx۟z}NЧT./8wy9"٥>j#>G<-x} 9i,4չf &9?mjpT40|ɘ@>aζW%8S;:1gǡhRm bII0-K4=jM{"f"m8s&7.fLO!Qz lQ:J^: l G驴b D|ҲO!&h ?.UQPվSTv5:雚:F>ۡy8Nͧ~)#~o\l|S*0q6‡KplN lĿܧ}XVjIŔ9>:K>U„f#TRLGm}{Bt!iUYV9ҏ724}%aC9LJ^5 |ӉP\(N-cg:\oyPlOպRI~`')}ǏRFSa|6 qӍϟOsK9saHހWp~ZǣS> >M6d`GM,D5|P d{Xo"j$u 1uVdR ~Uhv'OHe51! 3|2WʇǮSGu(&)tyu"`c8{bfQ+-侁|Xܭ>ϑ{wîK 0Ot!+Ôv \QY-MOWMNwk%yCưzvV&`W5$J$a1D I8h/A(|$sѱp-{5[t) xvR擻aՍ$,r+5uӇO>Lۀ?6` 1RV&ڭ=d %h^j߄ QsGVu]@7&uiOktv` l|ziع$4,Y"jH<"J AP}ϯbnǥ)w| 5Q2ּᤆ*9Wڵ΃>;ДSZSo- Zw[81 )K6&Ϝ:Պ0tEQR szY}R4UԦ3ƧpCLX&Ef!ϪY8J#ج;H 4 @X^iemҵQ9Y{.Q5YK"[{))Q:R1H s. (7g8*5==!c\qO.M1b)`% =] @%jMY Tu˗p K`IMh@):R .eI~ڠ8dZRDI_cJAmgV1ը l f1^SH@QױG#ns5ԓhlV;judmOTDD]3~9Jڛpggtj&FkJ%^vUjJ]Y-=t 2;QpW>[B=TߥΡ}3e" 屭YS45{)BDSqOV] ~_zUك]!ca/`UO6=eSN5x5!M:n?/ϡ bK`L]m}j2n$j ЈLU:U Oc>xM-Y`w*Nϧנ=SƔ.pob>j~ 9y@O櫕zEyɿ]s*X׬am .L`XmlVkO>֬ RUuX9WPF{~4UY@A0;t#e:/6\xUѩ؈:Ci\h$ig+/ dPS}IꏖCq9S_^A>ZZ@q0pwT`7g+:|I 0y{-I+42:qCƊE7NUbWYaS<) f x(HUKYZd]\xm(sf/f *P){AA2YLR?)jP;>?rC6"5-VZk`2%ꏄ߅:#!ͼƦi(4ym:ƪ, InhgN񬧂C,)ܻfSe"{է: 9<[@,DWĐ$lyϳoDPo:4w8Ѱ)./:Hx3V9J{J[/A> <ڌ. IRG۟t}?rn&>y59RG?Q'3^`tCQFW΄ge;1INB9!%i J Gs9` |ͬ6vJ` =TKm SCVDki(Y/琋bpdbXT.wJ *qckm6Oz! S]uE "b7{Qf-T=I4mN1Uz=bNT]ѹ~̡/"DarPWZ3< MC,ky]#;;Ѐ}2ֲJyC^(l?Tjiev&qlȥ&VpFu~:R G?*ղtZO{sjj~-aKps~m#|?rf*?$a8JWUD q!: }dTxN(,o{ʪ3ŭT',U$HC5yc}DE: %ɞQ48vTFɜ*E'{ePWAfpʥFp0ҪAb;AViI0P"/slɯ;ʪ\YJ{ois9V[BXz]JσJ&4@2 e/J~w0.8M~>Gxjbk1c⪄QWA(ZUy{ds<$xIRv>#Y{ڒ ەJZPfcZڲG?czeea_a݆y`T8(U"E!"܃rcxCWU*3_o+_ٽ=UН$"IKl*"{3:v V9fKnU<+3 ZbXN\&Nؗ A-nЅ*>ǟkDHʴlR^5*H $XBbU¾O>&o0CPUn΃J`F67;in*b*$vRnshi`:>[zWb=osϳVMC qidV!Koʪ,&llڄ#FZ^m,*0zRōhک謻Jo!Vb<~9}='}[C)|wؤ$E{~s"lþP-_ó?tR}D50i֪@RYa'@ќEF2ӈ/=>aw~1eSC:e#Y6C#OKv +NVef\zSix\!dw%J}ƓSPǚŤɛ8dsGG$6/4/U<+3s׽*| ;\WsC KG(F%zAu6r&;yV5M %I#F J99!a+G'sȏp}jp0/k0jB||U8!.vj$0jܥ85f|w}}1`AX(ў[ᳺ#Q$LkPA[ v,e>xJX&xkfkgM ˘>2uҾQu]Y 2^^sCfs[5dzAGQѲ;qd쩷|oCzRn<`A~ʸ=PAnwuCK *aHQGR ^)jԛU1oAWg#a"+Md0Ks-Y`~xiSq7!E2Z`@$1x!x#7W|TٜZ ]υ}\Zl@UFͻHUnٔJ&Ÿ^a vIũj+Us{jRXXGX!Dw– Y0>\#%|,ջSV\mvW~!UU/0#iOݕ00<&Cݳ@Wt0ka}=Z@%:y8 bsV W y>S&ēxΘQ5uAGsh$jo:x'XiO4b>2n(mXL$S 8=ҿ>zU]V-0u2nIJ(KjZRƉHimxb 1|t|~Pp8[]ONn50SB6F')7ϝ1R!akns<Bi;bb?MS|Ż7k<٪̥GY i,m?Pj Ø5iAѸ\W@Ԙ]_f)Rd|N<&eٹC Fl%PQ2*>%Dg!g}.8MeDŽwtS`nËry z9Hf"itittK!A>Ϫ*0oX6_U N5iU짪qCb)Nmr$(0|A>Jx?Bնi-:THS nT?fMViun#HxS~0a+S%דvډrjuU{ی "><ȩ-c^Bs(/_^c%u( :rs(YŨY& OÁ!X`LuqPkeyaTtjۓ{?#B$ǖ" b)tO^CdV=$}N_! LΡ󑼽 H)L`\ ?Sbr5&! ’(ukaY1 q.dXf]6RͲ%_LcVd >upԙ*kCW@noNs_ sO##\βAdAYsȏ`֝e^WE}wGܩrAMwo:dzqea4k^8=9NvE5+PEHEגJσ|;)t?+h߻DBZ N}}r Ud &/r*:5C9LV]J *X!u?Q,l%fIMbuIJ{S`e#q΄#-u36 w cWչ6^~C%5 AS~NWkcaUJ֩3ƍT1RCFR}>ǃ2sٲ^~)uvlFt 9FYyO *Q8{nsXŤ4uum*~J8WwjjOEw "m|PųN[@oΝ{lswb2er`֥bqKW|ˣ6<l*Om>kv`S0ۢ<ZqEWS+݃SWd ff9󑇠{Zf4sܩ2x-lP_7DZ`*wXmV9);◤pCƺu 퉞o 5ñS`=PIP)%v\O;[l35J# \A*dm>HTs\,R=f鿸=5X/fY\ Hfo/09쪄ySo\ '7 nTڛU&7cYm@2h]7jGဃǣO=5X !cT_:؞ ^$P0s(T'f?zO7nTl<4ݲ+NQH 0d!ynW .-2T'pY2<6ΰ}oqefNc}9Y>Y=R gTZ ,>YjuW9T9i3KêAnȨzݸGx3 ݤ'Ej9JA(Al+^u ?5X[Zul҆J1ĕHse>NF\i#GHyz`}t_}{}^Q̡ƛAnA\Sta ^%یj 8CM"6-\F9GT` `0k~H)&#6!Dpr qx1ISO.Я[=`u>}g31butUWϡcU՞=8NDӨBT'wgE]t#TW&dW?:ëO i+L`?`1G۔;<=-_J|r1A,_C.*P9g?x`MV3l CoT?\/>lD0&P7; wӗAyV5FL1d.Ct㖔 $ _>0+{%|̂7uc#^UD^mtM+]jTuzk]C{9T &Vކ.=uAh'xz3\U'avtsUP^N[V9k9U[i*敥6W2҂;6rjBt 7\K :eVVhz<Q}HQN6.h$^Sh }9 J2AgɎf[;WiK FD43dUq*}7~Ns<$|n Ohԁj95F.U! мc ̥Z O>{( S!ɠ_],IJ2h-h`ө‷ ~CKS)u/| QsRv4|I_5J> eH.tϘ]]%__yC~$pQԍ2kwe@`bGcThx ! =4wwC_D7ݛz6>Ek۲fw1!kcK-\RTU_w/J9r$B[s$g-Y/ _>llrҗ-qCm7]QGLRص΃VYR`ip x&2?"XU] dI 7y]>#N VrS8#AE0 @g9脎 WMrC6"{'tEOjVOx<➰Q5?Yg~M ^|C0@e X % R@JXl/RXL}H&s<(5Kⱦc= ت2~إIvQ/)Зfic}ȲfiPoS*;rj &cg4L%7}K-vڬ6r $?d5%JkΪSq~~!;IJ ,Jxw}Vjq5Xz~8V 85X>0ZU?ԝ.dl27 J*59}M}y"9\{S +X`Sxaݥ`&֨/xΡ/h1ZJWۧ;5X[ꦦ-sbM'aGZ2V-0K%!y}u!TqK+7a | |BR:d{◙wk]$zJ8@%SN ڗx4tm{=%+׳xZ:P|K njyjܩ%#ϊgƇd_ b)^.$; ^:qC{eW.B:w_xUړ)R84讧uW;]חAR*$<,'-25պ`K{g_9Uz=u  |,vw6y\hg?䓘 R5:#$nک6o,^΃|T;;Ա *g#2RZb=﮹ϡ+ԕ8TYh|3QĭҜ܀kVCL$~]TJȩo|?ͼھVYRkgc[ϳ]uNM)Mtj9%J|h? ZvJ[P~קKe:3uWP/غl%Ԅ/r*=!vFAm>V-|쏱,LJ6b,t7 eL _}cpNGENn.4Q@3Ғ vx8rc;GlggF2% g XWEpCvwjBP%̢סxMx2ko,MRA>ϪRtt` Yɂ)y|[,!})9,q؉TrrTݩ2y6rBUe.% 9H )-mẊT]σJ^$lĜ"Ҩ*FSvdw~91aSWTu;(`IỲܧkHv'V=*l?(:F(wvSݬB׍:b`n"H^yjV)pmk1!Z$=k#RكV #5XZ#UGٍplRh}=u?hZXZRqyuJ^hd gjb;̻!cE2*_`v_RgIO<+Oo eA6'T T;D;@]^c 4SyIG&4ě΃ n4ج& ¾UңY nshid;Yq]z G~`E5*la, ]e/Tǿ(*:bM .,mqS,}xi9+mOKziPb])p5NGZXhĵ7\ :3pA';e/rn@`OR i8|$GA#uwCUnxoz4S5*G΃|$'noRt^$EX &p] = ϡGDԍ4%wSeڏ=m2}<@Φ6%<ҙnjK$΃|Ŷ-k"]1TӒg-yi3ዬraԔޱGǟ,R`:H҉hqO{?ou|sC2跪?JһSB9Å?BhSPg  `?Su%Jⴡ*֍]˪x}N?Q&u*mIhQOtj\]e] ?S6&` |/mshiݲ 1\tԃ%Т֥Y-JlÀudmVJIիa짇vQE1lߪ gbT.?0I\S+NAO% ]y\W#jݔ"ڛbЉSŠ[ `VuKna]^ xbjfܜ%ץS;O %7_QkӨ)_3kٴ2s<6"Yڀנ+5`=l`qmZF.\2L)Nl6@ *0 l^Rn+a%a*YS %\D N_}yVe*D`E_M5.0:5X|XWE:d 9KU( fU=EnVNK݈@ XO ./һQSBmĥ#AO;u :yr琱TcRqo)JťrJF+l[L"70&o'T<6SO4uaVxbkՉhj@x>5XJ`;3 VexJ0'E:v/f!o(\xQXdNR| Ol]T)H8sh^7<1r{ Iew4`h:?CC9xW*OemӞ;{CtHkUN~ZwͩnꦴTU $\ur%M@f$t[s,Gb+=>wz`e%N_e (VaP}\jP2#I9rU-H* !~6yV1Ha903vc1 .-1Iu:NT8V=L 5qX>ުjCիg<?`UI^toIe#i |/v b+}E9dʟkO:¿:895X83ed3 ])vzЇ&g$hI&C%b\sKHɞ Uiue);}Xsꌞ,$FƐjƸ=5XN<[FU` 5L_C7T`Yj <;5o,նPѿj!As@No!?J~ڶ+-=`az $,џb`]1"8ZPϪIS#ZԸUP|5R~|Xs<nЗ#Z$Eh5q!VwIjؽ8C ZIWU̯r  ' .}9kڇ۽H9GɟE_Lc(FCSJkF}CPbvg?'P. gdT\+:JdVUaΧ`ЧgUlVcxAbzζLy-߆>+MO&ڹkS[mfX$X. xk6J.wN SSXO x!^SjTq*5z6ԮC. 9 9IӅ[]#kyl`nu8QA6*x5PY\x4 AB[4g=dU.޸7;VmFAHpթnsȡI LL C[ɐf=5X K3Z|a(،miɭZYsHHtN* =yV%ս܋[HS'$wC[?Ӫs\R 집јY}Gm0̪j4Hv:0jٛ+)P%D g %$SKu3 GZq\h(\P3-I(ѾVw`8kmHRdcA%.H&/g[3+BiN7@]9)@79qR1u;f$fnsh.LO6u⼁#/`>MNR(rZ A}HY2Un7`R9:5Xىb udfa HIȩ"}}m_xr;bSB8X ڳ+^[/ 9󑤶j s}0%#Y@ij9D.x "eO]Uʠ%gU+Gns4~Π`<"Xsџ,gCWgpp+՗=SVu.>Ǔ'/O'4(~G+XY˫vG#!ِх h\9G>*!*g"'j,~Œq?ư 6G2X4lIW59N~:2[Iyj7_C<#M,59!GZN CϸT3̲4aqshJSME|Tqû ۇht{J\ O!&]Z>/e$sؓ]=V4RN,H^^ҬV#ҡIϽ~ shBxru5Cr*c:rY Tz%& [shiPz=94 e],do?ΐЮκsʥPwis`!(iz>%{ȩ/)(H])6U/NT[wAdvܜAsPn5>XoaubO>PzS$F"f}"XېPts8'F*#x.:i۴1<_B}8鬔00ƔNYem9, (O%r\`R rbXC*sX#0B8U[g.}? $waMK -]EMP)u'%@y5~ړȑ*SHw|tĩ[b ]< Q{-GAPb R,_}a:y$4K9t`Mp3&ZzVV-ijդ)ז!y T~uYS !)%/E#8#c/gvgȑվNЭg\jX۾'7Л4ʂ1z)n}>2^Jj KJ|bσ܀@ P1sOj$қB٠Ѓx5F,M$)`h9}|_3@aê]B><޿Wz%ЧϿ(u'\&A pU 2N8#9ja\}m}WfcR2ZTւJY=^I_ /Ue7VS“V8fJx.|ʷXg#^E&5q,TΟf4|-N l0dQZHQ*eїT|eA$]}ɻ嫤%x!}!E;`u_> fk[f2&K I?*GOzq7 ?uYO࢕kS'K?-E-(_CSp骔rTJ8.V̥ެ#rQ%5jY7.8!~~]onIfv0M:v*WoڦP`:n@/ r&NGw8kw6Y I9(O8*  <|2r꤮+G^i 5m4M yN !r_V;-)érQUhS/6YQv#@(}E$hΠޫoXKJGb?"@^AS@ [nylIXO IMr6H.F'ؕE[ ;=PlLWTQr' x9@m'&D)SAM˜wݾbB?Z,?B€k :Zh::+ 2wO(^(t읎VS…Dԩ]^9L’""hq?O>qBTjRYobHp8~$g$ϺB{c!C TS\Tq\4hIf^m S+H#~)eP ?ea 鸦JF2(. i!Z~w)^w}28.*+s<lqGCնVBD5N\ وbJz> >Jr+2,?&2K[]( xme&O90d)$VUr)8oD24@o?6NK1ԆЭ di8* #(<&Sn]][5h˷]GF;m(Qǃ.K.o]t_}J;( `5J H₎ ?Ϊm4_$ O]w,;4$vS* ޻ u@{99pè&jlGq Bupac>ҥW^/w" U'O4ϙ⩍;Egtc켳caXTE&Uu/?ҋSh9A2! ߦDY%;1KR0n/TlsRazO SyFLXNL3r*RWN.`Aɂx@}mtA|S"Wh{kuRJ 4lYzRFx\?t7QCu ~i!x7[zQnSO)W0^2;ӱzpt[`;Ϊ> &7cYeO>Aa+d z > sfiAI9z:8痗Bp!&J4qhV5[u"ɛi}JPE"**MҤ먛 Ie %vHB"c5ޣ|`3_xdS&%" AM ƯU}%ҕdSƄgv:Dpbk:4Q{&]OSCXZ-)Bx0\ B"v (k*w37#wy[Ģ':`D5J9 zH\%iAMieNcHE8b:yf:1C~?J [:/%[|{v^g5xrJBR`ѹ*TBSOwy`5.dV\D6+ئ<vjC,iDβ?XO\~|$;Q-w'{T~ ،A3ȏwڼ6)KK/1*'*:H{ݧTDu8ĭuxt/ NϩʵkWK+"VV4 iS`ϙާ9T샒<ĺ/mUo/>ݻ{e)։gj"եa-7 +Ll= _unu\xꆹ?,dt>?q0]a&μ~>˨ť4PGy p ;h*:ނUt5*SyTTIuJDzbٱ2'Lpd/ɇN!hfZLہܵ `}a@w(H딲{ՎE0Ȭgg68@x uL}p-lF%:tITt}^w- _כ)S04GU`beH;>{#.]uir7<_ "|W x1.ʩS\A]0bdAļqM 9 ㍔P, k ! UXm&>cI`"]Ʀ5;݋NIU[e0ocg9-oW#; Fb>]}O*3 w3Y8wj"bCK_U 繾OKL7;L.wlN($r &E06f4˅4 ${/K"qHp8b2GOCn^ 8={%q8RÃ.!T֢8`<$Q@(ĩ튏aPCzsijHkf׻Ƚ Uq&~mm(jSTVʊ5^= >]Ze-&^~_.\ֿ{SDo̱S,~ /+t a繾d|Œzx~ۊ \ CL?GTo> a+1]yՠr9 ;o,y;zK6v!i^"AdcBs}j "%;]Wq%7-f/W\To9oqU/jr6c%Õu%C" F($4ܘNu軣 I7,Cs _mgerGCPTb51Z/ ➄qP*z%*&u p9 A!5Aop1fHDb#vZ)):Vw^sxH 8;u˵ڡ]"Hái<7=(TGzq);S9bdJDo^ /z S?h v t)*Xlv`%fѥ\xu a}_oc*B6urɓvPfEN=``5gmdF3{?Zƈ=ҟhƷs*I#a|Cl)Jfc"vEZ/O^#RF\\?uFcQl{ʈ`-ot}k邐g8>OiA06$^_yө0K b bw"\&X \By\^ "s2Qf j_ݐ%y_ --LSz7Fʾ`&ЩiW{O2DE/f0Q o\o1QkH &|(%tRFw"nGv}b[N߷hWY}Y,z pS^ XϽqt*)1%k1& @nt/yc}RpDo{ōPl{jē3Rqw618&:zݾ|k;4z\H[~]kLK^b縭 @w% 8@Ib*F}W,x9K򾄀vꬵ@Nֺ S<*l)V [-by#ha%CہCXNHzk?Τ>;TZ6?N.&4G/$WO7:5t%)G;o$^$/QgaB+ƼqΘR MoUM]^E"Rg.}~AAJ3[&%NZ9b̢dUPXI$%FN*nZ)%60`ĺh7p8`9K‡Rh2RhI)>;Ų4#zTDٍAFpcbO:y/$!a7?ށTԉXHQPOQ Pghی۩hk3LviƉ%i %uㆫ~|*}z>LS1 Jͧ/l{su Ƒ\x(g}/wDHM_T~:ix+5DsV̵p4NptҁSz%\cQH:FE>;&EKc G0m1L% 7 TJL@|%y.h`ގCsWDL%k*ʽ#`D73C %Vފ\KmT7Yx+J9zqo1j/S+p.UpFCaJqֈdb* ÷$OQ9:# ](1qKƮzЯX(<~SHX׍(~>wdn$";pB} j3}Q!zK8}׭|[!:]|%%H^Kʈj0zuL;[ 0lTR. TvH6ӦԘvc~.I5}EJH)Yo߹XD:rhpהZ3eąh/CL޾%Ctb&\Zru7}0vWzFWt.ZTՇglKtm[PlH',w IsA43rؽk("NG~Fіcmym 6[^d$ T:fk7⬥)C993C?jc!=@y|Ip@m\x3뚨#Q0}*Iy%c(+. U7 `+AWuOGTگ.|KIԙwI'P/7Do]74mZ \[؝# ?L`a=zuU쥮Ѽ+[WS$?11..G!+\>df7^H9}>mˬ(4[S b h(_ ''czU36Џ=mȍ6mF"B]x"KEDgs k&^h&N8.Q:G) C[ln#\IH25>Øc#H4/:]Wip(ohY_$( b}wLsrY|;`= ܛ{Gm։ۈͧ\2k vV]bITdڑצ5y0PfhD,8-35'ڈ_@ 01 VЎPe,"D.>&{,hEl VP 3`oOqru!'ZrfRP4K\fp\S6>syH(M}.eK&흶 ۯ2(ˌwdc34Gwdg{ ԃݴM\/>Xݧ{CAU1_Ƌ::QH<{MH{v HIAHypqmL\&OH^1 5ʙR6rhC<8{M s`cb^+;p&9Ҡ<{m9nd0gU+&;8&I/̂itD>n-ݔt'nc/* 3HṊ{̝#Gd[\=95!ᥴ'jD}7WkkS>SFPg VB"UGpNX:W0σ} ?-/`<%ho6\?iAGl;Y W ']FsǨ.>$\4ks3Nk0@;t+Ct*_LC-R^\I{]AGhf,/Jz ÷UrSQ9xM T4 A`hfQ!S핅/%ݱ[Y_*cX XWHltp#ۭu uy^rK)qa'u8Fk9hJ똒]jK?ET3) KGNBQ\@{Цǰf1ߑ׉Bqs:B >3E"M#@6SÅQ|OJ[K]E w''S}DK_Ǩ^qʈ֠Ȥ31bL Y(כ>քq}mQ2Jކx{'q2qI Q8NXZIˠY}͍C>ׄM\'oW#| HӦO0ա<­ʢUɻ@\߫5)C) P\jRv nfXl Wl`X>v"tL(ZN"{leZE~aZcgS jZh;bTieĭCZN b F}SF¸)Ó+d\gDv2 =v=Yd9`D(Ŝ;ùsV;AŽŗoM;.QpJ<^Lۮ^A-k`ŋVdhQ8ܑ\d]EEt wD&(9r"c`kwa&S1P{vLnlyuc)ӓ%P}"v!ؚ ooE:qSx+oN~fߙ#{r :N D 2j;"S?%)<{`í:^,‘ `eNwhru'ZTro;ʗp°bY?&0ifU\O E&SR\jhpVXSRM0*Cl 3*yD 1B3)?$¯RĶt6|\ }rm6A7KTV'u H8)WjP:Β۷5ɕEfR |mZG"ݫUQ_nˊNgq@ Bf21sk8g.ԃMt:]G/ %>]8jWT"M9 %+B-(TeW~d)#phq,BpWTƴ'xD +bCmkRґzi/\DvdEln{s1-\!X&DqXA%2bBQ)q㧜y|2Qhw暊A#F;k:G*jԄcJHR^)tRN);~FԦLaU,)$Ue +'.o-ۀ;>+;`w\ G+ʹ$_y.LڤWCMATW{M=X>q:х&•cy)־ҙ_SQW{:2\P^ݖ5]^%CE<Ȉ}/rtugC(3W`ù!ɩV$_\q,2MRl]| іI8+9YX@֧mxcb=35YH4l>RmCJ}Z=t9׳v( K>؍ ERbvh nu!:Pe$4h iRkk[(b=N7EZF؟k*Ma:+V(H uDɕ~h/r{r%'?^i71Y9oƎzqv׋䱊rY\h  32wkA~otJn.v2`rqYLd탶&@qztQE8C6vt@{qR$a&$m+!β'G?VesLrۼ2nWnԅBtT{L|wWFQǬ[;J(kd9/7G ogt=xzREdpM֡c[*`pB֙%=k.h=ۛn.zt c]Ō3zRW Oe=zoQsM!:9"$0].?J K Fb+V̌(37%y]|z::[Igd E[Tw9H_ք% ;$83 <]{v@D3VLJK.13"} a8!|EpPV: x.<^D~$1hh1ZR7Zm8aTgIPZЋVS>wy򎈑^Fz/dIGYz{MX{ЦR08ZH*O"y F:Kvm|EA,i C=&2z 쳐Dr %v+Sbou&gS$0.} ~wlE;xp9߾5P&v%' AY`QCIeq.3DN9]禸,*Ҥ)[OGIvC_2&V~Ps'tIn~}wn{ zI[ kqFq8B5`35'2M?`k`#^en1L#`oHZ!8-Cւ Ab"yA{R⌀x!V/}\=f80W^f 7ߩ=z03HK>mͭ5R1=VVXnJf|IW>CNR'^7sMsQG"DFljH&uIJ4J"Gb&HGVk>([lkӐ-~;_) aDGzu^C[j̪dWmW vb\O-OuBƂVN?D/b -˺..*oِax- D[pY|/m&}JW[82l6E/(,D) M4;&v =`YȱJI\啟k*FyEKأsUG(@ {SB%t|(ތ;ë.(є zG ;62ȑ"W>u@D=E/Z»,9s+Qz<"a:WH7Q(c8BZ\atd!7N*hdkr*Kmj<}~xBevrZ:(3)-73!S}/ >$C A_8*.:S vz;xVF22\ޖ&Ӊ^,3>c>Rzك-p&mXbUkLjGt˯.3?rٕ(iSZ1$NRY\SVɈk&{LL l q.4|k4`ݝί7*6XhOd(R􆊶~ZAdHAGpH|=k.gĤ+P -ku o)']T6J^)%f{!KB+?{S@H?nP[:(;Ë0*ʽ̰J/+D|DB)eSίD~z.&Hq{.{cL8=T8[/H~r}VH01ϩ^p UPxءc_rv{{(;/zw`WGr쀷3;υu.>*Z#.׸E=,vo@< ՛HoبAǼXaBquW{MJ ނ2Ч5^ڐݵrw#(;ѻ+I!q ֠RVbebqx<;(ިLC1^w;u4GJ('GC< l~|$qAutHHqA!>"~1*b>@[[cU|\7W` qmVZA {#bc\ b6ݺ6CWE&#%L$;]Ģ]kO7TFLP2|AF~N8NG)ڈ,P5 > `sAq5cQLhя\cw7gzPtL(-!pw.r|IU^pA&&e @x" N67vgx23=.<{븒 v|1c›Z ڿBk`ȎFT1//l(j-*@ #l%a<-Ky'dCEzz0E؝^SV b"cu};+䬘XQASH-$4R+"BALm^S&z,hf n3G&*boo6VVpqfn4ؖ/>T.fۅݙJBIG`9a{4GB+TpeZ$[σ}IJ}찤ʿ݃!i@@w7ѻZvc}Q0݄0!PiѼ{MHJ<cD> +yO5:Aq(3]ܔNԨN;&)PL XBmCi;m[ cB8`Z2=/dj+w:*+p:ǿɩTz^g6j5."gTC1A'm/utu HI֠yB:s8qW`@{co EZVY,Uj s[T-ci~7\|y>pS Rd`/ 1 x nC5=Ew" 1z}ԃ12E+S7x {o=F *b5"ևC[шr̕rԃѲᰜ{ ĻH D\/pgPD^tM!jch<΃}4dpsٛ[rw qS 6yΫfhjrMAS˻ԃrmDvu|Ihmp*&O6z?gI5IIy`ާ"omA#uC@w|DD"̮ bݠ"f&b+%Td: ^6ͷsM>SQب t61 ϧ\7^B2c#1 /S)u(0=Ss.ģK,EN6Ӭ(~I@; 4-G .bwgxy=Nj-Iǻ-Dsţ(dk%Tp0l\O^89Cm\f#oOGZfF}4A=UOB "e!&T>4\/Y5!A (7)u:%?Nz=(,+{ bۖ*klo{M@fY8oۼe #^mt#\g=}4,}"&5c X9e}d6p:-mMyT'A/jzQŁdeZ C5 V '&6F̻:W o6F] hg}Kz&xBƵ|1꓿5pB1T]tL~_h} PEe\VEVAA]4Z>m*!q]|3o70q10f2)F?Lᗒ /z IDZ` 89I*aI^oPA+V[QZO:S#x¡P/P3ʃSW.b1OURm\+/&hv vfޔc"/>=:֊pE/u;ePCHC=o=pmKjeel5aI'$qI 7Z>n qJڹ >)ك/C|x-sO-C}IE 5 rM*::>;3J aUABc "6 W|{Mg:2nވC۩ X) ӗq8PO+`$@oZK/G_oߤ4*Ӡh%#wwF&:C"{]Tw**+cwҶc}&X2mg˚$:앞GAI_.? R>ȍо^PD3i|F\~sMޘf0ACU.E#ʷ^̾7~Zj孟D=NyJY͕'}Idt{^ ͉`vV{~x苡bgiJf1ZQ횞O&)ifSЋ_sQ r؝ti-FJB{ 3+6BNEu(E'nؑ?)sM3 6  "V`oYʩ69.4K(Vl'WarHf &^~b2- ']Y{>E ]oǑ%  -n+;M Ɇ+T{PjЯ,̀m%_&lCG@Xs9;TŕY )NXk?loHjǚ$wb wc]~~E'7}yŖ: %"]O P>*f_;:֋frY _m,{j*H4(1hf@o({{S2:xgh[ W"_X|l.K.ѾwR*cGiGkj M77x(|RPcN—6ǰ۳" Ϧ|N ]}W{MCي_Q1OxEE+ /V##FeU8 8Xm ޹G N4E-7}yx=q9π-As~o 8( b@799{~@mY8+zp-Cɽ{M=vn1=/+:F:^;ë  V>zAa1.jrg X~fNs]1ssAwB.h\G"'F wrl Mu\k!#O]̩{ĪWnU{#?Ô:ʽ9֥`7R^i7mf_qm15O@fwQ뵎t_\!j8(t-+"9 r \Zn/\ed3)i(+Bvٵ6ww3SH^Ili-!?cTmP(mDߴ?(f1<֯PLMv$3&:u{ k͂9(*U@ۨӂP5u%1ƒhwtw%z۝gP6cF l&N!T v**4Ti{8=osM,uZҿE~=ӊ 9iV:ʩ?\%c~0q$[?ԃ Ubڃ xboqŐݝfh6T٧EF$7h_K5`<+:3M_ah>0DV 6~ѫPN7zU5=t=py6D٩qDXag%?CIfn()uszUۊh.e=\}kϖ9䥿>3>$p wwFȶapZ\Y F?^9L:|zٙg jWLz{?F/R>Us3hS02aA@_}57ת)UBC8Ewwy.UX=!wJؑ.&/ق 6SFu=k햮mJ("Kw"YB1-kNKi0h6ѺG.Bw(m#HF/ڀW}[Y>2~R[[}=6"fV &{lDHXs)Lf#1 wͼGIߓW}-iQzZ[ ^3)*5y0nܨ.t\Mׯ!o>q-brS^9,:Z+^ՍS~ |^מQzA>^};[P9\GҪRJ_ C9(|(b7]| O}D}PeQ!Uww7&=bcw 8w0ORy)BW~yNFwUlu3ҚjBg|DÊL!,P ]ObLT~I+P 'c -Znw^g:eb՗ax xڈF;(I3y2e{]T+ҥ%#4jj_L?>J@5wwbtoTm7FQ&zUhv:;V\e vŐݝᵫ$ۮ 6&q)t;\H?{MlQ2 s2k -^7WI)uu2Mh2\~gv1.BT*l+‘|Nֻ;ˌb%#$Ԗ #a"ci(]AHhokSRsEm헀ۍw,Ĉl`9JJfS 1l %xݬT<'}y#% V$G(.{[zr1m|RRJL4\ѷC/EG+3͡zP+R( W>lu>Ml;j~ݴ+`u3;P^̿fS4kW'>8E;\Gz0UqTI76O^8Ƽ=U%p5P~wSnh% f=7EY*v\3=#^2TA_hyQ"8,a^/|pBEw4EIń]dudDoHYӹ0e?:[!V$urOs`o_ Z+osqW .fhEyck+.ϬV Ʊ;û̲fAic%ڰ/( kR@r,,?B*8;wEwѦ'w <3nFT—W${Md0BįGN}= o«b D'%Pr} %* 1osoQsM6DPLz1 Lso`o/<89m>"z+d ̬Dc*j&kGkǎ)I @`MYI ٙ%4P1IC]>sMX8]XhjXwP Tzxͧ*-06kJsE/F;wVZ▘*#-q,y5czHSYGL8]12-= e1ZƐn=lq((k&yHN2* Cm~bn(nMTԷ4xPSHaIgrXH_Y͏bBm)jwQ`7/@~@ƠcMpp|+}~xU[ȿPיoǝ3^)&(];- :1]#ݭ 2"A u-P׀] K^ST*Lw-ޑgx'e1<.@CzLJ8-_1{{+k01p@k&>:$K%|Tc%gLXHU\&>OTqXtv(EQ 3FgKuQ٢?vgwE\Ctׄe.6W=2Xhg /3[h4DyfЫS Y9uX/()^OhZA@GUܷQT=.σ]/(V;X*4L4/DĂ6$2zsד{MEac -X2b$OFxQV1&7 H6(=%AX-gN!˒>פDPf&? )"΅=^C;&b8\$ @O EJ"!FHU^ ~.Z%Β(v8Ty5N^4f T)}$6핌!dp7DuhÎ]M5Id~ֱآc 2mh<F~c5L-:)^\h ( oϩ^OMNt`j dJyrHeb N*գUzen̊. onAS~Iwwˉ\+h2z./銃WgRx=;+P% u:}ShH\"/Ĥ>l@Ek22KG;<)W,D@1pɮXnW *j) @=sM,q۸41Dlv8).3hEL|'31Ő_G?]+ΥLwJs͓@ڗ}+x)6vaj"JhUk0Cv;zs:F|네b7{coWA !QZ XA" RVD4L{*$cǧ3#cTstlᓻF~\zIi=́Yq 38}qV){41z$WAF]\ p(ÍSs(pRä40^bů5][hI)$4\XؿSy:1˴v !QRɞ*H ]t}2Wś;'W~+XW~v[)6ܹű7 и!" 5Dj CV z|h>gиWsMRRaj*3JT^6",LCY ?k#voP5ٻRqPF){M>e)ƮSB֐.(+`oFz=Z=Y'RWRu֧raObt n[ کxI!`W{+wwL9U7qCqf76;Ϭ/ xJIX mA鞣`7>ؽHG4pe@c>IOA呹Z<-wcיIls6M*3jyRY `-HQYMn,XLg{qJ@"/^ XQK(J+ƬmM;ˤ}`b>%KJi1[%Sp's0%ҋ`քnkyiyGο=v1lD,/AԼ?\b/#Š ":&ռ7#k{J\B -Js"/ݡnJ3x  b M9u u-rI?4} PSnOB ɋӕ"b ތh9ݔ%:H6Szc :ޟp&%%Х]d,4A#ZnGP nS ՊE3RzzK ?kǰ_݂R;*6) ߪχR 3 MSl×OHyEBB֦ccdT~I¤(@G.C@4RVq:ut[qKS9d處\Q5A+֜b+W^| "X[<ImOoV9-a{A_+5D-dbLљᡘ:jouwQ`\:Ḧ?*29 t$3RM!Sz$eI ;KH({?GELilb(EB4ք9ĎXEώL%`qkwfԟf`(6)CjiD@XaT)(|{d  0Ooh-nRQT\+=o{MXTtvӘ\G2twÿ^#\& ]@)}:p3[' Nk^$q1)ԗKFEk:Qك$R<ޏ.䁱pdĿW=IyŝyU9σ_hEP1T1H3> SNnU 㯣DWxТNjC}ɩlb]mT [Kx oJM+A vT7iz\eOS&o ͱ)NO~* 7%^!|*Ԃat<(Ei xdx٢Ww Ԙ`ׄ%iG&) yP r 4Fsh^ȱXtz`.S:)h[T3MDw2*!3wQ4I%mluD5*MGSp%!7a)opGQh׾p/ygXvڦCɏdsj5ce_5)'gðHj Nw`vU`jm nJg 4GQK^c)1L !.M*;;J cQ 6,/|)ĂI]f4E3';޿Uk#%Q3UO˔_.L3;8+{\ 14o܄^J5@QWtnLn%`kVw&F='5 ZX G%L,PcwkM>`$bN2iT;@pVkL9Y)]fQXj)=l.05 "p0FD  2@p؝U*\/XEb2͏zO0֓&[\=&Fl7f>:U A8͝<%zVMKj}IU$R6 XYfYHAi /)+:"#ѓ Jp3ļ P[^7&0Z)Vwu (.5ǔj=x +(/ rx#i(@ 4D3hE\2;Y&e(luJi^ur*(/,DQqdg& K'lCDl3()=e5Лsy#MVHc"H;J>~&SR?qÜz-$6zBE֫t&L&Q ]^ fx! "̥2qhI3`^(i@y>eN90pZ~P63xy Ozmb"U-X(tbrkMxgiFL@"ჩ67sW%biL4cģ|e-k`6' kRT! m\u6+FoZ3ekX*~㡣0aBRe)=<0AkRcT^Q =F`+y/!PcuIO;Z]BN+ZS~ {ƟB[p9˯>vgx1@} }$x{GnD[^cgMB,bhX`.;ËAM^E_N'n: :VȻtmh Cr;g8eM…u(Ÿv5b;Ë2 j&,t9}hUY qd_p`PZ4Tkf PKQ$=/ ecb_e_m.txtK6Kv?zdl"-AK֤A 6m4d23Dc&|3#^+bw߮_AnoO2F_w??ӿ/?Ew_o?/?˿/_O_quE<??4 n 3[هh^qߗywόȴ wf mֺjrwO2˫o,{ﯽȴ-iV1r6K66XSNjy6^_ǸS{I]l&,)NiySLm꼻gP[j3}D1Jgˤ2ݞihJ wJ+fo9k,uG #~:"Ӧwֵ3fG39k.%w67ek}ŹFŽGd]>ʊɖUƧ oF=l_{is!Tc}Duv>䛫~6>}z-ﴬd>r9dbϴXk>ZKY]vN[i];2b+Vִ4%%uQֆlض5 -ݶ0y)&a.RR \ُV;}Hc`'{֌Ŷb,ol`jmj{ղ:$_˦vS}6 xW`P2d}wCyvC>V@> CyTR5mvn[1zk`On{v- TUܾ._Y?{*O ck&%xj},~x`]ζf]yVg3z>˪fj= i?*5 c #j iMF)h. fAؓom]G꓋hEaV^l^&:6Q߁9+C`mŖƥF-z ɼhKݯ0C_ׁھxo? ]@k7pe/N ckbh ?Uc؝Ǝɍ sW_t{^~sRך/§/n8B<7W{ΛW6{Cĵ0'\o]չ"|ë ߬t ϛH? m lXrk9W]Eَf-mӆ7>mmZ>$?+qfl܇W M`bW<1.2m]>$v"Iu5@E a>eixXKݻ7dم7W`$R9)lyC 7L%(f!V- GwQ[CL9T2X\;qg8VfM9"Aد}DD )3Էnߺ^9(oQhgm@ԧqCBj/Rl{ ɳ 8f.P (&|!WvRHĖZ!y^JGvڳŦZZ ֓&ZW0&($3|xUPc;9 J-w]]͝@\^m7(K*tf2jϼ!8d` |m{*{@8qV0˻w݇^YaC|M2cBR7~:4]df^]zokl? Q{@sNWown2P3 2Y4J&lDx Y`/5ԅ͋@OfvߵBt{jkğ.c'p㋃!=JLFJ/;{H[D8B`YK&#Cj2p@'}yPD#~Cѐ\akc{L,km4PX~G m;5;ړ/ ?G!w"f$P(`Oj${}":\~bC>*yeu~!{^މWo-`3G!<-d^:c~X[> ( kmf(sT:Hd+1e.-Q8ë3ړ҄49 .v~z:s7QG 65"$^ǟW>}qzl:W!VǺ4Z"&xpWto|dݔC>xe`=Y2?]?r}9p!V> _ !"Y4"5}<'+u:B8/}7CjJK+ ߼?(~x5=|h:q ^̐1zzɼ+)#_<0*a xǟWc!8 j4k}QfHߕXE)z >ͷW,#gg(MNs[k}tR׷8G|637^uDWbp2}x>^z7 Zg@+;.u,¶ш;w_\H^p #rZW97C_ȈHR#xҌĘӇWs*iaG!5o&igC`a5y^F|ۉHxCEB0}; w` r-7҇Wms@Vz:t <Տu2\A|2}xKS#1M:^sR txlEx5;GdȆ?J^ղ 5YoY|W~}Hd@&'kv>CR"?7C0(QvA|%ݽ@2R ʆlz>$Rŭ]'7o6&)XCʩ.k=އ?f50L֭`+AJ=P/dWBT: !!)d[Ŭ_k\POuHV詳\`'鞚·?P|8*k@碁];߇T<*v`SHE.1w?j,I.ېg$}|`u~>"ҀË"ïj,#Elbo܇Ժ!0tijU(hMtp +D]]!YԵ8(~dd4dx] G _vKtrL) ʳEWZT^m@W~uCr\u7 0T«B@$ф:s0U9-==]Ż܈Д{/^߰;{x&V#TxTiտ[ ZL0.ce$˶^qYώ=ـo !ښ"}$snV>;Og&Jdhamw}vn<'I%ӑԷ;%0ٻnWIːG$D怃!:>n$[zvnz[ *߇>Jy{(l*K%7t#\>9!%#d 0m]`^Wvêo.+~nz,XОv֕W!sVZ5v]Xgs?#42V,x1|އ|ֳj`ƶǷW!}&1U2 Xv[Ϸ!ղ˖֪P&r<+Ӡ7zƯ"U݌V߸pRߗ<Q?$P}DQZ"Nn%Vwnvyy1q z@Ӈ9ows {Vol|{rRZvt:Oqf W#ʖWyP̅uR/B.cFGë.0dB`q{~m̼]!X^8Ql='[V'/Ϲɼl +lV?\yb$~Cc bu~}'` Ӳ{It;{J)k-J dY8{Rx&{ jhc`BJ߹J*B,Kcuۂ ZW{zHc( m?_Ih 6S _HUT g&R&V?[jZG%~=Q\Lw ,Or5'e#t%Ʌ-PyyRh |YqX/VL|A<."hՑ\:rhgڂ8boAﵮB0Mg_ztH`L-ۘU oQX7e۽?⏰R8Sn(SZry>T0 cOw7AL|ݟ{ur!3f7wi&#/\:淸JX2zv|t]1]]iPnŽǛ_|G#a`hg(pq"ey~ ʎK h |UQEҭB~\y[}'픜&?яӏ;dTD7VR$a"}LA&*qo܊D손egVc`Jʗ <#5@cJ G_uRnUyaM`ɆZ~9'}JSh8҈Ue9t\nUd^ ,3\",<(CۘugxOYc kZݏ  ?R"HAu'~ʟc倠 ]'Yv$ !4s=jO{{wh^767Ձs9^ Ξœ3^[VV Cy}L߆u6j$GXgh z( .n0*.S)JDR1cmS3w挓h)F{Ԅa0qRKOZ:TϞ'#EHp[@y|g1$)SMʏ}y,HIo^um^'"csu)kQ N=Y^v ĭeyu-2*m}}Jpg/1湝'=gpy8ήj<ʙu!SbU"v*hr/|JC@lj;/:]dbVifݑ/^xi?bol°tD#61Ź:++>'*Y>>A#y[$_Z$ɫr&Mnc3( 6 U#CU7?I8ά};}LAlXݶcnOFyrG@'qK]_yS+":Wr=Z.~YMײ"s%du sı=l!ۄ?#SQg(3}L!r6(dUV|Gٱr1au(Nh+Vvz/r]|bOؔPTV:w襎+;ŗT*@{T6dO:IVg,:{N .Ġ(N^= ht24h pNKš|8p]Xշh/Ȧȼ@W1*٣te/^a33ˀ|C3TE#͹o~dWDXżrD08WVXz>uof͊Ysrc8j@ ͟U|ʓO*5|`\ӊ_r}Lb~=L`iDSt:ddKIC0{S=_)uL7z6wxAeb~C[&{2]yaÌ{WQ @#+F@&fQŘ2CNJ*S#]ʗ_r\~.徘V40$W[dSYX+ `WwSlȎX<4%U aYZ~iG@w|J1E\[6EԮ) g  " dT:cWÛ 0 >>T.Jjjc>X]*H"6C=;8ش|km월n|X}S2$7/7Jo?:o"ё sZ\Y]ThZYVk_5x:ad68^W TQEKo%Azˇޞ|x+ uP~uq}LM@ @`%6$ww_ S$aTw9~:WsBv7/C/?jo;Ka3#Jr>1T\:{:_)04IBZTrS!zU2=1h+Z[=bijD.؈v2O &-mL2,Th+A=>}^I7kG()߻|G{\ܵCQwjhKy!p9T\ʝ7bϧ?3&(á<— 6;śbVn9 .\>/.+ F$JN=y{r()V2.՗\Tr0mTV)yML:$ƣ\*H%VG!/>V*P[N ۓ2/7\J@()РP`,b_|S 1\"|cFCd+:(l^nkpfGTOI|q-N@,bqz:P NL!٨3$f 4L)_<)I: w%RXq'9^Uh$0P1w0m`db_lܳr!cpdOv<8A ċkes#:'wb HO*?kUwxSn\O$! V/>&AFɝ%J$A.;|97iLrq6֛V}Lje,tO~(a*C7(|4Ue"MZn7F^0#դ uy#aN|GGEN B ,>S&;Iv='zq%8Xo"oLdi-B*[s|w1 BTU'מ:+DTE&8!Vcj2BK[KoA'H$(Li(",u-^ǔa_DW5Ja1f|;:nʬa6h+ӬǾd=&s>VuPE@6$4gsIw&!uZ⺏6@7* =?!swmGbHfj ,a}LŚ0^8@-k$=*ecǟ00^i0cRm:KB(Lv,$ȥjc{۵g.VjK9"l YyuReN96Sz {ﺾtSϧwnp/[GR[\rWSGtX1YScsSN2S4rx>>tPv>d+!9djwE>hQ}L )H1EWydEړ.>4=;d%& =D)Ȅ-o^[.,!W6-=$kyԵunySJ"u]& oȸaxI4U8_ +Z!~1E}t[z$NƼ'׼Sτ\4?3PݲRfViӉmlpNʼC,$֦W/鄦'k8V71_>ɛWó ~-L}A>qLY7.(B9UlZjO!>XANyEzjc2E"?`e]ّo|=LB)ec4k $`> s<5(lymFb+xr*BSNo{}W;!E ,y]7"~[i -xݦni&M>&n Kr tgzͽʾ㷸9]0$2Q='1 #dP.CN*A&'DLuL1BK}cYv]6:H{1ȳ ^A =z)[ uLLn;rl\ Oê&z,?k똚U =)GF"C.\` WK+Ќ7]ǔZsj-Te uCK+5][sؠOe+^w{`7\ffe1ip﫾)#k[]* C0YO&*luŘl z~&Rm;)Qu<,8j<ȕӕ9 ev.דndc8u0*_VO@SSsySPwGbY\ЫG-" 2 2S0 ;\b:!@HHW6O=&:خbEdce^*v7RHj˒_3q>Jr]^;A>&{([ b_f'{N\h[AĬpr:+ȌUt1m'3\$~؂$4/P9)Ä́e^vMvܵ&06){,g_=ȁLnԣ"/6:#$c1(cdhdžѝB7,ܬe2NQd}Lq &m 몜=ru(\|cӐp["wT~1Q 2iD%38C*MQX u/RehrҊ'k@%`ʈT4uc*,%JS&5->~O-\R=p+_Ч/9:`2|8̓C/GEoLؠRXsПeuLbx5+ێ2 L!3+ 1V{ ϫ&`JƳ-^n{i L!NYI9愽)@ oc-"ݹ >87<{Sm>>o9bLΣl>Ԫ94EtiUC?#CEGtVW:KƻcUt'[fB4KGkl~a fbw+M 裮D>lVI4C-?9̂gCBtǢ`511hwǏ|W4D846l{;9,K,Ki|{t}11Nji̠ Of;u'> XUևUUphBJr_ }Lt1+`UX*g{ruԔsv%Hʵ:l1"=TXj HȩTjvNVZ`L|FǿAc8-!pSaf Aa;L3-7Rp'!mbbFbTuSYI2/-eV@s~L^ɡW7w$4L٣&V'"-CӒN<3DLK199hi*Q9F}LHgU"yЫz熛Ѫ^1̅މcJZjֻd!'Iӣe x|Sߘ jE3kY5[\rE·0Q*U~Bԍ7>Vй E5ܔ3}&+ͲkaFEqrN*[#Χ+io4A[ g|u_vuL&V;a}.t7[G+ [t'^'VF/rYt$Դ:{Οri-7rji߉jq_Ҹ%CJFUߢ6>DN <[1'>CrJr[]}或/9tdQޕ k"9x|rlLA46Cqs`f>=?m27hwB؛2ҫ>r1ՙg= l/ ,9oʻ^F١{U8:764qy$Y+Ք6J@ɡSF0Vn*ʩt! Ijf$%6{͹q'~/v-v=:scU6zW K~м(*Ʃwr?SyVVf0dx#qVKG\Jb #ƊJX{!*chfC>u\"jft;]lɡW isQ:mQc*??cLt QDwU6ϝz$$٤dF_vu'.ӆDSyɦԓC$u~zEF%)80i%tٹwutl/dըi)/f]:&c 54S^gG:]؝z%Y^de3|0)1@G옫Ek .KvU s$ɡVP iZ*N^^k-خ>mGL=C.XT2媐 (X+q~X}S!*#(Ol% ߫>Z6(}׻zN_͆Jl Du݇.ΩɡG*ÜL5V;`dt Ci3: J}\ Y]uȗX39mg,l:dHLE-fcu/^T\3!VIT@!!dӫWit}de}|rZ\dcUat4,c d&kMﳎ߫>\CMJ 9pz}Lb]eMBTK #NVhu r2S!>&V9|zWV7$Nmxn߉?Bqf",bWAHo@މc>xbDr8([>gXBgX+;ޤYM\a}Lm'9JL["AMw*Iov:rr4P$@Pyc2q3I6iC# cT*&͟C&yy2+}ϹcyTHy嬘::dZ4YUh`+Omcު2&A?r,Ocb;9OQvNpjKoc>a"W)1l(ཡUݟ wr |jҺ2Q ocU)sJ o/ffEACQM={Q P?oe}L14ܶvTzgqz?V9-q`)} 4f5s"Avtɡ t>puɈ%)}"Xl(3i:S~Nvoj9KÒ9נ>xrlSxx+JhPwtr: iO:pݠ_}L! fYZcڦL|Kԁ]&A>q9e3;'*e+b߫K(u3J5%yu9O^"FDunWv8dŻc2yAQp?S \oC.~T̏mVcjb5%YnY΄iN6++%h\uN|S,7+e7 2Om;9JuAqQL`wwcjbÒu7L) 5uw#'~ctvt*N15L^;OّY!u|/zAx!>VuҡTjEDC($3\M5ljRPP6 bǯ}L G򧗷e)g?2O=`BiKF^=;}LԵ|BKNưWt?NOi;96~H} 1%S*KgU\]SS8n8C_i~>~L x:n^gⓉ""[`sBH^U/纏UXUgY5 ͶzO۲O;jj^ x31Xv+ezd.`gsE0E,o:ꍸ"دi|a6ϊOKץ#QڪlO~;9A^2.%Ĩ6T)>¢읋JìGu|/HAk=+($Ӓq4} 1rZNJk=. Up&>YjTc0:&AⓔL|SgjsE͘rlO=7Jو} 1A,KTҎ}:Ƽ1r'>Rʪ6fD>V5KE XoO:4$'Hz82b!(ʒ(j<4wuSx/Xa9YNr !~#ikݗZ;: "g\a鈿D3[rC/ |9)*wTtrvM<7Va-ݡ녥^7˖?+b>DٜSom{?yDO}$1SGs@铼x}LHIVaL}/%K?69r`ygOIsEZ\ 1 "KM/`L!O]CT3#{RRJJ+̜|IsY^Q#x[|Q}kO<\)էl7\L 2 >!(2_c\GOM| 7L!WQCYPZιs:|c>,oE5' ,"Uorzܫu4*FVuVYȥg vNS_Y70’ɡoZsa[# {/:IrHdNӱ+Z5=TOhɕwp([U;}G;51UaSiT"cOzr"r:41_IuLY׵A}d&Bt\C_b0@Y||q˼:IСIˮ[0t'^ͩHrG~) '|c ] jG鶨M< rۈL aG=N+4sjrE[̇3x;3Z'Q 395hS>7L(gz +>ˡX(#s.'d_uL-.[|nW"5)/m|Ĥ{SOHCj=<92"`yXf}A48$01E}x$(r ʀ0;[gZԠvY iWwSiQjHYWF3y SO=C@"xP ~LWݽbhC.6+9T(c0wE}X}SxVy0BG洪Y=\8:УdvV~ MPMR/>'wU(bc'`.h0Aԓ>xܵʅ<:boq}5C댏Kvh\430}/P}%\C]!CݢE:|46NcjqY$esH3J}s΅ ML#|T9d~>D@]{PHmRo;}ȅba:~=LCٲ3UlLnHݰ*vZgϕ&練{*+1꺇*~u̇BD,OdKz˅=aOX켻$Gooc 2%$p@!U9CQ;>УDX=u\ڮDp2l,> sGݐX|S7De}#SO{]ц0=˞;_PecFw2n'tW}]JT7cjUXNt ]\?މ?2^6o tQc AfV;IB]V1TO}DԻd'UF?A% ٍS@. /m|VL!ME^ eExZgdbѾ!>[ED*(5yɡ*Ң a_@͡Įa)sl?rr9BP&ƺXY.὏9Etsi o=/v+Im9:1?6avh}V3'>,VzEWD]}1rM@`2#(nџz^Y+8ŀ6ܜPSKK=u~Oc Q:_&֧]D+&e|]>+ڬl4[9B NqGIzmm̒*CdcAhDw~}ދ:C'+PO9wfe?̘B.h lW Cj,$>Ԣ (9&1%a(j]д=t>O6bU 2_"}L!W%E[KGR$եjm'H|sg^>Py[jT=iT\_rjeeNguYIurK'4QE-y ȧWԪ bIme쪖'9zIA Є wuSrVWY`Hdu&>9)#YQ+9+BJ˗zS,-ͧs!P:;Υ ̈+ӭQ}GIxObJcQcu?(1:/WSc*:],<OVO}6 酒eSK 1W۲ j ֘oz,T6)LwSZ/)j YCOʦzbjpw]e3,>b = q'{7;DeS(5L!*XիaRrV9W}L#lt"ȺW^GC 5,&6K,n«:#1z+f ᲗO l'ȟ5tȳ ߐ!mG;pd(㬕8jĀ$NWGJ. Ua &cjd,]m4`eN"RUǿz7\`XHmFkB.M<&vU+SUwsB/Α-n/KΟzr!5t3䮱QJ/Kc _@n#.MSG_CH*yR)T4ݞXr((E)(OCxPSo>1D҄,GO$AmColsEeO-75jwrs[V# }< +Ϋc 1*Fe'5ro T fA ӷc>KvidT^kMs0 )'^>f"wc_2tԪ.I6iY7Zz8ɡ5eV.pDc21,[\of!QuHgZȍytԎ!ˌަ 16Br* ;Q4ConD+i94z:z:XkA)a] mx|rY"8 WWi2>PYɺ Y]]Ulҟ99_xs|>1c2tj>}c Ԣw n>Ȇׇ\r4D"YNs7TO2q~U1lj/S R0&dN|2Q'jZ4@@B+JDcU܅2uKcu)5χ~YJZp}R?qlctgM$5N em'cd`e$G[/=>&VՄT"rV.].b /~V,I?#K%W"_)BʧE8F%`T>ܿC=.kv0 {e71?X=^?*F8 '~)6bw똏Qk puUފ'?1Q黡R> &n*> ss'~;͞D/;H[ w}13*V,dkswvrlwuڼ4|d۷)t4>[2x$ssr]W 8(EKhwXrSJaiQSmD+^\U!`vK:׸1_䪦ѫc(qy7m'~ICFK*P63hAJ>u |?Fefxۯ?<οޖzs"9& mg?|!UX׿ǟA"C̒ۋ㛂eIxfۓ_+e38t=.*W3Y:VLT5%PlDgʘ:,uC$1; J)ʄ$V ,@p.;\fR~بl1(`( ;TłO\uA2q+_G.6<4Nӝ Q΍@JlC=& C h k'B{|A0Qxy7?bMhG"Vv} ~TəFD192ZnjN]~:{*}1:Y !CqZ僚R:^FQ`nJN$39*VZoAޠa'a['[BVc\-lջB MW0l)/ܧx֨!B:ڝH*g6 RVT|sɌ=Rt?^K1B,tS<> 9PSs:uRfCȁbDp*+.O<w9hR8a=lǗ&pS~B'Un,Q=g,pBu5fYQղ>]>,%J>pb + lAi~9)g#S*f"Τ5<9o=>0ISiL"+[Ϳ+FdӁ"_ )Ć]D;,(wHtj wUMN 2eφNĶV)_IE֊^I’bi[U=BewR¨:9Bާs 5`Sjt51Ef3k7R)S&|:ŐcBx>+lO)HYqSzAl^ryrB!~^SA۪`hZ{j=LJFInVjIxA^xBxTDw;;rtAjrE`[jcj`@,!Luz,tf5`)n[xY wEi!V y,a^˦s;tB9Kw+@NS`UQs>Ѯ5=zUDJMY}:?x]dOv I:u D)sbrj fT%u>E!)?"ڐ|nꛣNw)4vBn@oW=[[{Z~"39]Ǒ>!7&>GA"/:~#)>"$hnJQO;9[_Dú2HMGB:X[AtBǚrx?<2.CϡUcy%ް݈)eSC譆  dO2dWܤTu  T ȃ(5wǩ1PM~?ZZKJ.AYm (W\:ew -9t"Aח$/ 0#c4J.xJ7I-[sw)>d_IzS$T p|~<A u̙IR"}\:DGM~ǟ-Yns|x\ VG lHŅd0ON"MԩE/TP>.?;U" prp)ъ٣[FqRqBRu eF=+-S4RJ VEH]γ`FvՒwpBT_{!Ծh=g=ѩu:" 'c:Q%Ѱ8,Xu ŗ nj~lgE}_[dUeATϷWSE})_6*Tnz;Ã~]US~JY<jx3΢ǣ7 OP;DuA)N9eGЇz&ʖg%Cr-OaC! S(H {nyBbL Z0۷EҴuB7gVwt*+wKxbRBF-,?"hEoB8u/9\r}#H;XӝQޭ(~QU"JQ|B]/jRb$#vs)?T\Wz^,*:|)_ߵj:%!/A`lgb2W)_2֢Ї:vSy" 6S0]/8 hWBDߧ67Ն^i OLcy!Te,}fQ^\N!eOk 7Y]-ʾ8Ӗ|A,#_AQR-,?64ӕ)_f up]/ڳo?u3'l`ԨQ^X:>],1Ymbt{wpw1뒣_&e~)uJ8Э?CfTQ}5`nY^0B^ r'ۍPj} ẇMmRY˰d/oaEXZ׍R 9Ԧ:[ާ9i2 IJ,&59jܚP0*0Xz20Z5T*>"T5,KBN!gM"оU 9Srt۩y]x*&:_ y}65 sfN[!ꄥ: N ; P͖E͢57ݷ>S(s~VN;J)AVnt16;v+Uϋ(u!eݧTQY^eJ DmKYE4͑ነns)N!P [4bKT*GRth̾Ia8.K0zNS}F)4+A\n 5$qYL: LT6wL̩ʗ#~ V}˶|mS9ɺվ:|;x~v96D:K\W\ >SOpu1įڶm-D]4\#[ NA̺b> tcԷ0n9) (C/wTpX_:Xή吮&}}qB1ӫʔ$0Q~q?N`$Vv,6txa횲>zjMyw:>dm$s ¤e _NalU;ܧ9Fs>WZyym\?݉Qt+[,WՀpfSh'/:)@\zknTlMAuԯBhճX/Y,Zg~N1gyMUGmAM/IkuYuyIU  ~sZDzB9mdoUO;4'AkXr럎:FPPX]E-щ~ Ij(ďvL!pkEU\4CY-[U?Oҩ>UuHX[,e3 Y}Y67ݧsU:{ f%UTȑ |5vU2tVu X:N*ofnԁ_?IQi(=*y# LbUVAXѲy} =Le.mh7qSD_::lU]cuƠ64f_KnH,d2gaA~RߧaJ~Ly [hsp p5)h(bE, !g.^k} ʍȂMd|l?}Ꚕg\ rEvoZ%ª0!rBq=udZMg4TI9Iˡ*L}2ƲJt6O!~BTg3DN0OA{=VEq~xЯsMܣbTe/9`uY rߧ9E|H!zZ"(<SvMjSe!oSRxgl2F|OAJ:Eʧ&nԮB4)WxU-aj?_8wbB'|{I-bïrk{OJpPzl F|˪Ճ52u'_оfeTڃПPPV#c~xz* l ; ZU-^o_S:~)ԯ3=d(}4L2~/; IO:.(D%UGZ@5Vj\Y}}r!>?vw4j<ɘeZ #Ff}VM/kw`U9s(y"XR3D+#k)}S*%ڇg]^)]rtdЮ?Sz#P91V>;M592kIgە<e] چd9HȄ~z 7(_xouE5uPσ|Դ{zvNy3{-60bE\RK E/nZ Z<=dV7jWT:gt`;TCC|7US 9LB~iWjOWUBedv /BFE@0_V}Dj;TU;tƳXO0]=tȄ"` r> 7 a՞U9(W)qCApjhʷ*>xqDGdu3AgUnUQk- 6d [3=3Ρ[pꐏu*_7!+)綕MZɉ&z0Ye31r'w(ָ^ <ȇKWmSJ74|RnLf }g>HyK Ij_4))e>? T-Sʝ/&D00b1tkLiX'(g#rJeqK#Ie3(Pl 14w~d-K;!tttݠQPQ x2)Bfh4u rZI3ov2fksh*Wo9Vz2JS;՟F4'q)cJ'3fvC*Ur>W_Fke}SetpcvR[۽X7qkzGܩB<< 71DzJSsԚ0ZtLAleuƫ6[s~!HMGNd 퓓y0)S>4,=EUlי& Oym kDV0fPU8~ [C֧ 'mU^2NC9Ff4ªNUńe~P-)¦ճ {fe,HdVOsVFs'{T_ XR?xy<]~DN]WtEC-W[>vMjl+鑗/ q2w`ȇV Yけ'8U%G/~SE6+!I)8Rwl`O U ugJƷ{Rr.c*sc'Cڨo6:dhUq!!̀NCٟ}!l$#ZT?4ĔIph*&tfߪd8+@X$8dC>Z#[]푖(U޾'ٞ*XH?RezK6;4k:LH*}q\Zy`dodɪ# Faʯ畄G4rw_sCd1khYY|JywSX z.SPżd.qYؠ?^ XsC+TMVGhVrѩ%TVI3zlz`yNudu(=9x['eȆlQjVݲs[SZY )WLJվ٘N֙wg0`C=dO$`ICOuMT P!I J(6쮀2m{>rCohՆN)%|Tϖ߃CN%I:Ҩ%)Pt*Ρ7B0Ԋ G(3]x W)\)\=odtʝ;+BKP>\1Z06ʘIPHsΏX2ږ>X,Ce1U$Ce}g9YYE]!_b=V#r δӞInvTf۹E]wrBVYAC*4ʚ'Z:YkU)ye3sGlvESTTɉBV„KG/I}ˣ J|G"Tߺ΢Q)<[kqCUe};k(,n9˨Y""WKEEI~Ӳ=뽉1tC,u}# ']t]-+2Bσ|Țړd4**Y_t2|90;qmBW9eVu\k=(s *Ewg'غ]=|Ck$tab{9a:%=zTɾHI'(x/&E{Y m-_}}14d`PJ{PN?,F먻tbH[աߩ}_2J>#1Jri~U]kkaV݂lAPeTZc]GYBz<+nWDóSj|Bش2o%f,6Iv8tmʨtjIGp+H!ϧj^?ˑ39xVLK& }9<.|HL7D+OF{`uunT#ɯQ!f'g!$*9T=ۅZQ+<<@FN6.mM S-;|"J 9YհV 8O)rDPUb-J0'* R2ayCoo`[FGI6_+;{X#Ch]6 >d3IΡqQ F4YY\''NUn"6Q [<7LnM8uC=upqMC O@&uJ喝Rl#&@xE˥~Tup^ss uplSKpmIMo,Sr%.~H6k$!yaP7gOz 1YU\F_2qNtZ2&o*DґG`Be3NpjY컜xPWpszCF5(?@T~CVT,x@ʀqFC'PyIYMiT!_Aʏ0N$C Vf%m|Ȋ>e: #mlțGãXϡO,B6952wձ7_ݕ'__ leCEҎ0's(QfI?9q t*dW86)6'JNX 1u65EЪeM3_^ҕ`0#l2T Xt,l(_mח~C[k2*&R C\/6ahO镏=lK:3:`ηV3ƘDL_}cJB΍YO핬,0R|P a]MjPh7_]#9Q@nUgZP)jK)ʑ)*ۨC=~4ՙ#9$:% T,r+T䬾wRHm~$9؆V(@YA 2@Пn_'T7եxpӑQʉ斺GJ|LE圼r\iKݨN4GN+6;;? S$DKH`{y*U<@;5XÈ(φb2m9W*,Kl JߌiXVQGzS!!fṚjPs)0>v <]"#NT`xF1Oj0tF.kT"kwvC6$j{Q&!YA Yѓ, ՟;rTgMY6}z$.]_oھA0*+{: 7fI9*8V JQHB;Du-{}m_)51'ppgXNA>d[u j$% !'3%eu'Ҁ̲k4Gi\8S 8 jY ݲa;DOIC.shZ]dh+YhT;rY Rfq2a)u%rjRe]}9L[0۹08ݝMeg+ڋ<^݆v >}#9;x2nV-T |yY 0=:v9,(@+;\Ρ5·g#yش=A|A R#AjڧBN BMTE Ρ]؟|̝*4R=` zXlYЦV^T:?A>C~^]]6j7=5Xl1f_WI+v*YE8?pCy-[ۖ7EȢi7TAysΪnEݗ\$F+liH h9$9K~QwZSLIAN֕ uֺS;Tbc݆q9g! _QDȉS5 @1En jB#ć59} ҟN2 q`uUoIFs$y`XЊZB&~}i!TYoSw`,h|g,Tet3$Zu4޴C2@Ļ[uL4.#wj{ݕxxޱ?U$ m *ye5'sbBVARGr,(4XIOglP~[=`T%`<:U=>W=TC6j$FN d,j5Ւ TG2ʩ?7bh1a.$ R䃛:r[3eUYM)r@ػiސ" iډyށo;u緂*ҜAPq`ϱQFnsH`y5V4EOY@@ȇF]ud-*ӼzL]Q}xN  K>-Ȟrqب O3l;9Fyxu9A68__<WhW|A{y2'ƫKMZauE͟ Wj̱ /h9ܩ>6d%B xg 1KsHH2ks֢l̜eJ(=2yn`ӀSU(U|m"@d#5IvuPmDHujbZ28k@Uчj , v.)&D{ns@5j59Frv!`Y}'$فR{jz P Ḽg n@wCFP^v6NFmb P(rVL2)M(SV&VLJ'ʋ59ɦoDf7XJjz"s+DașnїOlC_u1n;ۉ#*EH^C5q꥚yR5/^QVmw)7>/Ԩ{:ԚUUF _]-xDJT kf/wU7k?}FUݍlpZwj%WD+q|(ORkq`j=X49x GK @FI-`%Нo1)+, xt9eA}}HVӣ>SɱD~A`uxڃA* ]qs{ZСzϾk> -Axa7F@`I+(S0Qw2 { xG 9R )*dmRVyCF/{Z]Pw$p=3U&U#9TRۖo l+&5)ecsueDŋLcT}KOC7wzCW¢\6Q,`ݣ;,'dCTnҡLk+:O0im,h{jokYArPݪ3D=jחE,~SV]{%_ĩja:H1|wNLP x=1ϡ7dV;~c*f4|<5X ZܘrYLcuL)}g9t,bL=$nx>ӳjbͩ 2QYjꜚmwP'PbY}>V ʸMb @tc~1SEC 6L+PϑI cuBϡ52rɣ9H:_:=gO'9)JfӖm:(V7rCVE^snTNY4gQ3ˎYjNM[ wO,_ǖ; 9#>MMTg*ϲ695X씾9s%=ޤy(k+isn,7U7Hiw}j8Dt@DW33!ބVV ׾ :ǐ~lHD}@3) FM,Qn'L:?`˺3/Uz9DiUC݈bh|2ީ,߉ѩ MXg a^ Nٲ ^h_}jz-o;5XlrJ>ؔKH o xk=%F9#Iԡy$* (?ݵvsݩkGL۠9mJvжD~ 9DMW+iC\NiJ`ɰuᗮqs lDOJY?h!wbx4b-2AmσZU!]ɍ7!&;X9^Jed{ѵWkRi>d}[RDV>ƒDWR:?rC L]yY-z5=MtܩblZCsBt +SBrs*/(*-E8)n`= } ;>fY ONF_} ^PӨ6hE)Szux&+]n{62U-Ø2j}m_CGI#/.ğ,{PE}CPwȶ Bl*{C H 5Xm:V`!T.FhUyR/aP}A7`Ä=1Osd:xzOnߺGKF D19)b]VԴcz+uHWoWCN J"XDU9`zC׸mF-4%Wڸ\;}'ܩ5󅚌-:[8>#m~B}1&DBª$ r6F>dEBmevOT?B:kp c]1RcHd/(+YC+CO F4Lh!;>Hp5Ks$sBr.Ԏ9Gy>5XeJa-gr*yF-5<$x}} eOeB%pjgU^n2ΑS1PrRb:2$@Snt9~VէvTNEe9:ERm5CЧ|:#‡q(/ABgAANu+Uފ:Zs<){ϗF˨e~yh9ix캲RZA*<[8!cj9ORP1sU o gNjЛE!ںRReSyYÝ,}z-mIRF G[U%_1)==?; Ed'ϹdqY*MDfyؕnߥ}#Jo(Db4U4T[#|$Ps:a$oM=G>9#8^zJVI<ȇ[y @eB~|+;/ $ E;5~9c#w3i(>_iTkXxwu~CV?$F V 5痙]Ff #}ڵ_ul]B?[r-f eIǩ=lV%f"*N/Jsh67@X#-YlUvKCy &B]|Ҽ}:@YҶХsY'Bȇ-ZJ\WgMCB֮QfGs p2e "F)j{Y. #*^vdYF"F`q'^ ؤbi#Nu]d /Eߎ2X&ȇ}PZVڲz-Yܜ8A-?5X/ĦOgm8TF*<Æ`+e-91\JjTkKɪoYO _ P_OeTu nBEuϡ cQՐ" S1F>duwYʍj/6Xli%|cL`W%C:T:Ӂe39@ K9RQc7UXMg046:jxX fn|9'i NfXuD<v2}A-i @T9QR^L=rqQr(̬\e$ĐmFy9őھ%d WM6*֝MjCu ٨{|2u]wU7Uu,@&[T~C֬ mxit|[T?# bVa$9i^S E}Xߞ9V%X;oll`6w)pqDk^BUeK߮9(?V";rh549L[RzF~'F9];Um>Y{Suo=fCD]Xn[ D49ezX9. GW*'Y,{Y]"rϬ[JB n%3 HXm!WjlScM򏡝!8٪9okOVB%V+"*9+_w1Xՙ[cP/rσ|t㚗V1LCB,׋*TNHXmٝS Ay^Yr /~Co$ ߱S ]ԡ3QG~5Xsj\QMٖkE@^ *X3 (6(/ I|.ZxCV%z>Woc^jl *%5|uꑯ>ԮKZ?vj픝*,6X{at\}T1)o59 2\feu5"58,`y䤤D(AMQLV[U*{=wz9ˑ%H"aSn,s?}Yƨ!{1X- k![r.D7rF9dbuu\9 Jr` ۔f))wdѪߖYV {}=Kk+!YǓIuT3iN bWI r"˃c;ñ1t {M乆߃|j 5P{ !=sݪ}}es($chJatSd\et;2p6QNza؛1ZBV0z#qens,qjԘm*_t=ֆjtQw9s_:}q]e &zT+Mjt:8ep: P_ ZP}̬Gt|mmΞ9l:bY]3kA}^Ҳtvs,R9t힃$|8̉yAnBڮ\*zu?uď*gOfOf?5XU锢t"*YDSĤ:dN˗xC"\׽Vuǯ3g"=5RҲ2c S%(};~.w,qCfa%xB wwj%4^$w VT)nc>J2zoshר[B!F̎R?j`M:5R"[UQJ,hNsH遾շMJQrl;<9`p$ėZت8 ЩQ7_u-֔PJ|_ۮ=r8\! 7[>CG/J5&⥛OЧQw .Xuf|2v?`A{{FV TEN MQisUw^K'\ju/u bA7'X^5|>PGxas!<>z[5!kv';E&|򔴪 e0Y`g>ЬztXeX2 D6ٽ ^T5m#=DYʻ0uDRۗaUAlx<,ʋg(Ml<1e@eu-z2?6@VNj?5XYT|yŨ S+MգWrЃ@J``v5Q Kڶ'`Mn!L&UvbB+|{KG@[Y_:e哶O s&IV=;"%C&ӈy#9Xk/RȩF.QٗkuYTkr}f~G9XyY::yqpWzlߢ[.`}}e7!uhXX|UϞe}O f;ۃ&X RE]sCA*\ |^9eJ(9ݧ 13)?3z;DG62pǕ z95躖Сu%yZ{OӠO1_A¡J,{ٯprN V*!ʑQ /Fb5wxȂOeIPIu N{jj5;)a"hAVQN] (Rzުf\MD}m0{+}$ԜڅëROu^A[wj|Q͆SG."Ťb'Oo%Yk>pE`|AALgל,fjP98-L^_ui_T3+9efKЩ1Oqr+gל,%MWKͪ_]S. }:K}ሳ;8UU=jw)<ȩӥf{ZdUE|K$5e8rCAJ:=ꣴe5UGjJml۪*2[ܛwC|Dwt24=< Pg]j.`u&GdN:O]O`Юq8Z]FqVn*,}U3"5#xNgk@]5 =$'w\x:|rSEȰF ʓ``ZPb&齇.!>2uY UC/SZ{n΃|]V׉gGB\heB,-]#9b)B)|LW$ Ym{SWC셔1k#N\琜_ɋk- H(]n*wŞTIJVgTR]W*Oo"ύp)g{EHkEubtj M)7ETR9aO#ŁDŽ%9xhJMjaVI[vTz*%PJV_0 e_:A"W.#,s< a/vYU;,g(zmi>dWP_I?w:<^ͼ7kr*6pdIZqOKx]+u`* Pmy׋رJ`L˫SI͡Qu 4vkT\T0fͺ#q/g!ԚZ5f);.xAT0!4De5pΪ8rCکzTBcTŌy/?<޿^4=Zyǯ5TlH Kecڷ?Dn?Nj\UFa33*#3:#o܇'+tm=Hnyy lΈfk۱W(f-.>0}DUBVY6oV 2JHb8:!ٕA,!nN?*@IlU=l汑?vlˠ#T#uí)CYy= Qm} @I%`U*jRuvթ )CI*y֑mD͒XX6I(>cNx\ s^ 0J(+U83̠!ޓgl2WdvQ2-sʈ*TÊ8$?͕d#/`\C#=}TG*dqg|nKEC[ T:f<\jlkf/֭y`VG4Z`s{YYR8NTаdcfGu _X^,"VgA^I>Tý(ZUmeQw&jJ%b1)˩)BS|ࡽ+:zz:^S^((Vv#Z WĪ /~?+}ܧl*s]eC·d w€3ZY.8%xR1 >BW=: MV,RZ)O{eÊnO1kS }}ʡ:.SR6٥\OqChMzT~Md]J@SEMp.?>BS>8'H|88}| h''ªQ ~:5%%!T]ն¨_3~vu:O  ÉMqۺ:$ʊ] uӃy4on78ާw$ǣ@y* SEáoUa3 y`k{Tly˗Q (1B|wN9S>L O25:m&~j$iip3jLx(8e`?x8qR)ؽYp;y;\Ytي^UT7?ñt_03G8AuREYA㧘S>@hO[O G&ozNm'$ 6ZŎ]6ń-*=|=Sj}faRASK {$ЇgPC`F\L]EZp`J Ah29:w&jRq/*o܃ӝ#S9ל,XNލ.Mq=+2uDjD=xMѳnSiW,G B:݂$uYEס>b 'N&UʏJ!=Q#+Ln,$ko6ݛ :4Q@mdȰX ғRl.{Gbwֱ޸}RqH~c(`K9ȿ2Ԓw(qY=Sguvթ}Zqm?3s#zT Sju! s8G` P.zko]Fn֠Z~ds۔LcRV7ȥMΡ;mOR*d"*ytj L.U@U']>pҶ__2lK:ʑyiA<9QʓRU"uz2dԭG`{WsR﫡CA$]d,*'']|x_V2ɻ=֢0)53E-%QQeZB)haE]Խ'|m<7ޛ'7eNK[l곫dUyb)2L;Ns PgRSV^Ze޿Ug}x#@tXZS .>0e/Ze\~}J=–;-Iy Ӈ-hj K+N *4w>U0K?vrq b:{Y]\Ôd#qN6HmSmv >Щ=_V] t9AOe kʴ'9!͗wRVZ|wlnvК­ǻ.,pey&AҘ2|uJ=Z<#CGi|qׇ}^VLCcKQߥƓ䪣Hr>uJ/zҪ rP=ybu:?]jvh;OYIKU#uRQEwO~`4;NYr+Mp*hэ^g9v! Ce:Os@3㟵}9ө2A%R5*j֍|__Rvn YF9kǟ3! ! YvNE eiZ~TJJKp ܲ"޳?u ֞S#MS-K2% (Yͫ.xsePx|>@ w~RϕU @ڰ<1 MEM_I" ^}KZ-qTl60d4@ɈN񳸾N(m$-FR̡v|}J/H3IF0 -0yӴ=dؒZU dn-t[! kQLOTXjZ%,=*:'.'ӐDVbvZkB4qaV=|x=$_kPT{41T|8YĪQeV˓6TL砦#Y@|?[O/A+E1oSإ3j\kpq; unr.!U)yC&BazZZ{HRb_X If19csq'K[o;u|'#['IơbqZCD!賥4 c\Rv0e#g4&VX7}vԎ5=(?sHpL3pu.QE8S(I?*[EZ2bA. %l|O 6^3J_cji =Ul*w^&0xQG?*V{ȁw *F8f߼nǎbr[(Dܸ c3$Ո~-ʼn\lTZ_;COt) x_dC3)-ܝJRbE4u4XF9+[L@cB-pǐ3ͮo:{2JIC&|q& ag!JCi r ׀͍6AWhC߿0}0עʧ鄛 yhfvLJE蜕+T %-(˟){H'Q[GzTҬ U)U y 5Uد=l!AB~}L!z6F1%bs.r0Bu=yx$z 4H8ؘXoYZHi.w㔋B'uhV9AӮ_#WKZ|C;ƥfUKx*vz鯮}9Y c£S~ilS弍O [!#DG3ځ0\H -൘헷CzH5t*e#8}=Ǽͩz$j&{4fmjl#`ҹ"0FI_=r.WBFdb'=Z hƾ)UJ٬Ǧ A(0(s+mdDҫ/Oԣ5Φ ]90K4tzx *球>HmhU RNhgZB9?T5B2$5YNJ/N tMur}xH'qϹ{R} 35z!#vP=DtDjCWtOjKby_|G* 5gJ]pD As*h[ئۏ!9xLnǴ3 #V3Cc~p#™4حJ&ٚ/ŵ9BʐɕU$OFPI KGky)7!j57[J: &QC;on}}I!5=ag$ *":G_&;]1F/.u9z\HMӡtÜh{HX9}h1hh;ϞоTbAF;WqA:ߴ9Tid<^'1Ewn8a8:JMmUT/wS,U SiUx*H"L*ը'W!,WWڧp{FPg8]a6J_ډf]*MM;.eL_C'ʶș)@ Os^d5q`a氛\F -d|=ѭ0ѫ^Kfs Ӣnb@O…l@SQ;}BGaut&><4nGzUȤ؋y}^fPlRadP k_ # WT,!=8cv:' CY.5՝TW-t. ;;-sӟyoÌUkN5Xϕy  C֌W/rƫQjUgU "<0f@H`_+ ¢;!5/ZrCqNQ&_߰VJh^"۠cHKS+LEyHsUW51q۞8=k¢fښ^` P-,M28͜D^%X*TE0cuks"J#Mw|i*h(A/Ep4cb'6.uU^b6' אGSPFi%TT ' A߼}my#ҭ1XH cc2.h"Lmy HjFO=$K(4;PVniAn(6{HC&4&90!<=MJcc9 _{HWDW_E{hlW/6--fϺ>5iUNxé*?$D 3-ؼ z-UA0ꮯ/ +i9mm$*mjLA+%nTsQ{,P3β K}AoUXnlAvBS PBW#r@q_zɺt3cϳ >}aܚT.e#(nuET[]PhВ1A\p]-L WQ"m/Ua!;A{`+")s0U͎$02~n wu"{LN(#Mx#l˩NPY:r*]sűbbF^6(~K=&B"ϣ"`kiLTqǝT.Nn)E"uI{mxD{tPJV^n Jե{'!aJ\@!RxeuQij(!Xȣ&V"ȵrv"ʹܶ9r1B࿐-*Ux/Q}'E<T`Y Qep?(H&Կ[瘚T xԍa_Nj' E`W*?9 wx /lcx!k vO;P={o H""[ i*1ҝ UWT6u17T4zbv޶L8,Q zwظ`ύZl$#$-8~1 g8>q̠ ǿ8v;ua8@lLubR$d-D^MD%At酽D5ʤUI ~`=jkP`,]ܡBê&'x vE 뷨*G} ΧEOC;JMKePF9Kr\i?cjbBfEw{X)aYoL*ȟ4H7cΞBdE>w#tz^t6,w^;p} UO^L.}Morh6iDw5UO*q~B98y3_S *6 -l)m*8a/=z+cvDz~HZC2 E!ap|<0倲49={IÚO+Y= F< W^έz*zSZW|U媠L1"aUD&tMt ylQ"i/1y  ֲC^a‡P8V-ßsL….Xa+`6.Y^֭bE)*}"Šci0WTf&H)ANUŏ̑Bq|\ By^ ]wb_W|Z덊I]"nrhuq,b jm$)h#%Xz6i+SܔǻUԇmB9Wd$;ppH˘T[4n:j¹KObZ#T4_h!CZ%A3v??p.(! ۚf!_w[{C]@q3Dڍ$$qSwUPGeH &@K1N{$zp=V\8^#Ң(ܗ_cP8uwLX+ro$M$MRўwYUy \i&\ıT} *8 O'uɷz}!zͳ{wW N DWP.Ie_{I0X*{x6njmCDoC"WbJ?MXsv<[$ըgQVsQU3NmBK#U|Ggs0m2[y)(OYkԢq U׬I]zw%iM jZ9nll@ѓ2Bˈpv,U<^Ic̆=2L H",ȥJd߬Ji^mn`CcК(ھ3/ ZJe/`u'E~`] C+X "Z, ZTVԻSW;?eǀB--lS+̾ľȏԂJ|b?b bc*jR U\ <tߝsLЅnZCjl[FJniHRGi"mFǢ_~G1AasaD͕ SVߩ%4}F3ڛ+H(Td "T~NZ~9&vi!wKY^B74\v!Ob1<Cߙm|zkb˭=hΓdb?Ui+5HψO^:<\8@znS%7+cUdOdIІ=CIȥQfu/qd,n6}8Kef (%t(|Ѥ<v SHUTt7W1q,@>zezf0}R: QI`tO7nc*_}ɮ; $t"&\A7wb_v9ڒ"릻o*갋UTg+Va3GnK]U}+r5zn =Qr;nCqE!¡I),翌 UFUleӄcVd\f8R\4VơthСգ G> }Id7 ] ])iԿM \iroWT%{Kмdbl_ຬ ɱEGYC ؋sׄ{)KKHQ(Q>d1PcrMI|}pGzF5-1)cӪ!R*с/cRvOvP4^va7/&8[\z 91lhCK"']mm`I#}ɫΪ53@ ]Pv7UՏYҦ3V)Q9t * xl7*cvh<;XqC +@ƴ TXLKj^|Zr[ߢ@Ux.!LLZk BbTO!KT7UL)wi3KPQQCEuJ=&Gn=gkǙDigEr[ퟋ,b)56taGϝjȔC%5*,K1ɕ\XBqK&U8;YSp{ZKl5JCnJcv{L?WZI W[!Hϰw.^ZppC[PЯ4upԣѾf-1Lf HsL…#ڴL Tl Wo{yx$rbcll=tdAobG³_хUj!0a[Xg�*ǚ+c9dY[+99}T nP))fDVw6+GEo"ƞc:+qmUPhi>cn&*O4MUIYrs1Jk-0Wa#r|/\n@UYh5.GX0Ii(+1]pOմ^_A5\H^{_S[yy3FF#{v⎛sӮ2gJQgηX vw<ŔJcєxiW)F7hRӾUu96JSTztho u$~оlXM=kOh=8g(v*Zw I6ЅDNBE0x1Xgŭxq_=.c."XSG,xHK*' ,nn"x״7*J6[}S*Ow@g.cjb` .WK9'^'{9T).BS|WhJ1E08e,1TB {Lݢ$^cP00)%r;™gMS: s!alxZ`D69&)iW-S!mD QG_dt O,([@en7=Ѳ]=Utuc{"$WF=^,8TVTz7o/Q/%WB*\y4 ge(szf7WpNl {8%HҧMc؉bb_+eZ*n2Zכq=$(*yH; M>&{L^tBok #K;T]ͪ!9$L kRBCh5Jj8"J T/k'a fmՌvs̀O FaG'-~N$f:*rdoJ\o8r@_wb_WMZ8(\PnqQ𦅳6#knj8*`L*#k)=5@>HV@Y3Kc(KcDm\,bi<"FlosDsAxhzu Z (f*K~@=样_*)vNW^.@1WL0h3G+)W`ی&`8(.c4}h,Z0V◰,DM1~ 59B8G^GP|90Qa?G *}븻݉#TdH(HYB>{L…{@ 9P#0oJ]144껢>MP2>К0M x(TI}\Vh_.'*!VBܮ:gTTQ&*x?~{Lv j RP]t'3U+/IG-ebV@lSE&s1&Xx0},㸇c WBl'}=h9]5YeE?D*,%ցql-l?ԕ$ _1 0E*b"9_NwG7#nZwwW^n#i+XK$!'SDtn=jW!O,-V6.a`a8~c4_.z>]R:V!Y "`6rA~k=&LMǗa"l˾)wQAkN#N݄U5d5l}t /h@C%x0uUE }O]0+Gs]F)p>]`*JK=M1c bF,t,zr"r0jE^׆Є0i9o9 0 [c_A5F o;{ί ~8 0ޜi (q,wrB׺ uy9.O$ w=BHcɠ WyiQH JN,==dbiEPQ,J{_)E%U~8-&|Fu@5j}SJ_KsL`L c䵍*>W*K*uxD@v\JmLLzmifScL?ͿJn92e [K嗲`W6rxP(*(C6OCR-l<҂9 &!6O9&ٱ?y$lS^뚎KQR1bU q`Xl^ʰ^L=&) ϩ:[4]6%>ep|.4J&z; ADv/d JBK+;w $L"D/!?!d%H@^kWhP|I S=qgЯ^0mĉ c(68S%Vʴ.019szԩ$X 줌muuËAF\IfZec}V՝K:w=f9Ô,C1^0R[Rx̘P܉}lP2EW u-8n4*^qR]ǤYC(p7b.<1gs#^>kE*ܖhՅQ,4b%>Bh. j S3Ma2S.E(l:cm ,!DXIH숦f"bcr UĕsJ{8wⱫ 3^Ŭ]*kT~ GѴ#SZ/H*tFurcrR4YYumF.w-GiָdNAXΕT]8q{iUA"YgaͺzO(t)\PRԌY!ծ]3Tg'fI9So:t'v{{9YM V}mqS0+o)0vb{yreSkA#ĊBkZpRs`wa_<2%=h>'VľoixCmXLW18^>sL&vB*O5uI;OCBS/50XYNyZp-B\;Q_iXUm\!sb~( STċӱe &Z8 W%=&6)&"ir܉,R]q-\AO gF@,crc맺*0?`Irx kB7⩂zrXޠ{emgWyacS]=$%}#Lu{&Nrx WȍE$ol8 >qґ 5ca"zE֩>I57f)p..wrJ'hHE :QfTaqFc{F Oc<`J>Q5v9J^(!JZ嫩. â;GL2zJ+ylZ X>"Akbق~{'v#AHr/mG Ml4N\WL E=&j6[_AJEo cD]''f&(|jύVP(kz9`$% Е-Ѓޘ֗Ѽ4Gf(ZqLjEMkSZcF"sӀt*ixS VCrx?v[EF@@.g5J|qk3{GE~Us̓đ"Gm]7Kx7/+/8uN"hTlj懐POsy!䱿hc6up~x|t*o[ a(z>JM.bTh c)=d["x,>G@ {9RYAqZ9VPk;m2^C1YZ 3WG]y9rpk&B;4bIVvçsKͩRee1a-RF\kަ*&*:Rԅ AN!!نO />$%G*׆C6aEż6n^R^9`aMJ. ,3LsS[t(Q3cR%cH$wKM+ľȯȥq(xL$8uuxiĘ{nC0Wc. $4#*/ľ%FxK9 U' -Z_$ѿ9&R^DHL(_EP f3oWP 3wUϪ9pjc"JLZچcjbU}đyv=բW ]/81K x|լ7pn7?Ge*[Zc`ѿGWu"UXBi=>d֊@v`4IUSPMے {y ^ jCU8o W͍czi9pΜ`P*)jZ.^LX [俅 טJNA}s;iֿrxDvf2Ҫ"\#=c1)j=sJ< =o^l%(ҋ Cn6B[ /]a]T[ZMc*YTW_oV-ڥbgU? 1MN) ! /~>M1cՃq80ꍣ%h2'pgĤ-V>$Ka#4G5Su54}ԴcGH[[Xi\ʿ^4rd-YgdLmHHoS5wD$̖Vګt[H4i/>_h\n +pxqD/ԧ`6~=&2GT#NU΂sPk=|XMpRq,69^%wKΒ*Q5}51c&U iPӻp{} }ExԵ52FZaSCEj%F=8ǞcHq,{ &w'v! 2ZQ84*tAuTK {iA~nxc2Q2C/ ծdEWpϕ]M8$h&wt#Ɔ.k8]s "F#T>h5F5M#=ZzQBi#ûTWB(jptE[ 8'>rRBR6ƞcc*2VXydK;/ Bj%c LPY.48jQqQ/<፰?9Q* }*DGŝfBzH#zVy$] Z1.U^-Yͧ>Vuh8 lUƾȿd7_95JS"wFC% 0"cJ5&jIS $# !Y7/ku㛻֜ `sh joO5&-GzśQw*hPψU2hh篻^R-l Z*荪Pe]Sia$% A-41%TЫ1w;1V5=-QR0s--h8X)=`X)k}PHP W ]/wBnXebpKuѓy-FK:6*8;\sLN[yg|@|Rj 8>iycD]h[5頯dԟ\蝏â>ia'iqjv_7w9~!`BA8kLDUR,O״JE#q X3<1Fӛ$$ V:Lw#涚[7SbV´OTa {b1Y`/42TѰ HZ7%];ޱôXf'ю7QhsUX+14\S-vCp89GCrx[b WU5lCW3`~"'SSa-Mf7^oJKZ{+ū(x)tB슀m7(埉İوMq,ߋ$+(/]RjgR YwY@z~QJEfەAT=CS +vs{_ZFszihJM rAc(Ս(^+crڳ=>ިDjA/׶\"-l̀Y<` }'oa!'o.;ySU2œm☨ m*FENqU'BH__u^%1ύS@=&O k3#Ѝi0f1D{GCU!B9 V^9 ȷ(rsc.ƄP*fȝKw]d ;UCQLVUTDU]+vN%}ɫDF3Xv!&4J.*lवR|tB"*P(.xWs O]5FvUt Eob_Lk?)*R[l ͧ贞5WnTg,(@m`{Lx``;XD7ps4@ MrxEWK (o4CѡEO=&ۂڣr (VIa ob__,a:䲄n9Gj|=)x[-*ZV?5Nu&<I!U@2_ONqFL1#5&@@.g:m_@ercǂbUCHKwz9s#?U%j vE`{ `b+ OOJ+1a U}0h`E}b̊cƚTҢI P7AW^/Ay6a':c2H!ixxP#m<SDy=v.^}~;D_[,Z= )Y@~m.kВ(5t18刣#q Cf^;/[mi86w n|V饁=U[]M%fq=&B;l_TNIQ!фE9r0,Nϯo)m ;5#=]p+ ͠kM-U">N,@yj2ץ$#=:4Yzb|$\TnkB5Cs4!"kxHBp.,Z*KPJ2{Tq;~IMhE $: e^u eG?6lSai,/W>8wL9PtGD-(3JDXhf?DMw-5ag7%M]y}XI}xu4Ëi-QU+"ػH\W>jzQ.6##D ao `;2>TzNDꋦ2/=$D|i`6GpO9&_SGeMN47؆o6!=ӽdi|-.lF-hKdc(F²pj^杻۔00)>~ UMŕU~ ,[c1YcڮPB6 얜"lp'vP.+cVĕ!=ZYU# {/cR%[qN{/\|#ڙUUZzAڬ M+QEQHc ?E{LRF=09S Ke1cË~ "Fj\\ EGUX޿<Aղ&ѷ.rx;4B@'45Sh4!D>' %`>'|O`?sbrB I)HpdS8vy{Gdk Ox?+؃S+$[ ۹5>n'Um=?_ڠL9_أzy0?BE3(J+(q/(rxm&$AJ>^PR A)&.aטg;sȋ+=?~^Ey|1 V)R 5xYT\faҫh\i.\8VJ?V<tQ&,x{FI/r{b1I]e- U$ Tp|4?|MKoܻ(apС+/\$Wr^ty鉱|rxmZ=V+"vNj7MC_p$<TzUhcѻk~^ gxû'/"<m_4EuDyNZ"yć.#9w98́8J`qa2JrcBE=k& |D\aE!D Xs}y ^adcHV(YY4-r&|5Lv(EHW%;|;w!8׳wf_'FjQ|VAO3\"t"5EcWjW6)$aG1{y*(eTXT L;$[cWM *ER¢VhQHJh:+ɥdW3^#D25b~x'wB|8pK K5xuA)6Ǖq_%sžu8`p-+HƬG r[>1 PTI ,斪8{IMiRůMR7_~ft,t&ym1pUB}#4;3=| g:zZ%`\U_oFѬPσ9("6W!}F*QO=<~FRU*́mGb Haa)T}JTn\.q>,B^5% ëDx\43]^yoO&<`}1Z>8rxJn7@.\?%g0m,x+0;Tyyew=N *7BVQb ~-/`;ygTTInw5&qeDMIމ]aqLCe} ˑRRptc1yb#3qlYᝎSѢU@}ÛF?]{/ 5SPYYEy؁SO9&I\ѽZQ@D8 Įz̍X0lxYY:nU:tP\漫1OCfTBO%=/}Gh u-S|t94*BC0v:ccrwvwCU2ud?ľȟ^O̒"Oi5bcViJV\L5$+/)ccGYNiܢGΎc[U jw0hB ~szy&f{T7Z+_g_Z[`Ngqt]4ɐi&*;wE4ʰ7%]/W*C2(e**<3^+߫|IJGHeiIU0jw_y9zM PZ^,pԤ[^>tVVBC]GV+Ę.ӮSQDBquCp녦fIXob1ryؽXs^E W}^Ņn8ٚ#LbrF4U.jWQ!–^cr1K)9(MEPݾ_=9FB1L4aՒ!z$T + ( ʨ+8&h_hZpjaZrx# ͏n\-GaM4vo馊͔@ͻ}3Dz dOoWȏ2XHf2X@G Z7ԅ+KvI"sL^ehk%RCО5E~Z$bnAeZc=A4hCt4-2 مKWZG߮"6tEbP/STi6$%dNy(Gfyɡ ʱ.Fpz6ͷXSsMd{nFcjb ;GwXUVh.H,lP:Z5klthJ0T)Ph')Kg-ϣOu. }WISwXXg2J5xUU)e8sp3%=S@%VzU]:^bCDNACb k&R XU"5/В3_5a=\E#NwËRkYUJk? {>Z֠S2ַgb1Odmgx^!J`N9VXdcImRrQM=Q A*7.HטX ޜ*Ø9+o??U&jʾ` xUWx|:[QFKOo D#PKQ$UΥN ecb_iv.readmen0 EܥiEMHtM zؙi5`C~Ƣ(LTBV$-╋ U觅&8|g**$)L̊6-GbZ9)BVWgO_zX :(i? qPӢ<ӻ׮I/EPOk=v3Gw/H^W-nN]/E6bͲJ!/S,~wC {LBhwUsEZ. `l ymCn )I}c `]D\MSLQ; ڜkOha7t:Qk4u| !d^/BypIgt:NmɰPKQ$:C ~ ecb_iv.txtVK7 /ȩ^A) M @{)͠qk^I})3/E~.O6G͛_w~tz_rs:M=]lZo뫧r[eòy?|orܼ^O=Qpܝm^l'o|ovﷷWNvrןL~~g &4ɐɦj؈i*itZצ7ǿޟv> k} S I @T(dy@ܣdK -:[&. 1QJrj)^Z )5 q\~Jh6!9$Pk.=*Li9"l WfۣZÉrhXku1 =%$*zMc |>1M`P$s+i:JIX'V_!F GOZ*)UxL&o&(qhPj Nrȗg^uV@ YnV@ :+cr h:&p(r\[C-E:WA#N+ PvD_# T+Eaa}*zdkRREO*$7&ؤbJ'ϐ=O) 0E\clqEOTB;׌h>U TWѓ!W (Fdf2UQ۪z8 qT[*z[V=lI*dDCDTbQr3$T s.Cb 3ژaX?R%҃(z59:_j5kMan!2]1 BƐѣ[ȘjBƴ2112$3$H@A}3 6dAy ҸDl }mRuYrm5(MvVWA5MԢVWjRjҦ||?~}_/ǯ_____ӟ}?{_/?|뗟~/-||A}N˿˿B6~ӏK_9G7qǟ__oxO?}___矿鯾KN5O~_㯭_ſk_cq2DL6ܦn5Zl]ar.wI3l̕|{r.1S7sQZYu`Mjog .Ƕؓm2}ۘKɾRP}#?g)&ms[c]vUw;\.+]*W]5}~hʑZtvnWbncvk;yO>oߴՎ;zl KzPf2t/Ck&e=ra=6`'B!jC =hxu54MW ] \rH3>2"ٖʡ!ku|n,zte«Nە9Qx0XgĒJ.%iuwyx[q~_%#.{_l/rX}s#٫5r&lMczl5VWjZV{Epn{rv kwG/K`Ҵ)FgsK-4# ,o0빷]r3i]7y15los5XfMvDZCQ8~Ʃ[iݭ7}=K_0[)X,kg+9ި\T_d0mz뽏>`Lyq6Xh"t胷w [ez 2 0F ytej5QV1ld!1|fuרdb5t&ls7\żaoXvϥGcÌ*pFV-pF7}p-jRnJmݸ7. @vDya'TN|ܲEN%W/}nU!FȱZH<"KlXƹ۵+e]N[4B>x5FnĘK).4N4<AѾ(*|oV2ë6^nknYdk=°7 !J 򆡲 a6J:$q?wrIDD'l vLDO@2ƍ@Ԯ( J bxr6^aD-QuK,F&yQjr W,WN=Xv7dnK c̷=r01 l$n_pj `gc1&tK X#񞘓zv!n/I[ݖA&/3=K܂FO揲Y:siؒ+ Xo+a O_iaT}=`@b0NV#;x?.-[s\Xliֆ]BɏuaFF#sUV};( hL69-^x=$p !F!ڜmR5W~Pƴ ߸q?mİ1F 9gےѠd7,5{Q4 k8>9^4^i cH܍WӇs Lޙ3{m' ƒV54<5VN658IG@b0abF xumz>i!r!7>@nOAjZ`kXlh:b)Vj|T~ƫ{83qgp|d-dYK`eOs!*p ATE_x|/(OrK 85d^V4FIV.P/9 76^=,Bn0r/gv7P h4.t-~ŇKϗnډVq3xmz"mV+:V_g#ԩ-B@cDO'Uƫ"m+\׉7;/G'> ^ʦU%#Smʶc[뒯X#wcP H W| ƫ"8,VзEp":: -΁viݡ# [q+7,9--NamZ@nEX}IG"Vuׄ ·J Tn]4"m+d75 Es"2|7mUwzT)йfK{:l0EX1"achU ŷ^rV(\;86^X oEXAut/@1lp nz`M Y0vasx!nv| (1:`5*P.(:_1П.c~͖@>W+ֶu[;Q1G''y-~`j=xX-aE&xq'AFZAMA̱N 7:Tʈ^# 6^h`w]Q}UA# #A!VC ǚ \i_XghmV4"mvn=u;Zlp ^p:^Q]qyΫC1|2lPFD#ˤAK` 2KvSd:~5/8m`uƫ%pQQđ:<)g 5Dwkc_f6^}(畁0y x} m ~PDpJbUx 4 7,D>–{s[ƫpJoS #s%%H=mH>voXa1Yƫ%qPV@ "%T"dĽKhōW8rIX^uUքٓ > i>AN)M1舜Ηah-L7,P!SƫqHV"-/+୘"ڔ9LzK {s7^}(@OraD[ ^w` D)l?%nP%rw=3^>glƲ!7(#0g&s>ǁ9hG+/v[coQc8,92L~ƫqn|^&s{~|xCFWpQQ铃x?:D-WE<Sˮ:9R (?,_`d[9x!(O* Gݯ| l¨ѼpjnPH ݎF6Gⱳvq]xp18]yNxݦ.-#Al3/ZG\VckEЭѦ=I2 "/V9'$B"D(lPG/~_)?,LdǵpyՇtWC܈"Xvv Ig2nE*BޘJē.>}ث ^4Eyj8QWVYuW:¨(w?wՇڙMY\ָO[vΐ88< 5l5\mP~F5?h凋BLռ.Q[!h|` ZJ&)Ꮟ$U2gx8ƦxDSh6j}( ́gk2o: ,/$k+^1OUٰ40E`/ pOg^R!Q?VԝoP1ny@ѽ|hqmƨ6c1Ay2_xׇA[ĘGi5n Yu: D[ fOaLIPj ͣh#P1TĸSTBg"7- W!v3yFG/|ֿjG\y;ޱ ^jO'bxKZӂJ@BCoP6c^5BI::kl#"\ p^>I0꒔ЗXBi@Pt.3 ȿ J{я䃗)pC6HAZ#^ʚ9лזCwKoPBF o֛M;rKwU\C*vĄ eZf@zq/\Sf1Ty)!PJWs=bƶ,wk(Fzerjʢ1W8*+^SE,p7wI4wV%X?:c7}V:&^C}N'tB_{g{ 8גoTuSK8-ɣUVYKnc+`pe̍S%=u `p)S Z-qUZ!^ef 7r}(1n94̜Ē -?٧@`x%e^.50T |Ґ9n59} Ш(aMsEKæCB.YX 0n} IǵyyD,̺:%Rr׫R,\@6?ٰԂ"IpBgҬ-Ah`nN҂&fTԉ1M^%E=~&6ko(K2B?.% *-݆R>jvu\/5/cpw8.X碾u(eq{ U\ Kٷr  [{֠XhUiJAqmpݪ@řOss6Vs3j m;^J^ǝ7 sAsBմFdN '5U¼e7npR.H҉n0}]Tk G9 )wX>tg+)̬,iނre<6p6R_h #'$`~^o8?䂎v{$LQIuUC)u1/~QwP#j*398񶰏|;)^R^X.T_ O>tx(RV.4K@L ̤DS:_XN( q1hpi_8F%Ef'+I`D6RaFATc5~b߬$(c>p&5̆*uC),uq /4DOwrclPB6(›vf5}/E:)Th5ۀeyZf02؁9y,HR);hC`i=%p_Z0bMQ.O- [jkNH䡠QQ^i)zZX 媎b쌼f~eo1?}ǯ~>K/f5*hՁELT>8uPaN{~%HD6?hTJo LsW41=KC q歝1e=}S|+?\hYAK>0ѽ;,]჌Kَ)<zvqxXzɸCF>:Ecf ጤ8-կߵMo ]R0fj\ټhQqۄG>N ;~% _;f"fPFi-xvDm.S9ң +0TMCr0KO{~kw*ޙ@6@ CQ0ٸK=W8P U|:Nm;~Ť=RRffb&BtLE͢H ih%=#DU'%Rsvjks'KEE6Y6uh|XwȿWYR'V5Y]IBeYJNwB5xBNCmJq2Qv  \hPNhe[oO{%گc9Ji]+*mq3ay7i>;V*Rlo=Hx4'Pwy~$nfp}GXyQRu >O.#˾(.uvD'}1,e,mxhMIQs؞o8#ދY;J&\mpȺW{л "xɴFbHj|_uk a;[jvw%E.)O#wHqcUjW~4hZEq#Q*}(qg?6.;PuԨJɳ橪lWΉ;i^^i~8uײs;XshuVwe劌zNorH-wa0C%Hs o*=~ vgfbVASU l-|F?~]µxX+&v =K> dp% .6F 8#^}lU_<ⷺ5|5&GFP:GƭRtfG~uY!igc"9-AW\lpCvF|;q7GMJq1]5.;gQU!弌Dx':X~#P\!ͦ Ʌzl{q7G`~*'Wq &y1jMFCFqɫK(\j̶gd{qgH)KE6=J1~g?6~s;Ht/y*q}DJl]w*]9G ű_ǛBGhڃFN᧗=]1.>3B㔞~sD YO%Y~eQ;L8gi\>8"uY!G>*6b&? TQt(1̜Ʊ38\@=|cʶh4xBV <\QowHO?Yǩ>}':޼zXe)]Yk4eƩ;`J,d{7GVv`w]e/?mbA9R}\x=y_;KF񓆱Y sދj>h6;,DS!^]jqx`2B㽰S`n_\^vY,V%uNy{<'eGӗ|$|B oGtb-ℵ=BR:wMuqdYIοCb4M ħIȹ`;BS=-,Ow.S9쮟KF46kNqkH׭Ӫ> 99ӟ{I!RHzŘ+d8a'ƈU5"޾4:S9gI/L]<7d]d&M`t}HGXOQ>t ]^=`4hiM47^UJiE}OR^Ӟ|.҆E'!.K*qC7{ eG6>AĬ?LzJ"v[", t%4 iOjT֬,?veg1S7˭@&)6oZ狰T>TV\4 d!*0KQ]v闣9ժ$ beΣgV4{'2((ν;znё,r~c7viԛK65y~Yy`zLK@fR 0_ߞi!MWѮ1ƒ:i~snPd  =ի/Q/>5V!5h0X KS$P=R6ACnƆ'[՞OoM =S5/*ȿn[4>9kmyK` 7Nﳝo!y2yVa҂/zupZeTHL~g7R.tXd[NXΔk-.]&N ` >mD T'noŽaMbPdsNņzԘT> [(B8b EVy3AZ1-,kn,Bl^7s8L袩15PSvFStí $VC_4 T?@OO⇺7]X ˜3?oĬxy- d'mey_m1 sHWyul翵TEn)!52(@;nU߻KЮnyx߾m@=,kA)>_~L?n|s%I\x*leA{}E5kmqBhb/M!wWs׉|k›سϪ'*g]iU1ՠG-E'x(a$0J,trMeQ ҈qSKQog儉ذ`5l SvmSMc|yM>QZ֖7s0eυY oMuX@YTthAohmO[S0oInO+F ŹEuq *NMA:O[GPYۯ@G72j4v`.b;::"]lN[K̓t3fDhf. G8|2.rchl^ STwG79 pmlQvx/K}ÅR.da6qcҧ ^l04uqȗo-3qm&aWHυȸQԆ}n4@_qimn ;OB)OӇ&)eh.5Y# 7[FvuuW3S&v sPȤkW sˆeIfu%̷s}Fn11=HS)uM#5y8RZ1ysJȘO XU!c64CW5H9+,vVU6gFNbA܌Wefq0Jl?tZxppË6h;3RS&kOŇQ̹&zz\z&U'~5B(|EψO([tb ]5y캝sOW>[EĒIt^)MÌZ=kn-b’!a>A)q?A?8(p6Nzo],ˈi'?5lWĸI{älK)ks E0 &aA=ۨOgQ)q`enq+-DNˢڶQ1H3S&fvTU &y;3<~c_ߚA3r U j*}l,#à']o9&S Sa'jZ Q*RKͧƋ}If/(Pjj!{\||Ev߸Ds.2)qܷ,{L/ k Z׮.MfʕQ\\8呯q9zv:Hz$x-κ +QT)q n!6 1]y[Ì i(.¬^閼߯[eiIJ0Yyaw]k)_rϦ')SʕTtv3:#N7ytZ[߷P+"\qMiN-:#ttѤ8 5|@ Ck;[v_I7!1:l6h7Gu$\Œ8paR4Mu>oe5kI>#fd;b=P.UҮtWWԕY3tg]V'~Q@WۋߣP7FoJuٜUu]m|fx֮rY5-9KU뵁滠b)/\s߆Uc2Tw6.Dhv@84^Wl`{[Ro`uM ;cǙ|Ñ5{i.ljΨSY#VUDЌflJ_Hu*].B3S_ܩ*A*U[ $s5ݳ!u|C{:xF>*SɨhSWQ~G?xYtu"SDxO+)/$S]I#)~\i *m/N>: +.xxF|JKM)JUyx?irTn}N _ٜg =WuOyDjψئ:W]5t.r-}5S_Tb3fJU]UI^7,^#.*$`Nny9C]  3耛ԕQͰ*UNN,f<:-ٟz6\ּFF8 #P5>kgAxN vb 8'ƿ^u[88 Fg|*,|1}bk A6>b(q+\Nfknu-/{̰fTټPW`cbGB+Q(3rS_G9tKbLuyG,3Yoq 6EuF}J4k[OcZw>TKc< ;5Bˢw>"eI) dJgu6uinʅ[mW)A񯳩j?wߌƹEU'n&ZVP6x_F}J823JYc]=kD/7)yxa)>$"ŁSwA@Cq/|IzS{zuψKB{5٨/\q&H8n"[ 4A]gTqIuCkbS;wzn6+5 \]U:Oډ< c8|_KS@n3nM-ߺV09#>%uUAEj﮾F-\,u5)cjK;xF"}JeLՙ~ UT] @R;pvl}gDҧĿSɇhtTU:/\.y'_@|ȤO=xLhTaYAnBuaPW%\7߸?Pcaa* hFS+^F*}F륛9l&-d}QF9$ >jKnYK)׹M|7G% FGEԊ:c K:jYIqZJjS-mt˸Z̥kfx?1f^c7݇'0Ͽan5.HܻC<'ƿMDM#<=eɗw#^jMQT&> !x)3cIJe}4. T\uj8gdӧĿX\3rK{.6s*%M)v3S_n!(b Xrot ాW|b9gv})3Za 4!dHC@k<{FMO:rϽp0>WkP/xn/đ3S_g] m Ϧч;Po4\ egNgĿ`Ն EЮ_=1Nݑqי#tF4~F댒l 6u g r[܃Tm_49T(I;[G#yl&A[3~@9|gd'̩];0XpVfW rM3ClkXX,T:\ݔsެ.$c,>< 3rS"`ko s; kS0sZ G?}:k_FP}J|?krϭ(M5z.-U=SB_FR}J Dw_ĸ+/w>Vug*MK]{X9in?#>%vEծ}Xa,T'-e'Fkx~Uf{[̮&a@W6y'2S`Zoa"ihj2쨅ئ 58Lp0Vp HO-{ ֮r ]O EUг=P3]5/p?1&E_3bUZF ǻ3Tti&<γ򉑰!k6\/eSuXuL Ďۍ!z)j eLlY7.gvaLHIv2Sba, ڇ=s`DtyRA C_ds ˠJPZ$lBSx. [ƙ_We{g]m q%Yes%ón녕8gKhd1t C58gf2!L3Th`X KۂLҴբlov,k6؝(^40nTґZJ[+3NfVR/va/_>1&"M3Հ.V( ?^xQYϘ]% |]fM^GɲڈfW6&Fƭa/ ;jB.?k ap={(WNO -ںf;_J/7_ꯣQB_vĸU4+2hd:A Eۍ;>vo?%0v^fq.lk{I;)B[4Wty)3~eX}M,.v.6wwi]:ơR볰gA5\1=@-b!3{S@xU;8 ڰ'ӪF~W&Շ_Sk]ʡ\$uX^2bpl+"ᕍJa>BQ22PKQ$g+@M ecb_vk.txt[ێGv|b[!,b]_ J;إW" ʪLMwO pI"@<'Nv믾|_.?|ϿzP?w-~Ww?>|><˄??z_?w?=~ϏyǏ> oSvۧ1Pՙ&Ci=}Y\n9X*oM,1{ّ\USN*&>w j'țdn(a~T /9*J=c=A$sM+4bQ$kMP#?A$sf\M+M *(yU ;Rj[͋KP4b>(~E撣îSS (F!wxyUPH; +.e|ݜ@"sm4 ):%tzwy̵={nS%;. QQR)). udaʣRQZ籗3dmgt&S F~Q yt oA-T*zMm97Muǎ\S0C-WŠa vxxy ##H1OVН4K!sd.AQB PKh`{lOzy}{>]]*gGMc/"W\mS$2S9Υ ȫdw3Hk2SJ\Rj*{mfZs>SQm{T}y̥AGsVJi RKkdn&ջ!q1*P+}wuu/!F57Aq1GlOo_B^#sq/ʮfֽ,P~2FJY0J >NKgbC27H]tai`\27HQڐ\BD81HbصN NW\k0G#͂H7nn'+d0 cd5%&gdԂf!@Ak6Zw XmzLf|a;cKkha!/-P@c+>nh%oΐ\AuhpΎL,h>xe /莰[3%w=Y=W\,bWe[YscBROu0(;G7`0vV]&sߞ2U^T QJ{tge2|i`!t+\&s 1R4#&='TF]qWLag&$4WJwܽR]$sA@/RHLb.!_.qW jCVE2$_a+1=4Ӹ{dnuk>(ũȫ5vadogz!^zr9Q1. { `#Xk%2WWDŐ1BI?z-/.:KM d,f.g%z.HF<"PSV@G3;2_%Jͭ:RL@Qن@ x ]E<M5Wz.[  =G@u dɭd?w 桝u6s{ڞKdLB]C/]>9􀼤zMf^[猰VFz`w̵㘞кuHKWنawyM{2V$:`sWd#<Z9`a.^,x(!JSy- f P<]t/pY=\҆*o}zeiY;\=\V+2Wh2(ZrkڛeЙUꈼQ%$; /`3Qtq|#j:E(\ MUP <8 Ws&seVn%'t![ v+Gw]5͌EPśP;Љ̵:t{p}wPUG0qk9y[ MʖDzNdXFVh5OuwxM= \&v7'z%kF36̐\ZʎW \f-,>e#īyIڙjZLU[oU 2;tsZ+Tǎ_W 2WX3}T@n_\F!ycy&|`=ѹsF #Z'vM4e*#@6|C5A QJo`3yF>WvS!%gq`ޖ=9Sh:Y8d};{$$aQaO0l.]-":]-(~H!*Eg=I|CE1E#` oTrL|CFˋ{GXS5ժph,.Dє@<0V_\} һG>Js>'DwuƱv~KG;;RĬ}Q D [: 0) Ure̷tDeuȿpذ:o"z2֏ihj)6VD}͘(7u0gXohe-QM .9̕jț:Zf>-!2&~0L&7uD{7!Ew &: D*#]ɼE{9VREC],#SDywDΘ P_[T_5m{gAFTry±9B4ĝ\ZEhulA Vz~^ }SQWC#r1228{V!ҳK)͊>ruw4R!`B?nb \trL޳=?GX YgPFe~Y: {g\u#tSU %@ZϒT ũweB$RzEC{1}Kߐ}-UI9R[CZ; :'cb-$YLwnЉG,n3.+hݥmͥ{gr:m|s>z̪--졮xel '0T[^Ou;fa-%iC+Gk jL|>$W;|;1රZ HhO:3Ӧ," ]x4`+w\&kb/̳tH` !w=)6Z1USyBSLfSxʾz}c1遰XRX(v߯|)ĹUNu;Up©sAVMNu;CT Hzx{1-|RL*jS JE5$Tc uF4f9T_e wUA AUR SU]@P'c(CـTEbnФkG)C݂tQG7ULP,ڷtۗrPG2Q,z"I}1l@ZR Κ;U7jgT$1 ؎wze3(HO(J]j8íz1kwh>BG{gEwU9 w"O1 WgE;>G9D :glDw4yu/?iis@c=ZI=)Deu3&dsx\1\R=E&}:RQC$9` z >uXT-9Q,|wjD8yd$d. (bQ摒wz^PY#ܢʩq'S鋡];r RbC ,yRTc&hk _ѽ 5&SyU | !(EP4lVC˄C Mo]pNQlz4PGch!wHGzKd[iIu;J:z4NW;VT1,| =prt,%Jq#<6q;1Ӡk8O)ƚSjtĩ;z_(I槺vSpFᇁk}GhSq8ԩLhYDقԔ_ A!;Y8ԭL#ŚQ\ N/ƨoIpƼQsEbb쭅Vn3,sMD4&tJD`zysq(4/M!bBWC1DLwLχ(ZLKyqf'G\l A Yr1OTA/,(h1*Ndu;faCFB䴦!Wч p[t#'\Ő8 RHm&:3Gi#Wh$ct0t٧?PFZ{0t1^B1 n3t(.%t`  쇷FA8VlZ8ԃ8.5%>9&d}/h$C*,s ;udejнIhQ\CJVR0)L=AAڬEVpqI( q=1Up1E =Y4q8'c(Q|ʂ'p/][&vL h I͟`q:Gc+k\S\[ x4!Xt+O*vsյ0МGq$mŎ}j*Qo`Xu8*8Ŏy!w Ȯyq|tcdQr0sEӹ/?8Ԩ%ZߞCUCzy:Ōs8WG䣚׶ N\h> kqУ>KBTrgpcYLt/ m ʰXIqn aaR4+MooRWlnHF"Kfk׽Gq!v-u y9{8+Zc>gLN*ȅʊXdWbs%6$h02Gj8W2mxé՝Bhl2%IyD ${aqWq2sbUƧŪZmu\+ҌAܫ8WC5ɏ&)xdoJ5*nt Y!wE+5;g\:N≟4m!3Fġf5VG4Dm!#+W4Nƶڶ̶}V/Lԋ pO .!}IerϲWy8OU8CϨBű.um!>d/d z@RYrٰ9\=+qxEԚB?2KnDpTT=pO:dr 9e4e%+*8vCB衦{p`[0v=_^C.L= .+5Zn{6ZGj+Sܾ|16\6RS!>j.e2+>T!7>fr,_K!wnI٪Q9\hQ.Ay &e)[e~)r{ŇCu)(&RllrГ k+Ldt@P8|o8ߕq?._vϛГg:W<\TWn! ɕ)eJ:Ql(i#kð|;q"ZnzǛCf=GB4]S |*uKNq]=7vhA zC)UorȊTr)۠M#_oׁrxҎ(.8 `k ~b:dr8f.;~&#G0ԑ@A_6~!72:6A6?q9 ?l0ΗCfښ֖XS܀A-:W覆W\K!\@/T(Q vmw+.̜aMNƜAs%Ovȼdյem@k~=WDªۧ ^q9d)TX({VNiy$ /YGfgB< ~|#}{rsʅt5r+uqqOL. N]|q4\MA7vm|#~{2.&8*rT((qu|~{Q K9ϣGG7n5qȶ\/y~hwWu!w2,e ㏟Y?Pq?,(^AOi< W{lr!xNض!`}qˆEp"A47̝ 틗|{Ž. Ck[zFψ<ڷ"W{|Gv=MـIlW6m"΁ }?"kBW o:^1V5j`qup03[gFnm|k\cU{!+%%㼎=#2[2o:?ZV_j9\h~Kgg,\ǵ/=8=湝]/ݚANr /jM7TUM5"TSP~nr wKSVTdXvo؎dHXȯ\y0Tei3~Gle\_r DpmmkYv9Dy%uD1FJ2:L@ ^hbҎ+e+5,,iUrƤ$=%]J3sIK[٭פO!v^샵1fh 2c)f.\2iG-Ȃ jGlwfI;2lo~ddӧ>[& s٤Ȭ6{ukj9fҎEY<*p<yO)s}Kv\3iGǖfM1ڎxfvRkӗ/ /iΐ-ZHkl`-ږO/ʈ!y"I nmWX ץWo |&D^YL7L?=='Sn%&0W#Xhi|~c5i5H [& 3 y ĬI;Ov);ŀ~og(-M',A욼,twyJb#RmvH Rȵ S _į1.dMqvLa!rifb;7UrݤcFMu.Ap-ASf-M"wp)LM칾BD}vIt*0H6Tz{I;I  5-3FReZ.3d/sy.F23D8mmk9qN wIR/Ng[yCVĶnHm<+ӕ?R˥v#gcnb&kƷJNظ}IfmdcjuҎIHdkٲB}|O;i)!;r١ɵk&`{V˵vȋ+L$Vj qJΝgȧLg9,wCl]ɽvObnѳ9 68y3'xKa9cKT^9v"Z.['mfa H0l{Oɓveۄ9KڜOǾiu-7OYxSɎf6Oa[Az% i9z>`[ȥco> bMEWr}ޜD[u/jƒ| +9{ҎJ:D{e4+j6nr}6IvV\A'sG'%:-H9& nb\>i{y#8>ߜDvҠ`C>b] >32#濳gHhrf&{{5do+N)-iH*SdY,r4]X6H ܲ+_af(˖Sr=C&=c[2^$㰄@ 9"dy9S&[>-;J;s9\1b"B "J (ȭ9YTWY3D)+ߏZNzw۶Kf!S=6r!+c֖]J.b1eh9΋%83"IX)沦[j>+- +g"~0ݓΐZΠ3dG.GvI3sʞ ?->ϐu9֠Wy"Ie-Pڙ5 MLgl^)hR%vLB`XQR)v^~YB:|298vnpBi' ꈉsͺ=r 4( r6큵VwlCjh/:Q5v쭍 wcgdL4סlFs(=6Ic\"jzKnJ;+{;!b&j{{,5OgHU{l@%!rk\Di> sƨV/QIv`7DAx5ehҎHL": M{RQItk%lfeUY4S7Ҟ16vx̦ژ-3_S yj΢3!Bu{c^֦([H HjnPw硽#?w )9Ҏ4ރͦ=ߡ[{Z.#I픦HS{'Dpwj9Ҏoi'8VycK 6i5Ps}fՐ"9-f"dǵ.6掩8J;{:خ'Ą"iHo(dHUDxj4=O-ߓ5QٟkE!BWB#Cq!Ts}PaOh,j1xdHigݲ /Р+SyZ.kuVBX4~ĉV6Vɉv:یf;vQ7:-7RyNz+4ܚVfe#~~4gz/Ӟvf@Pu.3JJ;~cb(Oj܃ nVZΤ3ōK+$rwPڔ n6BKSɱɫP)Շ}`<޳nB1Af<4t@K*+o>-RYȝu}]jj3,c E3i̼wLiudx2hla1\Lig>dllCР]VI5wh9ҎGL׬ _c\Bdyw>Lig Ur2T^ݶKjO|.5 HzYZ.Qa3L$ ɽf;)}::e݄o2vMigr}33ؚ& ت/~ = 6hm3DB<[vs$VzBzT،ptwr:]mRb&:ė\3\" WNiϘg_#R"T}y@Z IG3mY=2,tzJ{ sUkHnXDyTr>1!IHNԃ[H\=uo/ҎO@ p̻x4Ĵ*3ji4d~z\s&NF j_J;C[X2OsX>Z5ۀ#? ed $pMˁv &R8U;`bW'hΘHz$Y7<8)/IÏ?zϞ Pn1 N;DHE&4zWiGux=lC[aLշZGZ i:KK+w~SI =:@Z Obrlr3b!sfdKz[fDL㧷7_fko(af;#q8rTO?bZu+L\ZhĄu[xɓr >Zp|OS̿&O<ް"+urUg2bů㿫Ą>c"rxVp,K%];~?MX)!"Kqܷ_z L o46S燌3bB2<Riޭvxo멿'Yrی 9-3$dI__zPj>?zW:G)o|߭1g:HٵƐ1<\tKmB1coAa 7sVĄ1=dgC=tϦ; }̖J ڀuP#% }aj}B!3Ʈa 5aOvS'_/z-6#r?Za5H^Z_=ͻn~ =1~GѸs񶭆ǰ?УgQ_DjvU;~z?d~<;쑝``{Z~ }L ^'i ,D\z/ =z(L7) Bb|w? =J"]xV_kW1OJ`\ki.ĖZV/+uC8f(E2b(1{D9PEJ~\^<ǡݚ@酂!Vm0xMЕg਍Xm#JM+ZF5!hۡW-Cƣ\B[Q̙;'57'=@5&OG0KɠEjgCC5e|]]{!b%QL7Nxʧ>կHF{Β{ 3(n1y̧>r}<-S6α(1hˡSE5I 7yΧ>ǡ׻͂3`x43kqps>>]{E@NTL%H{$yΧ>ǡf^XxXZm!yΧ>ǡvJRܹV#&.筐O}4:t5 > $E)u] >ЕT AIq3\O}4:th'ijhn։|ѡ+'t_(^pչ>Ҏ[vl]8Z.SZ1u2@AYk)YPyç>l V)2'PJq͈yO}4{I1 &htF$ȶ=D^vl! m.2'~kF7lw[V^vn'ͬK_6 ߰E(hS'u]|sGt9 &'1q jw|꣥ouTKYoC0Y"໩H3 ;;>d:YTh?5wYvjzc˞+=\h_ *Տ4#vp{Q6b8: V3%*FD%xmx ^%ruqH}7O>!*'k.zk)lx%1B c֮jX(*N-捘x$xl}D:iehUq{7="^#we$xa5NOI}׈\PP#xzxuFWX73PC1!3fVh~^c%jK~p U~EX\̪NKijD.0X.Ie%ZI痈g 4 $sw^jfDŽ0'2,ܧ]f,s!&p1D zBGm+W9K3NXOc|6 _i,K׭Js~+͐)*B;#l4C\ٌ;b$̫c€"'jhfDF?@t- A8Z3\ՃߣOY%B0[dhd_k+83-=f0Y% F yِ;- Mqs;_-e*HP Y] of9X@˥E4X>bZWXC--{5abAв,nͼ"6!u0}=mf-'_cϾ=0!U *r1Ƈ|qA2X>"jC#XV#@K]}٫Ex*) %WŗrB 7ZbO;\oDx)'4ZBY'1NX"Z(В"pGOʾE6XRL7Z@ՙqL?fa=Lj/+Ep4t3c-!1EUdBO!D?w~gZGWFvkCx2 d_*h-#kq`N 8$_U~}qM4nUoP5UeZ&Ta%_]յ" e7ngٻU+~Ebݹ T$cܰoDhˍrS]"agو??-TJz%_n5G"= hc(<>MlH| ׁU&Z`{khɈ*0 j%|w_[@Xٽ7 _t}a-+.f|ag+2=/[%|-xHvh-/Qb`Rnszh-LH蘚;lo %V \ON^1x+Z2W4i*#ubePwZ@KTyKiFU֓l3:{+:p"`6tCO:@Kb2 JT&M?;,Qn䡲"_Qx8}s4w`o@P䀀> YN5:5W=2qqF_`-W'xbQϵ-r;πH+"cQ^/9N^UE3}9_?πuXcKVH+λymt 1s#_Ǯ8]Vt5?/kyGAoo{{TضEYn׷Zx2߭4Q>F${rAKȍNU(ԳJ3J{rKOXVf,;ai&F}~2R7޷]Gw"f^N2Q㉊%R7⍾i^EԴqn7S'/;(%Uf磼S,,Y]gE8vPýunj//rH)uc|e25ssa7w;(ҩ"b{/ja2GaTúBU%:];xj ज़8X'cΙ T"Fxbh$A\Hp m\;{ϝtmnvtC56#ˑʎոUYL%B*"Dq7:w[w xٕ܁͡;IgU #%u> xyyA?^히Ԅ%^SSC!Ƶr #l-e7G|n+J3?X}eˊ!XU2te xIj2".PQX˕ۍh v cur-fJ+A.լ.ԲCT1 e֡J;+j˫%mI}k%04ף1OXˣDlpR׊jGM0RR/XYwҡݳ^EnC)q>>ֽ"- x8%+ e3Bdjf xՆ߈J/)&{9 xpjNn}Cb e-kB+c7'. {G8#U;aj-.=^tEb9tϴ ?p)xĚ:d]{8@N:%1yJH),९3ڗRC)KH_Oa xYZl25SB '/Y˫f7jT];0sβN+n;tkx=sB&^1q_WX̳wG0FC72!B<;SU{QTGp!ylm5[X4k_`Hӽ͵:r\^.q.wd/IՍ"?q(Vx}H H(  eoMgٜGPxy^3!yꈃ̊gk%f/B_rQ~:F۟ D-eyQURK>7W{ͷqH[uf1NnF WL.=ߦznoHM.y$K2bwDxR_ *R%5ubZ0XKe{өQfҫ/ֱp#uP]tkg/5P"-) Ec2#^T.i:2^I)& cxM.lk|zAOcMt.I|ψ=-K9OL쪈83TuqO $l*iezZFUJىyIFVq_Ej/<)͙T ,#Wza/_U؋lE/܍l/knXW\<'JmrTd{Hٹ!`h 7z?:5\} Nu^VG:sE_,4yKW"OyxPE\,%:O4_ndaQ# %%4i%XִAi._-eB';7D;{ i/gC_`7ic i/obfzӷ*>yE~oHx9#f= R@uvƈ\w-"xYKv5 4-VqحruXӯ+Lh2*!JS~JxYuOQ ʩ̪ Y \1f^qO-2ߍ,#㊂M}-$S#m.ASdlH)mwQE@G.}ǮDjZw^w(%neAD'7 l1 el[C̈́CLe!H7Op9KWeg!+*Kx#M ̺ 'Җ{q*K $οc lv, vdnS{DKc읺L$ Um6^B+`][~L| Z̨6dk|x )/ ^6Y)Z|z>Xhsl:)^A~,2_<غ@ C悩8dxaKgek2QH$PR`=9PKQ$n2*-  Readme.txtMN0׉;K.ʦDVN(dqƸ#6d­b8%8j(]kb_=AcoBH= }w;k^OfEfVf^?FB'aQ}22A:7OrAIIIާ= > j Ui.չG:[ȩPK&;b'̉ katmct.pdf̽eP\ϻ6;\2kpw H`݃[@>=Sus{^VU|͠!#K d۟]a SsSY:0@\*6vT=bo8rw8̱HHK}Kp..:aIKrE`D:Tuɵ$F'Ca٪I8׸o? o'*%gj$y?:;^}0S֚5i|ObF:MQNUET~cbX7maMm"ȶz:Q^IAd:]ۄ\ ]ÂI&x|l)V0iȐ)GB38/(r$IjkȂ:>8D0=D5[k{2Up 푇Ykekذ&(~^NRAnIxXqM}^2e: g?* *LQƥQtUp"*3$+؃~밎:3~IcmqP7HrS:)DR ct5Uo[Q ",O[ 0?N:~je%PG⪻f-J)!iF:ƤҟE.4F?=KL`0' E-aބlK߲FЌ4$ )vh̥$$O畍ƪCFl||)?=uEzy =)re4Q!+3Rd'㨛_TԱeJVpL|H&z;tXt6zoZ V\X/{ARVIjDjvl<Wj' ij?ΰ׿ֿG||=L݆K柂75iZ6^n>V6^TퟺqS [y#9. O7+moj埗xQ  _r#ǦL0v/ 0!z|p(0¼?+9 9Ef #v[vG 9EPQHѡSEj9Of& Hr̐$V9*{ՑLb1=!8D.r:^]ycѰ_l@qS Eqpds ) Y &H/(xFa@-yɦ~Ù\Z6|kkTkz&I(_&h#]ukZ2qߤy6a/>lQ\{!0` BNa> Ka.L,攄3eDc1F;)͑5@ZfHYȓ P0,=A:Xaմ6F*NNQ(/ȕpKBHFQ PCP:")JcbHU*9GU1.&` NXHtvH|Jm\چ2Z6 $oLW*dFR#XAku_ҺE[B[MF6z=qhyFHSMQĶW[dL` ɇ.eGm8_B6Rʹc{q,^@EMLfA0?Jjh9_\犤?G~IE9rLH:eB'R\IpJH:QVb_sj}6n۫:]{.vꅆcT/ )"mЬ*Զbbs#}Ep2ԡ@Ջ[-(W*tE\WیkֵEz F3&L%w~b\ufϕ}2"n)[q2X皜3RўvJL!o%rƙ8g OٮA, Lon D$)(t V?g'XH 0g(-9@'-E|9g܅ h2iT^uE#g+g1Z 9DG#v w%!5iLQn;hrd%L.0R"Kv` GB|MJ&D,1fTMVnʸe}dN5S!RnrWitk`H)Al.(K1)%M#/[>Y0saL?E9REf$8unmpRtq/CvDZ,l%nR"wnȥw7憽K V6.\H,'S Vj:hmtr/ADލD.{W:=s (o(?bL$e>˩j\nh<}e(wЏG'HsP\-VeQѰz @^?< 7)*@TK\Skk<7ArӗvT","XZ":HcBCz !njh:[֟Mԝq8_mU=FUa㶽LsPrm žF[ o`ςl:*V^o:{wn8UWFϖhy,$;uq^Uޑ>Q6VNR9USGթz) e|;2j >?+Vw>TӟG3h*tN"MH=Sޑ'00wQCEϴeeVnXyU;#3sM7:z+3K\\Oy:v D ePeIiyxHbaVsּ@0{55)  H҂Qd* 93p9IF<۝HG;{R9!;PtT)j&t];RT߼39?Ⅽl<63#؛!+(kl*-ioe-M'*~'8W~#C~]$k..!G^SX!,5@dF劥kجܚܜ|s'IjDc2Sr»N.WIc)J `e. 1&s1եPRXsZV-k%fm Kj,7L֪Nјr FI)Zaj=PGEy{0eb#3fҒ?DLk] {_2&XXi$ҚpUghmdT3'`H`FSJLLVl,QE!F9|;-kYc K~SV+V37o HM0[̤uw& (xs et[ĺ r0ƷYkK҆RQ:e%H-vIM{kB.%ֆ_俥T9Wf䩚$jIh֖|y$!kkTI40u86t%V;+x*>Z7]'4tk İ.IuxDg{۫ɫޞ=u/Z?Ա-D 8GQIP\|^d[)o5U8n>;?~v-/Į42e*uj[)v1ζ3Xg8.YIl/oʕZts]E[+L>Eٔ;G苔#Jjpfrܴq`R0i ȠPQImuK䔀f~(qj)@&i7:2w1hH\;&?(:Yc=4^3h3Ski~W^K-0ka5HE_iVJ{R xp9;DfkW¤q vea> )mtMB\jPܠj5z 閩&6*ya]m9<" 8qbI0d׏lX-ӆw7?a! U s2qXU2nزZ*,iui]QMnz}ʠDoM(ө`o<(Ny/Ӻ.7L>ǾN{1>e7uOP D}OoQ&+ܽx|ulJmݘ79&lMq:.1Z B(~]E=*_[wO^o}"޶=q̒me]BHm~=&r{Jj{s^=}/ԶQ=r q"X Lw9xBf,*֙{Ж$zEpTl[@ф: +e֖g>|.rrhbKuj &B,NeqH]m:[p>DݳqOw9.$J?5޸$d ̗Z5QCyv!(Zs/>3*ZcƓx8U&gT! 'AF+wncvj L?C.wΔ꟤D9f4eecpȓcǘ&G"2$2WUes׌[%~@g1h4Goa= *NpF ciꨆ4VtJsݼ A5C[#m?aNcX9L)# t+_tn(CoŢJQ|#4I!ZJ l1+tg q̭1#V'9vܘ'K9Y+L9FqF<7 Q]P0g$a, 8SⱎԚw M|ks6u͎HMGMҎIIkuh;//3S,#2쪁F322&Z l/K*i[X/>`og3+ǯA:iQ|>dNZo ͷrbEHYWG3 Xy- ģ:A-5/hlqlS( E,M0y2|A">>Fpi@<@ے3 3#xN cʡ<_(sg(,z1qd@pgG)qw` ۜT8iӡ`F MIlcdVE>Cu5T4THLz(NdB~UQ}4/FM8ϸoIIEbOlݏU޻"mR+SI|hDРvzOBH(qcop/;㉧HEDH: i1&sm ޠt*ط :5BR;'a'㪀{;o['7JMjآR=5މp)`vzX溜+h\2KqGQ"Eۃh=^Qz I\w^X׊΅`_o(E7V&Ȁؘ?U2addzRJ"_O7q*]5}A䞄3E1ߘf>.d<8.g[|S_nRF[Wޗv5J~q޼o6il!Oams(z&*ǺQ|O\))YzJ\ nxx'-yK+zmkLm ?]GrD {[x R1| ϔf[D,>|2|(-V7%p_%+TfNZ 'w&Q\AKSMF6`1tJyS20(1|JaBZ.MgC/TDjg-NwO,tÚ*tz}\NCz}"鷜osagx<wTVd9D`u?tY4Ii;+tHkQS%` @&WFZ]nAΟ^wAg)V#+']FkW../]q&K{K:[-q :] 3_՟U>/F<% /"VU?>59f#W5r3^}>D|AmB[`3Sqٽ2XvMHZ}mFWH?Va"dYluOYf~wAe`QQֲ[ue?!mSb.u;t (p^~&쁽 8ETftZ"7G|yOq4!h}S/DM91U]U;q랒|[]%Ơ]/a$u Qbdׂ/NPOc-[m]~5MtӡqfY Oz4MR|;"3Qv7MZW4mo4QN0}Ν$N-}l2zh>lU/T0Ѡ۔, @a&b{婽ЇDh "Y%ڷ3 C |'eAV-?VL"@omȴ$}jm?}|t~4o>>GhGiw[YGɢ\Li?6FGuG%3'W[>yqE+2$?jۺ2&B NӭdЪϔsBoP~X>ю_9qLJ/=8a5ݰ/МjUQ/ҏ$lzGJl}w@'ؾ眅` YcHEjQe/ܰ|%u~PUUM)u\5X’޲(q~…E.mvT6uyw*&hޚѦȚdbGK8R{Dif $NԩQL m޸%\xu&4tj ڵ[;,'~խ6f6ptd:o zr@ }U[L|̄)F7zӏ(hn`]I%=<~t u]d"oQJѿh*PlxTmb3(cg\%%õ@MUw9jVQ̾9y'k@t=k#pN9J+H!!zˌ$9Qqӑ۵G+݇ɧRׂț"|)/슨hJV^䳧dɎ/bsiYj{BypOe&M< ۧPPs+&x<*ow/^ࠟe!6e));c#rhys[GdeVf:$v@uYhT\Ilҏ_Fm= ͿhvxbkI"=Q~ZkKKoq1c#5~ :oCEy{# &p+dYXk'eN1N;iRS0TB$ ts%!Թ;do_,4Z#YgbY-MF+reyʏiVC)t[b{¨g woĎ'ᘼ*L9_bި30wV\RLJ,$LjbH{)pW+s4Rez'kX>2ReԬU(um)+MsMʑ!tF3^`RQV]9)v'$UE^ժOEnOhx0A-5-^[L xGu6&HPPaOśٲůߝ\=82|~vX@wjTbdq@^3"TwF->ρo֩@QOM]L)&h־Bw^DM7;SAIH%C^oMJ0K5q65V4UFi?I56~JNe.;\43!f. r!6b\ PTuPDj1D!?3j;րA[a>-lLod}ojLc"LV#g2v@:`9=\FU'YtCݾ cBݥ[mlYI[٥YJXR"p[\@VBF8EpP[4 KeN0iB&*3X^hR9.򕿝LLZ\Qh+i+jҦ oauQRvV <<9{+uJIsB1GK-B m25Z%*tB&!Ы*Z+Le͒8͚LxjxYfSԒ|zcUVMqגMvoPb#嫌ZlTz%&=Kj}kbhh,tF= | %P}w95V z$L;}y` P,IfkXiVIH)Uo6wPvR>Ti,̓π{ԋyTI7ԖՊ 7gd)!SafY:-f`=4淗LBѫ(c/.Ds[8dPhrP !,w璋aZofZEqZX,Zj[k >).y, h;G< VU h%mfi, ȋ/mAL -JB<'>tQ[ h$f- +f]mZ Qd 1.+: Oy q(T㓧]`paO0ߥIAMs o9d"o"RyQM=͔-] )0UCBu\3:neOD uc)ᓺAUӕedo˅k{$}J *9r|9({{R6 }f A*=Aƪ. *Ub ;T;9zb&D?nbWt,=AdzFOb^Ӗ4#ژ N4W l~˝Vam45V2yER4e\RͮMK+rd;.;;;\ _@Nў06_u:9pu^n{[kqvji]Z*Kՙ~SlE0 \T3#5Cϖk@r7eU-mwe-LvJYVhw;Ml,0,Cfx>YX>Y` 외ˉ@vҚv MZeM'8e--d&[){yKITnI A}h(c 1Ȕ36XhH60Q BrxAIe<$bfnAe>u.u1} Iw3UJ׼}yaZj?K,E9 w 8A{qE6XzIuEwt9OsFKZRK [U-7m"%>cg/ eQGNE8eKEev Ir2 _Wڤ|8{2>2!9[ pw\H-Hrj;8|iwޭ_*m-8]<\ܟqWW9KBW2DcϽ9]Myw].FD<q~"Z>翱mixGd/A|{%WϺGUq0lQ<+vŻ]f6i ׏w&̩4Wf]3{mzmїgmzg_]R/=z#1%g3WYyO953?W~̘~\]fnʋ)|AE=ZgwScf]ݩݾaݡSϼ?D~K89Mݲ>w~I,}`-/\oHSrd|dA?1L @TAIp( 10-Gl#{c$)2,So۱%U$4W"DRMT6f-)OW17zẖCn& Vya$:1};~0dLo9[G٠m=͙{uhMTLnk?6jfZ? uZOI]1f}=4ώ}j\vy}'_v @H޾-![c|:#~t5PפN(zv^ {51RyorJIڟ}(¹d{N\ ƿ`a$CbGf%Ij?d2{`E--k_2}N|mLamʍn+8Iv\˵ӑE]pݎ/#s{ Ivj-Z8 էڟ”>7EBcpHTԤ&NPh%\E7+h1&{ [ׄϟRT'0RL6% - cDg6sF=1Y$+塱*Sc+^K񜲼_r| T\p+gÆ+v|[YOGD8&f#Ѯ:f .7ym;cos܀}-Sa/^Ig xunpQC+mnӯ6F,=?g L ;85g0qlke ϩOW3Xrl@+| EʼڢvZԅ7I)TۨaYTW:VYo6,dZeQK9cc [٧e>d~ _" m-e++e;_ڮ.so;^]ڰ_Nsn1 |w[b=>?g 0>f90zCCvrt}GZɫLkֺث9hsIy lBDlU֡Y˵:? =YYA.?)S{X>~@\kx~r1#3;[(m[݁n()߹`ܐz@Ȟym,,T'-I_:^ۨ\Z#oϧ2O7nA:(_#ۺgsխ},O=oAϛO:1j v>K2[k/ׯfgtD?pH 7J !blE?HhOCL E,JLJ>j4*1{~e "Xع# ʬ>P=1'>XQUQ_~=KC ;>r  >3Tā1PwUY5\h7a V K1K̄\6=*ݒĀs|'7IZ(˚A_5햟MNM4 Y6QXGzgIbg:b\d,.bu9OjVR)GD99V4INCL]| ILӧ9񅢆u-e4孻2Pd= Ic&c"'v.;'tu7< 粌ߙ.eN>>8r%[>4q{:67p7\:r㫕;Zژ"Ȼ+P&LфߔULaMY^#(oDbE>krqo |Ab3m* jK*Ut@4imn*hbooj9G* .+qN  Je?-6R& 0$q%{f%KUQǎffo‰2u"οGeoNew$ȧt,[CrFY}1·Duޕe5L]So'֔'?abHĪ*㫜gߩNUH5WxW.P5ɈIKQьSUv-NQHRInQpN}%##x%ne]u(?ʫLw@GaWj*(>'Ugj/jHgW"0JZR2ႨcOJh4qcrdqgg*~*ǫ s/#)&5Uz+oDcn cAڪXi<*V0-Q|^m*CѸ([Xn?ۦƜb, 8G^t^r[?=:=q[㛥b#o;7㩊_4(v+p)1_9䰨:0qӓ⳱v׶ J򖪷2wlegIb6!" / W.y[o.oڈ^>oĎ|*ޗWR#zzWϗدF7Bw0_&Mi!@?^[W,߷v _%@%IToRAm&->KIz#+?IP+XC KOAafs &~2'(ҏb#TMю!ىdjBgbU\2"ax)XFy!4  vlㅖv$K:E,EPeV pe89֙ͧ&<GFY.(n"6?,t >MUZo55#Hff}U7ˢ˯%TAVw&JM+Adv} e/"ׅ^|^1Qqb+TY(䔍%e;ᘡ~_$QQуPwQt -zj v bQ_x)n u VcO(W-ix(Z;PT8z`쌙큌(a]Դ<3T$X';3㵥 ;UV={}к]Ybtl9` B8(xh! gPQ`PV3F60x+킖a`蔳T񞾔ޮ` ŽbP[Bh~CD @P?v pA1X)DP(Uzৎ7P)D}pm>IPO@(9s瓛4Д|(Pʰ]:e7槞1s M-ٛ_=be_-CʛRGLdoz~ P"Pc&~m@π;=@U66tqVwgWxN vdP fnH(eIHZ4VrR/k`B=ꠌvAmn_ʫhbl+عK̿,5);2ojg$APl)oԒf>Mv"xR$z}7Qؓ[=hyӣ;$iGӖ]s4 # F|_&TysSm-o\OCA;ӛݮlv$1suwr셜]![C(;fĿmu ~hʶ N{arETfLzG KO t{q\ pk _ qCЊ؆wɟ|[h9$!j,HQ$]yRcdTjD Mf]PLZxڂ/θȒ()ƍc&BAStΝ{ $w-^8mZVCw7gk1-R76(\՛.[689ܟr&6? Ro0Ӳ)%#:֫b|GvKr)|l ON 0}D.e_Ľ v®ŒAN._/Hӵn̍nTB&+P-V ʞ6 $" (dO^@{..`~QQ^rj/6"@nQ/d('{Ԫ6RhG"RL;.9YΚZ9^CP4$9CiO,V',O_Q)*lyhd s=MY$\ yh@y X_0]Q yJ66Ϙ,H.(h,0?w="=-|WQ1RI[h03AkYl-nF5._v &3]u4.nf-nZR.9.Z դ&*ٷ |!U o,y6g ^_1$#{䷻ <`)KiU?tNY&sR &&;p㙜HM3'WԾ3&5@'?V3ţd+-1kL#%#t y "gW؅ʛ ;2I37\yX.zLk P->'*NˉdAϏܻ9d4/-+LyHo`-:pD4uՒ0IG,VF4@b=ڏ7LbM1nAo >[x}+(qd]!pq"v{ub17hCaL#U{Frx0YY2P 6Z ;.x# P֩ ]"@@aXdExY$0n9H- yG8gDS.˵AWVϒwozB;)(!Y_ P =Ř6[̖aGQJ 9jtNK8LQL=yn׌}4V6]n/'&`dN_Q5]3>HQc3 )"_:laD=+{BQу,gY~l PO_|j3lߛ9kC+l"+k{%>-,Jo0OHncyn[٬M[ n\2m,Yff4:KsM(ɴnU gĽ̬g; ?h`#G(.+ض~ "cq,hsb''QUNDq%W{\tq5~.Oժ"3a~W֎^ofzKUL.}^VD%y>jL`9Ӏ|sdd)7["=c^*/eEлooRvT8e tuƺ2Pꭆ7v[|5"TyU # xfIR^eMH:%=tj! b_P-R6ׇGG tΚǟq`PoXp,@Ǜ#S߱QKzYnX|4ϾKbG3kK [YOZl\yG7'uRf* u* xn9J$BèvTKUN$*чdy+N\p'tC9/ =[ã\-*%IiUaDx-]xĕ_ Ҵ`vAO3di%qZ{qJ(.d'xAZFW@{jExgc"7}uӬT\(]W0cg~d;-Nz̓=XFܪ͍_m-/́Qz["$۸Q޶@#rH\*g96'Väw^xh[ZL[]%Ɔj@ua'e={>6n"Sw{I{ 0gv,c7: a-@":4?lk܉8VpԃhRprr`;NK 1OV"ǴMCò:1`sk{z~ܘٗ1>6Ula]c6y¹0c% ԞX\rq?sU#-0v38,Ʉ vY ?V\CkIE.8X ?\޹0i.'oHјA3΋r!5GPe^jd\2 v@76kBV\ᢇJq"]0F%,04Pvҝk؆jDuyb\"9C>C!Ʌ?U 9,Q?O69 Gv'y8{?GJ}caGeXE5Lʑĵ ] D#LbkJݠԩv{Xb?me~ƆLPꊢUhh(SGLn]'efRl6;lЋv},h(@58Y 'Sz?n.95//589 ?hpyf)z0n$^ƈ3+#j}E?jY/Cf ?E'NXAAG %>JEl@ /AtĠKJWpmÊxqb.pQ`+~EAVX+Mykk8'nޜMVvH^<&pQfLEecrPZM?6>2Et!T&Z,FÓV!jBs\cvH" ) 5;Npop6ǻY ܭ*!$d+(6yDE tb[bNJ,4[CEªK1R†΀j(} y4]7ìYMI``mIzU#)AsB7K|$LduLrF*CG[=ƀRةV=r<뭨+ >**^U<_Y5F4gƌ,`΋a]K3s]4)^jʼYvFZ٥3w瀁;2\< Ĉ[vב>YL#KC+pnN]=ejٝTNPԲRJAeFHc"`: -Ҳ*b20m," N‘ 6ݡqW5XxXPRqcvLxWЅ E$bU-m%*\J [$UپltϦ]\~̡lDo7_UH^MӤܤ1 l ?G'r\PpdȗeJ]0 AԘsobY jBpd2cIKUg1S{W}cBnj|B?P]'3fV: zAx;{2R & x],H;¶[/^RG9#%x*G*9aV9~ D>ސ_+UtȉD 4FN.oϛIe qk#(!\pi%Oj3 wIcNE"lvC :fn#GXwIo'a!&pf<:dVJUphEk1mb;ݲ߾€a3W>z2^NB =wШɲƕbШ@eM$%XgTكc[ ~Z3F)MUiZ 9>Aİ.5 {<в߾vh͐!Y4Y}Rz x'G0-2 D0Z|4zXrO'r èX&=y@aRa(R H==H0"toYSލ$wSAL荣 Cq- x'fzYexx ѢݒfB!4lmChaY[(l4N]?L}R97_B6w_/jhoil1.Kjj;{\NG j3#@X"Ix+u'&r?4p{ty3mo 50I}jr,W\NءU2l{.̰yDqe_݁l2 n)k-qpOlAl[N*1p+euIt CtN{Hcr1》t\M(}y!>*'-!\ ҪeK<Ҵ5ve;ubR8*<hDdǥM';Ғ2hU4?]5lL82ɋ?Q @5QݮzP n"'X&eR+8b_* %1!o#Y\ zyٴW3jӌP+/vXYE,^Ɩp£H walu"F6wgvvTAMz@#-mOyWZ /$l+` . ='|?K`)v]ֆ ǗzځSY>yl[A)97kOڵ\ l'TiB+ m Wӽ# "³QܟUjFk>RӚmV-'ak#;}pf/HI?ZȶuXL hSO' gn)'AdM%Rǽә[Fmxmb/#ƹߢoS/JX &:ĭ a@s&k.ل|E,2Ρb$SpL5&ffp!pO=,ݼyH4<. %"\4SzрMG-25r§Ȩ;#vHXAnNVX,~pd&=@:!ҔVZu{䉰=DN6Vt$w7т6\vIUr4,$b1YCjQ1oV w`Y]n%u2"ݳ.qcX0UxFD^yw?T]1OU^ ,_(i+lEL"y] 7+ܧelÍY1Ēhj|(p\<9 LHxU4q&kU+\*i.RF'`FIU)-u?!9_Q #rٝ1?Ϲޓz 6=(.~$7n>9 ځ_1q v& EPPhhZ8$%YY+A6X< ȵlV)@UPK!&Ҵژ QJw(W@J'Jm+%=aR7oj| ~hdm@8&JʃX 1e$^%"aͮpJKczbx2 Lժ%yi-QkTRCr\ghk3/92WIr"▰Cvi$kJrLL9 O`YjMYE0AF': ˨#힋[S bZEV=x%\c2DbKQOLuz$({tGc۲-m7͠xb+n-ӕss|=l<$"rM3i V\xR+$KyUh)a,JLtVѼQ ")h| yu틙ӭNv)bY b]9I%cҕ=Sdy! Î/2;k7Y,Z?SĬpg^zUV0e!FMƕ5`ܓaAHϏřnNf;Z)jb |0c:3*˞QTA]l4'ckAc&\gS&>o4HswkSO~ a;[Ac)nHŽŠm Цsa^bz Ӱ wEt|Y W++zgÐ0:O p 9,6BۈeĊ@]fi".uGcrIzv A2mW!Y?ƙBu pΘHwT/'}}+PDŽj<@1j-OXY&qsWZ A(Ahk Y{MRC @K̹=:/X >/Ȅpa):?ɑ%HΪ>cSh,XVof \E=0?.`dfRp^}HAYȳ)v."x6E}U?{X bшl[ҾEGpPXqE)0,aaߪ^{ Sɻ6pU.DXV8L<0::J(D)|{Ve7Pm if7ɜ|qu+m6frg6۳Veb#1FpZ||(@ȐxNP9ٗF1:s%{ݍ.YyVN*f7: o#lh`2&ƽX'랺0VO<8cwՅY]̃ b> W#1\R_ 3Uh-(x5hnrjS[PbFɓ#UUU:{ r"?NƧUqQc!vK!3j}G|?cOrYP?u3#r8KBq-,K\WrpWR$RdXql7μcK& H@"SD$GO"^$yOQ[OR+ q%ǂ U0 ď7+N /ahxLxH{ԬwC`ؐxmw(Tdվ%\ȩo=CXhǒZqlɟ]S3}vb" AE$!L7@8D٭5<")D%^ 1%C@1Kt;KXu~}BRv'{ܔ6y]8> ۼǝǂ*,<"HzCǐ@xww@i@jț ?!һJZs{[j{W&!C#BiEX3`L&6TA`UM ީMm(Ɉ{vA }J.&z^٘!M/|MXt^jj5m-uHPH KCbA-V~ AUv‘.*L?M EFwDrG|+f- ݞ 9n!4OXzd_r(W2[7\zFUZCd(ah7"a1fn-rHtŢ*!kj|>uaH:(L5x($ GֿƠt^Z>sR]D{:ζK&ٳIS.I !^|-vHz3 u?~sx=aۥ_d>)ߑRMpqI 4˶Cbt;o olK)܍*ϼ +*9鏝 O)eh%M3x#Y_~D)2nRfG*@S"ejIvl~1~얄za~{\%$ZY{'#}0"Oq ~oS WE>8 U2`f+a,0d4=:4 D8tf͆z4);u 7LQ4͢ aI˂dPaKsLDTTrIDTr`1o@ssq4U=]5Z]RRB>.@=S ;CQњVG#eXmk2XpAn:38i!1QfNai}^ܐRSۂ )>9 }ܹd0eǩ7X4ea&N>ոh1)J*7ƴkc}8Q3F&m>7it->[C%:B*S4<Ǭ7Ig r#OBQTjZ~e\Mt.|9:S)iϽMq |Ff}Sq\΄칒B۷2S2 C)<.o$q,@v>`R쾇Ƀ[kh-rdyjb^큢MݶW>F{y>~38*H)nJ?Dbr1?K$,,Nznt* &%5QFÖAb̡ Wq] Ywy@7!t] d'íU<~51_k:2N%=z:<2d)BpYYzӵ$< SxD㣄M}CgeYljM G\q4;ZT[E&.򲯕vبEFW+ϨKghU3dM+=z0}raN۟ \KG[l/@8s^&FLk e(,YLDv}5~#xwWhPgnĬ &Vgg _~GD'aM7fXe} J݅ e[5{Xv<6~}}tW!Z**$ijZ.g,xMa?>0'Y]UNRl}vAA|We y/CQúOsfNއ!֡7W8du2]g@}mMsKm lC S'bۼ^>|IkK4M0AqUG=?v-K wOp]"??I_ k7$C{rnձiWOpE=ʿGtg?s$|!k滤e\xLʑ+|6KbTV C,س^iTMN,}Jԭ6osyQ5aJQOǡpSK!Y*]_|囁U,+.V&O>la}NB 5Cnu-nSɔ,in,A5D#,[>#a4}ܜݘW[\E.!`7s9=OPߔWA62l,ɥ 1ڨNz->2ƶu$"%7}S1I>g0rmxSɡ"JѾKQ'!$Q2 7ô]^Њ3}m(f`֋#>%6ef_x0qM&ObGjp-XBMv:|h'=0):L{WP֗%2=S>|eT/4 &n#g- 8rڷ\/BkWj&l5rC.<]hr2S}1 _y^P|)[loj) *)y륊c,N%" Cѵs8J)Osj#L3Rk:!썢:{/L2I֕9̳?ԨR/M/uA$Z:,M(^&8$gNDcrFJ`j!l,_YKqlD]2o+M-+G9{Y O益ܬ|+ T(*9JDU|DœIוw%`\4=݁L~eʨۣ`a=B<=; x:6|ek(3D033̭ rf/RT$G 푍6@?[{Vۏ𧟝k<sG>7^eɻwGR%܄8  US‹ެ'FO!夢}_&7ϕ7b)&wA1wFFbw=?}hws~W_(J)qE&TErk +c^VXR2x2pS2&d6'j˭GMT,hގ4 *7w=Ef_#v .LSa2w$|tϳoeb#Zk{LA MTEP|XQHzlMiY$W4+5FT^W|-M+>Q Ku_-ɈRFk4j\{~!wJJ!&slۀ0B't6gHܰm{X&"P"Wp9\[GEq5Դԫ(/h1ߙU$EF'*&. =V{JИ.Q!qvM<˅^zu~L@u~Gg7atT6T&UO3sg[bbIZ)L; i|tJ_sC&[m Ү*<\D ޓ1M3IW o=+6\V4q}&ln. }`Xt,g?+طj %’+t O5X2hk#JWEDeק7Ӽ/O2TY7սH؉OUtz1e:ܹcJ谮iwh9 :/]W|4dD'bB}0dG`;7a\v bwIycޒ>C>vf2,39'=^U^\܆h %5Sc V;6iAT<۩Vs͐r^~FWg]180Ǵ(!1 7ՇQh:qo!q΀⃇&)R?&\d>Ct_CD ~D=yt$q$&. (sRu~ˉPYŨoxHVJru=1=o*\F4:hsSS ZIʠ- ^Fi85K65ͫ;-N ;K=t-ևm %UEjg8њM{ff\` WbY-S!UC8ZXظ*ya5o|˗gwA-FÆy"Y#}5`^T=Vy4r-*p }BVNlңiDuY*X*vnľvahkׇVc1g/>}5ͬ:3V.nr:/]>D+b7%tb~𹱥msg_LMQQ\ KܮNaeC :mH6?w䶦2dqV ׺tFۓbl  Bv;DΡ)- Y|LQ`6OjzEz a94%"/}#Lf#lu#\XdnAF܌Pp'e0V")\-<'{U$mcZ+A 'glÃ}dydY\3U >^,rn9aٞ/[#r^d>C^0ͷꄄ+NlD܈k3ap $$v=,:|dܰ+MfjڕOH7t0ئkXEs6EO_4Vray9`Rˢ/εyLdž4u5V2_;T"!SGXyiEy#cW6/?@N/8 y&z#"MW}֢|_Lҥ\SaW%V 5G;z;%T X +OKXrhA<&s5Q^156T_yYΌ?yeTleEo/:%՟LcmZ&3]7ɌMLpo[\5FQQ=ebd:wNGGGc, .F*K}%Et\u/(E LJͅ/_Ԏ7+BY>3g\cDŽ -_E`  ٯFP3 C'. ͙m2~` X\R9_ME79{trJ7ce \a +iT=e[Nl$֓:a Yה MrD 9V yLJ\EN^zC۶f*%U+4k|.l\ $bt'})Ego,ٍH@}O]˻ +(-\P-*S]XzCΖT){3qwVrUQcv=j[z/0Yyˀ'k\Lb*VnK|SɽuDV+MHܵ %_nhW,<ط!D()}K9uw+*|T&R7x@6;nClޫBnNIeR}:d 5$ԃIDOS σ 5pi\{uZ JZYrNʷ]aEh5U%\fgQ3S/3vӆDnEHkgÉ՞`7 N=L`SeϼᶡvgApuF fv56J\I 0\@F!G<)qg)}|x}:a\̓|$,7ST|8^Xɹyv Vn{.<*fTjonhtZ3CY]s~{|x㩷Ǣ*uwN_5s C%4wJ-J`枀WPvBW)D끝p].loV)`qe6DLB3~{zJv7l9haً.]`8cp@Ʃ#Q36Ouo]JN;d'ۺ15[槍=vDA.{li8.H ||.:qˌS^O9U1e>W=Qiȭy7PU&ԕ(Vanj+0wEVE.[4=bCw>\ҙ0`qhRW2;lES_|CLN*HJ㣓Ҙ@C }71cn*v;)_óTС w4كkF9IIcp?.l:SvzQH}[+x>JZaϥ!>6q4ftΎb%4XOu'8s"#մN՗cTdM*hXs!跳$4G![=nw[Ǝ ͟#<)/(8RI`s YLzL+MՒu5T/˕H1;:D\B\c9&jԷ br>%s/1)U񥧧q />G X7 EZ>{+Dv2$]Wf OrWݮ#Σ,w߫MhUc=jj]s?/6d) >%FgTiWѻm[p[2)(|6LI۱R+ p+Lb@a/k ߋ-vQ /}g81Nntq|<ϮЅuY\S/}V|D3C+_XmEN&vca@xٽ|ӤoJS"KQIHڨu|3u.tW w :EARuEXdtW9i*SQ+>TRxt(~Riq"5OTr&'<{fW..5fI 2~8b?wy_s>$t2mq`#܂yZ?:vo39Ҿ>// LƁ}'6@j{ ]ۻyB].A n*۠kM,͉I윒A҉ly8INrLk'u/3qt:*wʟg$[ra^_}?t\wsu~-EM^P}X]'s2=~굨 %ZzBn:Oo<Nԁ}zB%N2ЩQ%41,c; ˹7ugkKo-8>"oHEǫ%FiO>}M=e'Visލ T7uopB,u…Fu-R$3EI}/&-6`POv5$Lz>mT2M#s1[YiaO._BV }mU9qydAx 9g{yۉ;ۣ@LD N80FoK?~_>"%FvԌȰ")ȹqQUa.Ѫ_$Am+ˎQ=\z!"ݷ`s!Xj$g{'+5(DLDZې4 lk|o?Ŗgox(>} 0ڜwp淦 KF;E019$NRm,۟f!EوN\:W7u}Ji,ޱ]nƔ*QKPRPfU}ǵAcHSsWl% l #j>LC-;]7Yj;$u2RMsJ8uӋ*+ 閏@Q"Nya 4Icb-ʧQU3$Kh> ;LJHm i_3L#L?dqls#Z~9!j0YۦRT0X a8$vTBd뚂X΢4:zզ' ףy hF:M=w *R0ԱIKwΝZX]KABQZQ$.*,1=i,;o"eF}1I.Q>()8:汜8޽u 񛱊ⓄtoE!r:UeyI^ܟko{'d&*}pnj\v5V1{8xL&8cSd^嫽||M/\]CK\ .y!'L>Uf9 ԾAYQKQs<,ÄcjN=76Ɣ䃏Z9SI[+6\2\hzq͜V τUlA$WnM͇'\&sv7)=@yWr)[r'"XI˩kF>._6&U)+,E3|ΰMGK=9zGj̹K2AG.X:09G0)ы7橹oX>WTG>zSABD܋; ~UGX=Nn`Qa['!*|L)**[&s!O8Hz7zPNX7#P퀚=J'9J4;ZGIi-n%\+jd)s}<ɚL`xSW)T5M34V)jo#8 %@^( yfJPx=Rɥ09-'^ynٶ́c.=x"qqmz%ifZu)yO)H7[xi +d"I$x1?7Y4-ܵ'jIS-L&_N(l{RS_m2' y29C;J;Sd|Ȳ\[8)ryz`D ӗpK5@B,#2hcf%jYQi4As`Wv@'_J\GAsܑ`/rˑIC:~wSv0V|al(JڹJ,1+Ykq=}÷\nH_ `aEDj+^!EWxp |>n~Tmve0s9x^TQ3l LYYp։qE=0oɻ1\&^=eNgV-z4Fnι2{'Ʌ|E/`V A'cVզ2cCWedH,THߺk.|hΌGq9?H=~j0tRM} Y.pT=3Q&S\M{*``Zufʂ!c۞ޢSmRom+ k%>& ^;G܎Y ;LQ~q}./T1"qK9Sސ\GH>Y{]eNUdѱu[t#e󭇉Tܡ]jC}vMB@Z%yzh+ԫGo^fjꗾ,Aa .$%聞!)N<"a-,z!n4U OBBJ>Xr`1<G.m/+B-4=zkʱLþX>cݢU0fndi3Q f\pʜcni*z ".F%G\'k kՈeR}|zbs*;2GJtm+Xɦ~f3_#kYWhIL#4$6[E܄ϣGtj7TO+.b?0Jߢ}Mq`fhGSw/gud8}8Z-"9"Cۈ  S>DO]tQ9ƟLq0#0aO]W |!Xvo7~嘬)9O{ ơ}d逮foM<>(J(cEuۄ 5ra3~Wϰ$D}g.?7joݚR$FT΋I5i}gJIUpj,32 3P !?5j{*`ogh(*jQe(߾8c_` 1.NU־7Ѳ!Ȫp_i}nK!l.-;Y)U7b=Lwh*.dO'йwIEk}spMا!#)"HbETbO)+R㘅\+Q>9)R׆i8GO)D9\EhByȢt2.!r?3DHR*d0va}ènz*J7R>OWn! G+t /]>o؋$|6lWw?h쵦iTV3y܊+w*ج UT&^$³{p a|qB>ۑʆa^U6 p_?#l``LX'eNWUuO^ Ey_ 9};\$k@kxVrPG>wHW85ڒcg;{@FEN瞠3jk ϝQV̭TU]nzqB{ F&lݶ^ 򽀋?KgS1ysH/\69L ';(FˀqEgDl4t8(t#=8W0DwS]/8{)M҂I[~$Uw瘄銨+{5ܐCB r:/XFP/2?QJ)3 o`>evx\5ըGJH0RIWݟX'!q#?c]ϲi Na-RC>b,ͬyにzNaʘ8\zM}95.#Nw֫ONsX0L&8oq c-ߔwMБZ*!pd#?l!Ul߲(v|bѹ3-m][%8EחiS[5Ű%['V;@laH W1asJaZv^srzw=QPsbMnFEvD4E\VwݞTN#T|;8u􅋪:Lq{p!"n{dʾ`W3 p3OA1W#<{:) mҾޭ;4E:Zuxt܁ޗpgG@Na|7kVݨqa[3xGo_>i%|1ʏJ@;WjFr@9)I۲+Ջe|/U'3RSfy~#*8K.Ab2wwVkWwkl 7%ʸU5)]jw\ȍ?=Mx z]mD>gĽB 23z«7lw$$hG E]QBʇߗ/9JGftE1yKy):#D<6+cyh}\]z|uEyQnWi /-Z īkEuzXM2$iR5񎁯K`M>Gy8 57=@i;vbXM9,[;zDcHf?olOq>)>^Q~viO{+3J|-uI^^^%3,8'2+y_ ǘ홢?L& ;sCE=z!ìmW} [l$Oc/n:Ě1 Dǧ$Ԧmb3~dTR2N Ky0DZK^?Ï3N, tq\W4 /`F|P1\X߃i\9^U][00ePzT[+(~Fh\X}FzE1-h^Ķ=F쬊r[BڰT"dDi|ik_6UKR, e*!F,*\]3bU['FFGẳ/+&$p_Kj0ŚaՔs4S[z(ld<~rЩ {AFMj_[жߋ0F3 $jṪW)߭'Yя8Ǭ2ҞUEp*:ě4dJ_^ qűb&,iAH5 }A!3n!'KL00joa], M R9pU9EH*SIҼ8sl)t cQD[VoU}oJ>6U#LE/$07*T46)T+4 e{X^H+ >BF<<RB %5AT&)bX9*ƒ+pB%R?ƨ2ϢTƔ2^^G%A`Gs$rؑ-;PBĮ7\i/0%ӏDWVOTe*2SJ'R߇-O.M٘6ҼauȒ'K-KRo嘎 $R?dKaܟialǔw>r_7ٴc+#X-|#EkU{I}[Ǐ[4obTwllEؐl꜀"BL;S`~Xjm]c*U$ס_,AO I+9k]Ҝ^nژQqRlex28}$"9ZIRTg{K u!m+M9 ,.6x)-'-jkE86o X+N:S\ qZo;Gľ1vms"rq}cqFM_ (TLdQ6lkmj?uTTGpgf}4<͋GFOwoK.`G_}g~,9!F:ս.} 3pqGů=?>_?NP͙A…5̒0qXq.{_#4+oik*FY]ثSqZM8 m6i^s긶m7XXl9q-]3x2Q'=Ãp̒>I64>mZoBwֱД/,'30\Sv>GҿJ"s_>5Uf!B`S,1C+i\R*QJNQ|0v%MhLvջU^۶{Xr'xr"}fgutq_E4PtsC{88ʆ^DT_a%^Um״Ւ+\cGYG򴻫i+vӶ69 zF0ïT&P.3w LMv}W0poIyW [{IRZcns+LMW7zƎJZM%[|,G%N吗֗koNNT* D0"Qs~W"&;uTIwأ҃'X?pZUdI̦:%~m*݆(uNWcIi#ͣM%%7JR雓 Z$'9>ݪS/B cq\1-gX-md(Oq바)q~'9B- Â7Z  IQ\D)F>}HA?a?QSn˩ _(2h\c PPuӢ!Ꝣ70J< (44\>mHqYjWvf9s̭<}V+eGոm:7 R^ѧ0{]^]71g\И49Qoh\-LFKp·Ǵsحf.O,4bsf#TH!gWzOq^1l%i-(>->RCyMp\3k!A([,ԕ7>Dk11zIn`ٸF] =(If2[8)j8X?/l( ! cCS'rZv 4!,=23DV;' #J&'~[݅c5LgDڬ]R>%̖΀yJKGHVs| ఻Rw'=oCbsSZQo< .QOr9VoqU|qJ{\~l*ZSX=cO m.|H)CI3< M<{瞅wD̪\9v?M3xZ5)30/-YGe &\\o $U)՜/ n֯z9"g>KU#mȀϟhn-uNI6E"75`AO]Isz&פیA8xum%ujӼs9UuvnO1ƒ 1ZNl82Ln W{kXyPkRn\r͐J ~NVt<ʍ6kZEaY)Un@5}2FRqY_D%֜}ɁGZۆk+m9Ol{jBC^Fͥ\B˧Gj$9#J0LhONϓ^_ KX~.Q-6{ kw UBW2|(Gш'^}~5[TQeHSxM)ΰ$\߫?|$V98ڄqWvx6IDkX*#>Ա "Y_:Gh)6rKHO>PY VgDT!iEZT`sъ(Ōi>="Rle8 Q^JrRt c Tneushmh'K Wiɖhy՟Xd2٢EF:Z~dr#-dSo%o/B7e|XQx;3Iw]ue|ާGA`[\H2&3N4f'] œ,L*mBRoR^Di<6Sr.!#ѕWU48{ c\$377Wue*"zC=AaxbzkηJLE߱?\M-h}CǶFOıyrnDrgJ)#,OsFОyDwu>_H$чK\&Ov`|D+] VZfOgNtz*ʁєz-V*K%k+7TFP?]݂'JKZ^zMÇ_d0g!uǬyvJF(ӉlVʲgsoߖnsOpp{w>1yƵHxJ2@:=F:ӺOSJ*9$b9˅\pv> '6Ev9Qrg^q?.b-*Y@{<ҬUmX%JrOkz4rg{KscbH6TMxq[5a"е"wT4ӌmh၅,-&9} V)y'R*PsS"ȝs'ox\%-l`iyK]hi&~rHznvpƝ% L4g8-U0ʡ. X+TsOԨBc% {TL)m5$8aY+cnrW\DhJ+C0f"6ʔ:Rk.^cҊBl]q~roՀƃ+$J9k DUԕMDSԩg;U΄pRK?_p|% :[$zQ3h_Z:d Sn_ַr Z]wj(pԺyس %8W%c ֵQ 6SZoy.G0<}32,s[p&ƺyaw1% }?|#_@׳ԊyBg?ij"!%LXBxEHbgZX_85!l?bLd#|p|}`.ͧ"\3ʶƊU-_GV0j/?@iǷYA{_ґllБ.7 FVRx#'*4 ׌b]jv8m]C;zW`yU#wAAxSY|B}tX5(siK~*8,IsIYUt%#Ěx['^x]&"6ϙL鱶t5'FP3ZC]irG/(\{mSMl8/c?O߭@|6Te=2ۆz42 ئ$bc&Q~hCI@_/!_jW煌YH7xg>} 3CQ쾖CAM)_yqn^rXRԅ֤pfz]d+LmB7ɯ$K5f@&𑯏m]G'.rQpOb{Q~bW@ɢ0}U=jk[ۼU|ZD '|_ӽh3rz9xDpS¹[UD򎟺Qq|(O:1̀7j#5bAWK|ɜ84?kJ bAzƀz!i1ښu -YAd=͡5& mT~TEb}۱5]eٛK/duƷǒcCc0^}LzQ|}B}x8^c IyxH"U]gldYp/< G}7֖ǙT Ôx#. x /9Ҡ+t Sп'~ѳuGPuD2W.Vqtɿjv`Њu*<||]%(ʶ@QŨH瓳~uU-mn uD%핑I7S1 jgnO`)kܐfI/6ODŽMm8&@+mbjs#4X< ;ύ)t(IFg.= XZ0u^18E'whlST,Ayx w)g2hg,ػ?pb{cQNe4K 峳?y8z_7$lda>9KR`12eO?t+R/o)PB {?c?ק(ŕiu9 #OPtk$8#bs\~J!ŽQKqW%Zar۲H5̰6eYQR}BT%Y¼6ld҃笲Xx'Tp|jqnoȯ"8Dm~=ltERL>VϤij~{Tm[.6*X(b='Հ>jYGƝ-7kQYaKG._'QgTհOkm}+Ee)j>^tzO9X援r aTڮitV}Fbn[} k%i>6IеPORd{mˉT`dV^Hc&=_bGGt\͘ mM}27"f~]~{x=8Ի(31}a d7*Jt6|وn+Je5̔mF'GzJ92{jnvy& Fv<.]o$%N9q?Dgsa]o<ЭoouA%=葩_8t%@@)6-˧'/I0;pq~~:ce>^{GÚS]Gղ7nzyt΂tR%WZk* Z-#[Jo\ vefdNMJYB!!#-\ViK=L=;^ro'BƟ݄?p"r` +>)ߏ-{dzǮ~W-8bwlK\z_{F춪ɯ/rUTٺܲw3:y}Ŭ, ڏ J'.}}R~p=½-3 쇡sg/ }s,J|et6ЦPt2yȃ.ofg}`-3vc2J">hP,l3eR UA(Ss!L&pCeNgr[dU ԣPV2q c19TQEU\<}a,{(`kGɱsvc(JNvrT2IE˽¦xh4Dؘ=gX ɩ[>2>fQՆَp9.Thø)Gx&wN2pK_%b(Uc1;|RL$U5D&jesν_l}&˫l q.Gdl\Ծ:zz380<w |۸ɡ~ /2I^C}*uKn@i=! DxL: Y{STYHLx5%[ :Ɩx'ۜv6{GRas+$8 ]4f FYs?oW)F!y [|xkƒyR&JqBMQ& 6P%Uj鋷cuL)e?zc[}6EG,U WսsIjiUzY=wB7]fꂀȩX-F$?V_>+GzŜ>)|*hO0癈ʵhP5 /b~qW)YGt_[VQjZ$Sn:N{V-t`~EOrfyT爣\~]tf2-nqv|?p6\)(Yڂͳq\sLO'c\P-lW RjqA-o_$>0za}u6rPiX~~zV2twƿ[%/'<:BtsqK;'JDn#jH7#SQo/GKNeHF=̨MФ3YUG{Ud'1d.9 ղ׻r6 u#aGCӈJnklBopYI:+[i1P% |-'F街K]L(Aн~ukޑW7 '1 #¹x ,jMpS PD^.h1(ĝCiQ|CuR|뷸!0TSzRh1ȱa5|kcdT4yƓnԄjY ԎkƴHx:^u6vX" b f <6 xPαJ[PzdXDlCx,+n1uV QaiZI.l=Eq22%p;lOIJK}餱#tY 2I\ђG]]++}}L'-"O`stUu D(م~*.v~ht~pC 9A'fXY_xV."x/2{T08h'"Qw~R؍e`'?q'PZ'f`Fϲ!*7vSğ\]{-hIP)o0'Ado&d9R= V'_ OMG ~WcP7?'aϻ*'u G+~"bx9 ?+)+{C88bA\~-d{Ȯ w9$KϴPكޭbIruv E-~戄]Jwv9A|XnN.]5m7{wAAxoLHď<-%_ v$    L$qS!P<|hE9!(-Pƒ "t3I_VL^6FSi]N*x< 1v0.P>.؇L bpT! H&o;`?iSt-@!\d` @ A`7!.wPPDo~'G}L#TL*h ~C J"9%@ң11spr?p/ ($,"*&.!)!yGUT54ut ML̏ZXZ>nswp$99{xzyBN9{аȨظĤԴ􌋙._}ܼ¢ҲʪںƦͷZn޹{`phxdtl|brg?y:ln%0/߿$ǐxO 0cOи*h:i!Pf`vd87|? B0 b8 H <@" p@P@P @@00́` Xk8`lHЀ'p\7</|? $ Ng9ИsC hV iA}rx wCi4b!iSHIIANkx\x]lU~ȢdkAnFQ$5Ah b!L n84B^+(`))dɨ`2ДVPf%*bJQ<7 b_-|=aANC3r40ktT0YJ h喥eQF68#9!#e(əa O&_YQOQOy?<^#(?/3^ όgeHx AĂEEܹiii..i,C.X0Q\]RB씔|٣X:!v`[h]G񞫰ϾSQB+1䙐fx A+;*P՝@fA OPfSA۽3A=@a( #d@`m0{`=_L 0 |ȮPyTy!ZPM0Wp`߭(&BA!T_sC||gwJ뷡O埱<kBz_A4?pC` ӳ!` 2Q <:Ap% W ܀.@uNBW1٫BRAp *? Cen~Ҥ" '2.JC` >'8yӅ@B@ gXd WGKsOH ]ȐmrOPr ?zW$ k e\ 3P gs,ܟ䳫0@c?eG? .#Y?Wp]\:?N|t@K{\vnRCbZ۵^??0sdЎ49T3M3~)w4 *Loo8?d pi'3M W!.4|? Tgg &*4$SAg_GC,RG4 }'A5rr*qR^%ګ U#A. (t$hAv1yBGI~A$ǿqiMIh=Sh %prX.Ru Bd?(ar2 isS?g3}Of4A2)AHR4 -HAA2@&dYA69A.p?x<An@~P@aP@qP1 āxJDPeA9(*#"***&j:.!h&)hGA q<ڂv=:$ t]@W t=@O }@_@0< ,x<^CP0 L#H0 cX0D0 LST0 L3`&x b/W`6x s\0 B,KR ,+J k F: 66 6;.{>!pG1p')>|>1| ΂``;Oj@W= aGC}Hc *> yhR~?NOis9BA8\)=](NɽH')\H$ '@? ' k0?)EՋ'y(h2@WRh=]C)o9J;g̱4cNv`'"oGMZ!Pҏ!QM8JZ9)Qd ڏj4QLGuTG:j.0=r0 ~T7??1gG)ޜhjٟ(΍EJSo?/Zh xBnG[?Aw1DH?~4&0w®?:TQOxw̎A-~!G D'~!`W4~+VDȰRP; ~ RsQeu@l/$ ))vC^j/ iBڽn/Ƚ4j/Ͱ2By^[c/ ၽr<{!4f^(Ax/-WSt/-{^[^}^]%R{{WwӐ]d~j wdߏ/OCC! _BBO:;jHIK 7?4TUPлDz3>u\@c?M4#ut|Y(&?|Ak? AG!A*AMJ 7̸ f"0w ~zr ? =hqۈšeqmrtR*1/DJ-F OwW˿#dG]0X%e ZOL ؿ'+V ]_y1ҿԓZO2J+-e.S4_"+H2/ E'zG'KzؿJ!HZK+K=_t\J d!%`~i )/m2_t/%K=?K%y%K^ N"x$u`1_###r6I𒳈4<8R2x-gzMO{%c$6(pP&vgMz"i22qk& ^S[f$Dv7AoSm U)N rK>UIR*Tlc24ϊ++TP"A=zLjN LȠS8t6%قՁOiq p;TX&Y7aG^FwM7azEֱD3ISRQQ3(? 1y\P p3t1EKV.Lm1νi**qv.VNoTM}4 ۾SKB ~/~ugPKM++뜩FO{QS,bSi_WuM߳*G%UVτe ͹ S +uXY$CnZըhi3'wTVFgUWBDKm\TzT =}}-FLnʶ|cV͡&phpzy[SX=EI/((ўOr uOӹ@&Or sܭ5Q_U$Rv8"/ s6 Q5Qs'OŞHj64RW5Qh ے =@h >M.j`xY8Ԥ0j!v?oɡjnNlWRJMi?WhO=|=]L'RU\L/-j$;#}SN_EprݧAVd )BV"Ӊ֨.^((STbRORmNR|ӆdjz ><[y!fFKV)FYAXF[i^HٶaՁtNK4xCd+ƬEۀjmX}۶*21-_8PϟNdqsHTt*V<#ϒEl]|5{\86p.SN,MN+΅[Mc şNL:Wy9hb~E% vky%|<f/%eJ:Wݻr~-B'њs)jDEE9H{b.KIļy#6y2;I$?&5P@u`G@jnBFU#Q ﰹ~SkN:aJ~6r,\eӌӤdm_}#5{{qvqx "} *%/>M;.aC*5 +%-qaqcc\FcZٴYd%Z`nLI:ΧQnpNҥR[4 YT IX\((!9@R7[ԡdf-I_%nmPȌKŸ kɷ~ZjoBe3n~Fxt{ИOdy%%!*% QQM1>u[oVeW{&Տqe+^kb6HvR@qGV 1lQLU^A|贅O W+_mTZTҹ$%Enptl &GC#*ˏe{4~M΂G<_w]S6iydr <#WOߺ~_ENΞ)׭K ӂnrzFr^S,_J4 +>!O1QYpUٙnÒ.%wGW+|>kL|— ǧ" # O]z(f#on+i8|OogW-]޻2&.4oZOJj$?l0Vm{|$, +Zv4zJA?g >:,2*""5n2"8l{)1 N?*2*#_%_Úc]|gGn|. !uɷssqbKΓC?oZRz׮i1MO^ۯw~r,ϾFiAFkLvWئ K9P&ްtƍ >er|8<?X`gmݛ_a%}w/>xpdMWvC@қׇ7kf0O}`=oķ%sMLrGjғ+N7ngW<+W|>es韯y+'ʑ7,ׁB߷āgUju_lOノczxrSiCBh^ ~vgǶoy7U? X mio?xN](R3->fn߽ g:I mQh)m,ٴ(Mz#ѩ g mG^2`Yr|-cj滼9<ڿxs}7{9d1,?{h7$n]3g c?ٲeʯo}ܨ9X}l}lj~un'߷myuۙ<e׭Cfi_-Նc+U[xSm+[ "c 1"Bέ<W`#2vQ^w{.$ G5xvM/y5A׌k.\3ZŀkC5`kFkp1Ԛk}5߫ b֌s. Ys ?XW;5?'"Ռ`ē-Z91\l;(٩MCFG`2 (Jm ,p3RLސ LdXa4Q@b4\%suјFJAl:+-SUs%5 ,2  bЌ!&DIT)۔T42]ь"A 2S‹H9#}ozcW8-%5Q~lzt|`" +tLfF &4~@E$PNňnMkX,?)!E IVʧLb u?"{J  BEM9-(Te R%l5i"*ytMbWpBG\I cdVkLp s [I JK52)2wJU1 EmbiHgc@DX(EL]bI1mPg%NZ;܅D Ę%dDT*cK-7scZ' q3R`׵ 'uxkx-A7'^c@abN XG)z5VuP!S:/c-x8]/V|;!I* 32 =s(2QH/(PMյhQpJ:ࠛtt\< 7% k|ߥOyg_È"1z, Zcƌ S[TyB"jPB FUrZm jǵM;%Eh WqyPpAQPLzNǬ|;i ZaUcifGLU JrQ:Ln'SX!QELZV+1+Cvk~t@$ySR"n~/zTH%k!Rx_:s†[BkD,,֖O74Zi9Zt:q~'?؊[]czu>S;lPcmݵ.AAk-|˕y_7Z(x2tV-r7>B>/+LthR xPL w'<$spgڡ2r3Y` TiHeXIGIh iXd-e/Jp5k"l6,ģ~"oFrngzp:r(VRu$ѡ뷜cZ:Zɔf(JM#prFᎵԌ}.YbɬLԙrÚ45laA1hNmL]DJ{WG;༵;{o ?LCx-ɘ k_dZUqnrܲ jc|;Ɓ*(qivC楢Bj.[4;z0z.Qj'4wJegB t>VtXgA;]rDs07oapܒ/ww8g;AnK =v{mElpjhI4.^yX3*dA+P^K*\nu.373 TaтyҦشʣza`DWҪu !y ޙa- ިC'fmf]]$SVQXLlXA[^Apv;];x/PgZ*L[^?yTm/_§Z?dG3+\s_٪!JNl(= +f| k_'YXeIOJ['NcDC&H~ L+|r@s>XJJp^_@d=1\3rN!|.h3Uz &7k:#/5)ҀXuSk‰MwM*l>\[ӞssVjnb|=m/C!΃P6&T]t Y0[H|!1LǛp)ÑeS4BT-4= Sb&ﻋjȺ*QM Fi*:m/6k},Q*>O̺m`Wam n̵hj-N*)b(‚My+@>>*k˒-#:ԆC|Rj6d$D'--*EzCͤmC1L`%Am8`m+f߃wǂ)u 3ZBinbXC)vsˁ1:+ϣo)+oʊ}8p'uYP MT;tmM P <^54uLd+o:il! Ydm- [hȞݯC JQ1Jܠ֥cxKu^kdJ) F9hUۈ9z=^rNLg(UV;<,YJ\z Dmj}Q5QZPg8.\7C澹tH-ouL,Cs^Edzpdf9gU<[wq;[oܤ+m$M1p[ę`# (jr9:>b"K CeP.[ES4bJ9r"gu]Ax^v5*6mf0hɵ^t0oۯ$p$ dE?SpBRO ^BŞZ ՁO-{jyxF`Ͻ =FO7~S ‰x S$s@ߘ|xE=24$C>݁?(C -%1RU8IAQ_b f18J/%D3':LéI¯{!\1(Bm cK(2a ` '{%>19ᐾ~$$1G0B0BИ {&r_x&_KL8+Շe#?>LD0>oN,??m>+|+ja68+fc;J`S.G~}w~RPKQ$<Rzot/ $cbc_d_m.txtPKQ$ڱlot/ $ocbc_e_m.txtPKQ$u|:/ $ecb_d_m.txtPKQ$=/ $ ecb_e_m.txtPKQ$UΥN $&ecb_iv.readmePKQ$:C ~ $ecb_iv.txtPKQ$qK $ ecb_tbl.txtPKQ$g+@M $Pecb_vk.txtPKQ$Y4:'} $8ecb_vt.txtPKQ$n2*-  $Readme.txtPK&;b'̉ katmct.pdfPK pyslowaes-0.1a1/ruby/test/test_helper.rb0000644000175000017500000000044412126341024017045 0ustar bartmbartmrequire 'test/unit' require File.dirname(__FILE__) + '/../lib/ruby-aes' require 'fileutils' unless defined? KEY_LENGTH KEY_LENGTH = [128,192,256].freeze MODES = ['ECB','CBC','OFB','CFB'].freeze end def random_fill(n, buffer) n.times do buffer << rand(256).chr end end slowaes-0.1a1/ruby/test/test_ruby-aes.rb0000644000175000017500000000641112126341024017315 0ustar bartmbartmrequire File.dirname(__FILE__) + '/test_helper.rb' class TestRubyAES < Test::Unit::TestCase def setup @keys = {} KEY_LENGTH.each do |kl| @keys[kl] = "" random_fill(kl/8, @keys[kl]) end @iv = "" random_fill(16, @iv) @pt = "" random_fill(64, @pt) @kl = KEY_LENGTH[(rand * KEY_LENGTH.length).to_i] @mode = MODES[(rand * MODES.length).to_i] end def test_modes_and_key_lengths pt = @pt[0...16] MODES.each do |mode| KEY_LENGTH.each do |kl| ct = Aes.encrypt_block(kl, mode, @keys[kl], @iv, pt) npt = Aes.decrypt_block(kl, mode, @keys[kl], @iv, ct) assert_equal(pt, npt, "Error in encryption/decryption (#{kl}-#{mode})") end end end def test_encrypt_decrypt_stream file = "_ruby-aes_test_encrypt_stream_" sin = File.open(file, "w+b") random_fill(4242, sin) sin.close sin = File.open(file, "rb") sout = File.open("#{file}.aes", "w+b") Aes.encrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout) sin.close sout.close sin = File.open("#{file}.aes", "rb") sout = File.open("#{file}.plain", "w+b") Aes.decrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout) sin.close sout.close pt, npt = IO.read(file), IO.read("#{file}.plain") assert_equal pt, npt, "Error in encrypt_decrypt_stream" ensure FileUtils.rm_f [ file, "#{file}.aes", "#{file}.plain" ] end def test_encrypt_decrypt_buffer MODES.each do |mode| KEY_LENGTH.each do |kl| ct = Aes.encrypt_buffer(kl, mode, @keys[kl], @iv, @pt) npt = Aes.decrypt_buffer(kl, mode, @keys[kl], @iv, ct) assert_equal(@pt, npt, "Error in encrypt_decrypt_buffer") end end pt = "" 42.times do pt << random_fill(1, pt) ct = Aes.encrypt_buffer(@kl, @mode, @keys[@kl], @iv, pt) npt = Aes.decrypt_buffer(@kl, @mode, @keys[@kl], @iv, ct) assert_equal(pt, npt, "Error in encrypt_decrypt_buffer") end end def test_check_key_length assert_raise(RuntimeError) do Aes.check_kl(42) end KEY_LENGTH.each do |kl| assert_nothing_raised do Aes.check_kl(kl) end end end def test_check_iv assert_raise(RuntimeError) do Aes.check_iv(@iv.unpack('H*')) end assert_nothing_raised do Aes.check_iv(@iv) end end def test_check_key assert_raise(RuntimeError) do Aes.check_key(@keys[128], 64) end # bad key length assert_raise(RuntimeError) do Aes.check_key('123', 128) end # bad key string assert_raise(RuntimeError) do Aes.check_key(nil, 256) end # bad key string assert_raise(RuntimeError) do Aes.check_key(@keys[128].unpack('H*'), 128) end # bad key string assert_nothing_raised do Aes.check_key(@keys[@kl], @kl) end end def test_check_mode assert_raise(RuntimeError) do Aes.check_mode('ABC') end MODES.each do |mode| assert_nothing_raised do Aes.check_mode(mode) end end end def test_truth assert true end end slowaes-0.1a1/ruby/doc/0000755000175000017500000000000012126341052013767 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/0000755000175000017500000000000012126341052014716 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/rdoc-style.css0000644000175000017500000001033212126341024017513 0ustar bartmbartm body { font-family: Verdana,Arial,Helvetica,sans-serif; font-size: 90%; margin: 0; margin-left: 40px; padding: 0; background: white; } h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } h1 { font-size: 150%; } h2,h3,h4 { margin-top: 1em; } a { background: #eef; color: #039; text-decoration: none; } a:hover { background: #039; color: #eef; } /* Override the base stylesheet's Anchor inside a table cell */ td > a { background: transparent; color: #039; text-decoration: none; } /* and inside a section title */ .section-title > a { background: transparent; color: #eee; text-decoration: none; } /* === Structural elements =================================== */ div#index { margin: 0; margin-left: -40px; padding: 0; font-size: 90%; } div#index a { margin-left: 0.7em; } div#index .section-bar { margin-left: 0px; padding-left: 0.7em; background: #ccc; font-size: small; } div#classHeader, div#fileHeader { width: auto; color: white; padding: 0.5em 1.5em 0.5em 1.5em; margin: 0; margin-left: -40px; border-bottom: 3px solid #006; } div#classHeader a, div#fileHeader a { background: inherit; color: white; } div#classHeader td, div#fileHeader td { background: inherit; color: white; } div#fileHeader { background: #057; } div#classHeader { background: #048; } .class-name-in-header { font-size: 180%; font-weight: bold; } div#bodyContent { padding: 0 1.5em 0 1.5em; } div#description { padding: 0.5em 1.5em; background: #efefef; border: 1px dotted #999; } div#description h1,h2,h3,h4,h5,h6 { color: #125;; background: transparent; } div#validator-badges { text-align: center; } div#validator-badges img { border: 0; } div#copyright { color: #333; background: #efefef; font: 0.75em sans-serif; margin-top: 5em; margin-bottom: 0; padding: 0.5em 2em; } /* === Classes =================================== */ table.header-table { color: white; font-size: small; } .type-note { font-size: small; color: #DEDEDE; } .xxsection-bar { background: #eee; color: #333; padding: 3px; } .section-bar { color: #333; border-bottom: 1px solid #999; margin-left: -20px; } .section-title { background: #79a; color: #eee; padding: 3px; margin-top: 2em; margin-left: -30px; border: 1px solid #999; } .top-aligned-row { vertical-align: top } .bottom-aligned-row { vertical-align: bottom } /* --- Context section classes ----------------------- */ .context-row { } .context-item-name { font-family: monospace; font-weight: bold; color: black; } .context-item-value { font-size: small; color: #448; } .context-item-desc { color: #333; padding-left: 2em; } /* --- Method classes -------------------------- */ .method-detail { background: #efefef; padding: 0; margin-top: 0.5em; margin-bottom: 1em; border: 1px dotted #ccc; } .method-heading { color: black; background: #ccc; border-bottom: 1px solid #666; padding: 0.2em 0.5em 0 0.5em; } .method-signature { color: black; background: inherit; } .method-name { font-weight: bold; } .method-args { font-style: italic; } .method-description { padding: 0 0.5em 0 0.5em; } /* --- Source code sections -------------------- */ a.source-toggle { font-size: 90%; } div.method-source-code { background: #262626; color: #ffdead; margin: 1em; padding: 0.5em; border: 1px dashed #999; overflow: hidden; } div.method-source-code pre { color: #ffdead; overflow: hidden; } /* --- Ruby keyword styles --------------------- */ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; } .ruby-constant { color: #7fffd4; background: transparent; } .ruby-keyword { color: #00ffff; background: transparent; } .ruby-ivar { color: #eedd82; background: transparent; } .ruby-operator { color: #00ffee; background: transparent; } .ruby-identifier { color: #ffdead; background: transparent; } .ruby-node { color: #ffa07a; background: transparent; } .ruby-comment { color: #b22222; font-weight: bold; background: transparent; } .ruby-regexp { color: #ffa07a; background: transparent; } .ruby-value { color: #7fffd4; background: transparent; }slowaes-0.1a1/ruby/doc/rdoc/fr_class_index.html0000644000175000017500000000130112126341024020561 0ustar bartmbartm Classes slowaes-0.1a1/ruby/doc/rdoc/classes/0000755000175000017500000000000012126341052016353 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/classes/Aes.html0000644000175000017500000010003512126341024017747 0ustar bartmbartm Module: Aes
Module Aes
In: lib/ruby-aes.rb

Public Class methods

[Source]

    # File lib/ruby-aes.rb, line 45
45:     def Aes.bs(); return @@bs end

[Source]

    # File lib/ruby-aes.rb, line 46
46:     def Aes.bs=(bs); @@bs = bs.to_i; @@bs==0 ? 4096 : @@bs = @@bs - @@bs%16 end

[Source]

    # File lib/ruby-aes.rb, line 61
61:     def Aes.check_iv(iv_string)
62:         k = iv_string.length
63:         hex = (iv_string =~ /[a-f0-9A-F]{#{k}}/) == 0
64:         bin = ! hex
65:         if k == 32 && hex
66:             return [iv_string].pack("H*")
67:         elsif k == 16 && bin
68:             return iv_string
69:         else
70:             raise "Bad IV string"
71:         end
72:     end

[Source]

    # File lib/ruby-aes.rb, line 48
48:     def Aes.check_key(key_string, kl = 128)
49:         kl = Aes.check_kl(kl)
50:         k = key_string ? key_string.length : 0
51:         raise "Bad key string or bad key length" if (k != kl/8) && (k != kl/4)
52:         hex = (key_string =~ /[a-f0-9A-F]{#{k}}/) == 0 && (k == kl/4)
53:         bin = ! hex
54:         if ! (([32, 48, 64].include?(k) && hex) ||
55:            ([16, 24, 32].include?(k) && bin))
56:             raise "Bad key string"
57:         end
58:         hex ? [key_string].pack("H*") : key_string
59:     end

[Source]

    # File lib/ruby-aes.rb, line 82
82:     def Aes.check_kl(key_length)
83:         case key_length
84:         when 128, 192, 256
85:         else raise "Bad key length"
86:         end
87:         key_length
88:     end

[Source]

    # File lib/ruby-aes.rb, line 74
74:     def Aes.check_mode (mode)
75:         case mode
76:         when 'ECB', 'CBC', 'OFB', 'CFB'
77:         else raise "Bad cipher mode"
78:         end
79:         mode
80:     end

[Source]

     # File lib/ruby-aes.rb, line 106
106:     def Aes.decrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT")
107:         Aes.init(keyl, mode, key, iv)
108:         @@aes.decrypt_block(block)
109:     end

[Source]

     # File lib/ruby-aes.rb, line 116
116:     def Aes.decrypt_buffer(keyl, mode, key, iv, buffer = "DEFAULT PLAINTXT")
117:         raise "Bad Block size" if buffer.length < 16
118:         Aes.init(keyl, mode, key, iv)
119:         @@aes.decrypt_buffer(buffer)
120:     end

[Source]

     # File lib/ruby-aes.rb, line 145
145:     def Aes.decrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT)
146:         Aes.init(keyl, mode, key, iv)
147:         case sout
148:         when String, Array, IO
149:         else
150:             raise "Bad output stream (String, Array, IO)"
151:         end
152:         case sin
153:         when String
154:             sout << @@aes.decrypt_buffer(sin)
155:         when IO
156:             while buf = sin.read(@@bs)#+1)
157:               if buf.length == @@bs
158:                 sout << @@aes.decrypt_blocks(buf)
159:               else
160:                 sout << @@aes.decrypt_buffer(buf)
161:               end
162:             end
163:         else
164:             raise "Bad input stream (String, IO)"
165:         end
166:     end

[Source]

     # File lib/ruby-aes.rb, line 100
100:     def Aes.encrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT")
101:         raise "Bad Block size" if block.length < 16 || block.length > 16
102:         Aes.init(keyl, mode, key, iv)
103:         @@aes.encrypt_block(block)
104:     end

[Source]

     # File lib/ruby-aes.rb, line 111
111:     def Aes.encrypt_buffer(keyl, mode, key, iv, buffer = "PLAINTEXT")
112:         Aes.init(keyl, mode, key, iv)
113:         @@aes.encrypt_buffer(buffer)
114:     end

[Source]

     # File lib/ruby-aes.rb, line 122
122:     def Aes.encrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT)
123:         Aes.init(keyl, mode, key, iv)
124:         case sout
125:         when String, Array, IO
126:         else
127:             raise "Bad output stream (String, Array, IO)"
128:         end
129:         case sin
130:         when String
131:             sout << @@aes.encrypt_buffer(sin)
132:         when IO
133:             while buf = sin.read(@@bs)
134:               if buf.length == @@bs
135:                 sout << @@aes.encrypt_blocks(buf)
136:               else
137:                 sout << @@aes.encrypt_buffer(buf)
138:               end
139:             end
140:         else
141:             raise "Bad input stream (String, IO)"
142:         end
143:     end

[Source]

    # File lib/ruby-aes.rb, line 90
90:     def Aes.init(keyl, mode, key, iv)
91:         unless @@aes
92:             @@aes = AesAlg.new(Aes.check_kl(keyl), Aes.check_mode(mode),
93:                                Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil)
94:         else
95:             @@aes.init(Aes.check_kl(keyl), Aes.check_mode(mode),
96:                        Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil)
97:         end
98:     end
slowaes-0.1a1/ruby/doc/rdoc/classes/AesShared.html0000644000175000017500000003471512126341024021111 0ustar bartmbartm Module: AesShared
Module AesShared
In: lib/ruby-aes/aes_shared.rb

Public Instance methods

[Source]

    # File lib/ruby-aes/aes_shared.rb, line 23
23:     def decrypt_blocks(buffer)
24:         raise "Bad block length" unless (buffer.length % 16).zero?
25:         pt = ""
26:         block = ""
27:         buffer.each_byte do |char|
28:             block << char
29:             if block.length == 16
30:                 pt << decrypt_block(block)
31:                 block = ""
32:             end
33:         end
34:         pt
35:     end

[Source]

    # File lib/ruby-aes/aes_shared.rb, line 55
55:     def decrypt_buffer(buffer)
56:         pt = ""
57:         block = ""
58:         buffer.each_byte do |char|
59:             block << char
60:             if block.length == 16
61:                 pt << decrypt_block(block)
62:                 block = ""
63:             end
64:         end
65:         if block.length != 1
66:             raise 'Bad Block Padding'
67:         elsif (c = block[-1]).zero?
68:             pt
69:         else
70:             if block * c == pt[-c..-1]
71:                 pt[0..-c-1]
72:             else
73:                 raise "Bad Block Padding"
74:             end
75:         end
76:     end

[Source]

    # File lib/ruby-aes/aes_shared.rb, line 9
 9:     def encrypt_blocks(buffer)
10:         raise "Bad block length" unless (buffer.length % 16).zero?
11:         ct = ""
12:         block = ""
13:         buffer.each_byte do |char|
14:             block << char
15:             if block.length == 16
16:                 ct << encrypt_block(block)
17:                 block = ""
18:             end
19:         end
20:         ct
21:     end

[Source]

    # File lib/ruby-aes/aes_shared.rb, line 37
37:     def encrypt_buffer(buffer)
38:         ct = ""
39:         block = ""
40:         buffer.each_byte do |char|
41:             block << char
42:             if block.length == 16
43:                 ct << encrypt_block(block)
44:                 block = ""
45:             end
46:         end
47:         c = "\000"
48:         if (m = 16 - block.length % 16) != 16
49:             c = m.chr
50:             ct << encrypt_block(block << c * m)
51:         end
52:         ct << c
53:     end
slowaes-0.1a1/ruby/doc/rdoc/fr_method_index.html0000644000175000017500000000337112126341024020745 0ustar bartmbartm Methods slowaes-0.1a1/ruby/doc/rdoc/index.html0000644000175000017500000000134612126341024016716 0ustar bartmbartm ruby-aes reference slowaes-0.1a1/ruby/doc/rdoc/files/0000755000175000017500000000000012126341052016020 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/files/COPYING.html0000644000175000017500000000607512126341024020025 0ustar bartmbartm File: COPYING

COPYING

Path: COPYING
Last Update: Sun Jul 29 18:32:22 +0200 2007

Copyright (c) 2007 Alex Boussinet

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

slowaes-0.1a1/ruby/doc/rdoc/files/README.html0000644000175000017500000001241712126341024017647 0ustar bartmbartm File: README

README

Path: README
Last Update: Sun Jul 29 18:32:22 +0200 2007

README for ruby-aes

=============

Ruby AES <rubyforge.org/projects/ruby-aes> is an implementation of the Rijndael algorithm.

Written by Alex Boussinet <alex.boussinet@gmail.com>

This release is mainly an import from the Ruby Application Archive (RAA). I‘ve added all the versions I was working on (algorithm variations) and a new C extension for improved performance. 6 variations are available:

  • "Normal":

Pure Ruby implementation of the Rijndael algorithm specifications. Useful for understanding the algorithm.

  • "Optimized":

Pure Ruby implementation based on the "Normal" code but optimized for speed. The SubBytes and ShiftRows methods have been combined.

  • "Table Optimized 1":

Pure Ruby implementation based on the C code from the Rijndael website. The arrays of constants are bigger because all the operations are already computed so it‘s mainly based on table look ups.

  • "Table Optimized 2":

Pure Ruby implementation based on the "Table Optimized 1" code. The arrays of constants are bigger because all the operations are already computed and table look ups are also combined.

  • "Table Unroll Optimized 1":

Pure Ruby implementation based on the "Table Optimized 1" code. The change here is that the loops are unrolled.

  • "Table Unroll Optimized 2":

Pure Ruby implementation based on the "Table Optimized 2" code. The change here is that the loops are unrolled.

  • "EXT Table Unroll Optimized 2":

C extension based on the "Table Unroll Optimized 2" code. This extension is provided for major speed improvement.

All those variations share the same API:

  Default key_length: 128
  Default mode: 'ECB'
  Default IV: 16 null chars ("00" * 16 in hex format)
  Default key: 16 null chars ("00" * 16 in hex format)
  Default input text: "PLAINTEXT"

  Aes.check_key(key_string, key_length)
  Aes.check_iv(iv_string)
  Aes.check_kl(key_length)
  Aes.check_mode(mode)
  Aes.init(key_length, mode, key, iv)
  Aes.encrypt_block(key_length, mode, key, iv, block) # no padding
  Aes.decrypt_block(key_length, mode, key, iv, block) # no padding
  Aes.encrypt_buffer(key_length, mode, key, iv, block) # padding
  Aes.decrypt_buffer(key_length, mode, key, iv, block) # padding
  Aes.encrypt_stream(key_length, mode, key, iv, sin, sout)
  Aes.decrypt_stream(key_length, mode, key, iv, sin, sout)
  Aes.bs() # block size for read operations (stream)
  Aes.bs=(bs)

Valid modes are:

    * ECB (Electronic Code Book)
    * CBC (Cipher Block Chaining)
    * OFB (Output Feedback)
    * CFB (Cipher Feedback)

Valid key length:

    * 128 bits
    * 192 bits
    * 256 bits

For a really good encryption, 256 bits CBC is recommanded.

For more information on AES-Rijndael, see: <csrc.nist.gov/encryption/aes/rijndael/>

slowaes-0.1a1/ruby/doc/rdoc/files/CHANGELOG.html0000644000175000017500000000447512126341024020206 0ustar bartmbartm File: CHANGELOG

CHANGELOG

Path: CHANGELOG
Last Update: Sat Jan 05 00:53:21 +0100 2008

1.1

2008-01-05

  • Fixed padding problem (bug 15885)
  • Fixed encrypt/decrypt stream

1.0

2007-07-30

  • Initial release: RAA project import
  • Added a C extension for speed along the 6 other versions (see README)
  • Minor changes in the API
slowaes-0.1a1/ruby/doc/rdoc/files/lib/0000755000175000017500000000000012126341052016566 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/files/lib/ruby-aes/0000755000175000017500000000000012126341052020315 5ustar bartmbartmslowaes-0.1a1/ruby/doc/rdoc/files/lib/ruby-aes/aes_shared_rb.html0000644000175000017500000000373612126341024023774 0ustar bartmbartm File: aes_shared.rb

aes_shared.rb

Path: lib/ruby-aes/aes_shared.rb
Last Update: Fri Jan 04 17:08:17 +0100 2008
slowaes-0.1a1/ruby/doc/rdoc/files/lib/ruby-aes_rb.html0000644000175000017500000000416512126341024021673 0ustar bartmbartm File: ruby-aes.rb

ruby-aes.rb

Path: lib/ruby-aes.rb
Last Update: Fri Jan 04 17:09:17 +0100 2008

Required files

ruby-aes/aes_alg  
slowaes-0.1a1/ruby/doc/rdoc/fr_file_index.html0000644000175000017500000000161412126341024020402 0ustar bartmbartm Files slowaes-0.1a1/ruby/doc/rdoc/created.rid0000644000175000017500000000004012126341024017016 0ustar bartmbartmSat, 05 Jan 2008 02:15:01 +0100 slowaes-0.1a1/ruby/COPYING0000644000175000017500000000204112126341025014252 0ustar bartmbartmCopyright (c) 2007 Alex Boussinet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.slowaes-0.1a1/ruby/Rakefile0000644000175000017500000000730712126341025014676 0ustar bartmbartmrequire 'rake' require 'rake/clean' require 'rake/testtask' require 'rake/gempackagetask' require 'rake/rdoctask' require 'fileutils' include FileUtils @name = 'ruby-aes' @version = '1.1' @native = false @lib = "lib/#{@name}" @ext = "ext/#{@name}" @ext_o = 'aes_alg.o' @ext_so = "aes_alg.#{Config::CONFIG['DLEXT']}" RDOC_OPTS = ['--quiet', '--title', 'ruby-aes reference', '--opname', 'index.html', '--exclude', 'ext', '--line-numbers', '--main', 'README', '--inline-source'] CLEAN.include [ '**/.*.sw?', '*.gem', '.config', '**/.DS_Store', "#{@ext}/#{@ext_so}", "#{@ext}/#{@ext_o}", "#{@ext}/Makefile", "#{@ext}/aes_cons.h", "#{@ext}/mkmf.log", "#{@lib}/aes_alg.rb", "#{@lib}/aes_cons.rb", "#{@lib}/aes_gencons.rb" ] SPEC = Gem::Specification.new do |s| s.name = @name s.version = @version s.platform = Gem::Platform::RUBY s.has_rdoc = true s.rdoc_options += RDOC_OPTS s.extra_rdoc_files = ['README', 'CHANGELOG', 'COPYING'] s.summary = 'ruby-aes is an implementation of the Rijndael algorithm (AES)' s.description = s.summary s.author = 'Alex Boussinet' s.email = 'alex.boussinet@gmail.com' s.homepage = "http://#{@name}.rubyforge.org" s.rubyforge_project = @name s.test_files = FileList['test/test_*.rb'] s.require_paths = ['lib'] # s.bindir = 'bin' s.files = %w(CHANGELOG COPYING README Rakefile) + Dir.glob('{doc,examples,lib,test}/**/*') end def task_gem desc 'Build the gem' Rake::GemPackageTask.new(SPEC) do |p| p.need_tar = true p.gem_spec = SPEC end end Dir.glob('extras/*').each do |project| desc "Specify the project to use" task File.basename(project).to_sym do |t| @type = t.name @gem_name = "#{@name}-#{@type}" SPEC.name = @gem_name SPEC.files += [ "#{@lib}/aes_alg.rb", "#{@lib}/aes_cons.rb" ] task_gem end end desc "Specify the project to use" task :cext do |t| @type = t.name @gem_name = "#{@name}-#{@type}" SPEC.name = @gem_name SPEC.require_paths += ['ext'] if @native SPEC.files += ["#{@ext}/#{@ext_so}"] SPEC.platform = Gem::Platform::CURRENT else SPEC.files += [ "#{@ext}/aes_alg.c", "#{@ext}/extconf.rb", "#{@ext}/aes_cons.h" ] SPEC.extensions = "#{@ext}/extconf.rb" end task_gem end desc "Use the native version of cext" task :native do @native = true Rake::Task[:cext].invoke end task :prepare do if @type == 'cext' Dir.chdir(@ext) do ruby 'aes_gencons.rb' if @native ruby 'extconf.rb' sh(PLATFORM =~ /win32/ ? 'nmake' : 'make') end end else cp "extras/#{@type}/aes_alg.rb", "#{@lib}/" cp "extras/#{@type}/aes_gencons.rb", "#{@lib}/" Dir.chdir(@lib) do ruby 'aes_gencons.rb' rm_f 'aes_gencons.rb' end end end task :package => [:clean, :prepare, :rerdoc] task :default do STDERR.puts <<-EOM You must call rake with one of this task as first param: normal optimized table1 table2 unroll1 unroll2 cext native (imply cext) EOM end desc 'Run all the tests' Rake::TestTask.new do |t| t.libs << "test" t.test_files = FileList['test/test_*.rb'] t.verbose = true end desc 'Build the documentation' Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'doc/rdoc' rdoc.options += RDOC_OPTS rdoc.main = 'README' rdoc.rdoc_files.add ['README', 'CHANGELOG', 'COPYING', 'lib/**/*.rb'] end desc 'Install the package' task :install do |t| sh %{sudo gem install pkg/#{@gem_name}} end desc 'Uninstall the package' task :uninstall do sh %{sudo gem uninstall #{@gem_name}} end slowaes-0.1a1/ruby/examples/0000755000175000017500000000000012126341052015040 5ustar bartmbartmslowaes-0.1a1/ruby/examples/encrypt_buffer.rb0000644000175000017500000000132212126341025020400 0ustar bartmbartm#!/usr/bin/env ruby require 'rubygems' require 'ruby-aes' require 'example_helper' class RubyAES_buffer include RubyAES_helper def initialize setup puts "Using #{@kl}-#{@mode} encryption/decryption" pt = "The quick brown fox jumps over the lazy dog" puts "Plaintext is: '#{pt}'" puts "(a buffer will be padded so that its length will be a multiple of 16)" ct = Aes.encrypt_buffer(@kl, @mode, @keys[@kl], @iv, pt) puts "Ciphertext (unpacked) is: #{ct.unpack("H*").first}" npt = Aes.decrypt_buffer(@kl, @mode, @keys[@kl], @iv, ct) puts "Decrypted ciphertext is: '#{npt}'" puts "(should be: '#{pt}')" end end RubyAES_buffer.new slowaes-0.1a1/ruby/examples/openssl_example.rb0000644000175000017500000000054712126341025020571 0ustar bartmbartm#!/usr/bin/env ruby require 'rubygems' require File.join(File.dirname(__FILE__), '..', 'lib', 'ruby-aes') require 'base64' enc = Aes.openssl_encrypt("pass", "test") dec = Aes.openssl_decrypt("pass", enc[:salted]) puts Base64.b64encode(enc[:salted]) puts "Salt: #{enc[:salt]}" puts "Key: #{enc[:key]}" puts "IV: #{enc[:iv]}" puts "Decrypted: #{dec[:raw]}"slowaes-0.1a1/ruby/examples/encrypt_stream.rb0000644000175000017500000000207012126341025020423 0ustar bartmbartm#!/usr/bin/env ruby require 'rubygems' require 'ruby-aes' require 'example_helper' require 'fileutils' class RubyAES_stream include RubyAES_helper def initialize setup puts "Using #{@kl}-#{@mode} encryption/decryption" file = "_ruby-aes_encrypt_stream_" sin = File.open(file, "w+b") sin.puts "The quick brown fox jumps over the lazy dog" sin.rewind sout = File.open("#{file}.aes", "w+b") Aes.encrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout) sin.close sout.close sin = File.open("#{file}.aes", "rb") sout = File.open("#{file}.plain", "w+b") Aes.decrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout) sin.close sout.close if IO.read(file) == IO.read("#{file}.plain") puts "The decrypted file is exactly the same as the original one" else puts "The decrypted file differs from the orginal one" end FileUtils.rm_f [ file, "#{file}.aes", "#{file}.plain" ] end end RubyAES_stream.new slowaes-0.1a1/ruby/examples/encrypt_block.rb0000644000175000017500000000114712126341025020226 0ustar bartmbartm#!/usr/bin/env ruby require 'rubygems' require 'ruby-aes' require 'example_helper' class RubyAES_block include RubyAES_helper def initialize setup pt = "0123467890ABCDEF" puts "Using #{@kl}-#{@mode} encryption/decryption" puts "Plaintext is: #{pt} (a block should be 16 octets)" ct = Aes.encrypt_block(@kl, @mode, @keys[@kl], @iv, pt) puts "Ciphertext (unpacked) is: #{ct.unpack("H*").first}" npt = Aes.decrypt_block(@kl, @mode, @keys[@kl], @iv, ct) puts "Decrypted ciphertext is: #{npt} (should be: #{pt})" end end RubyAES_block.new slowaes-0.1a1/ruby/examples/example_helper.rb0000644000175000017500000000110412126341025020353 0ustar bartmbartm#!/usr/bin/env ruby module RubyAES_helper KEY_LENGTH = [128,192,256].freeze MODES = ['ECB','CBC','OFB','CFB'].freeze def random_fill(n, buffer) n.times do buffer << rand(256).chr end end def setup @keys = {} KEY_LENGTH.each do |kl| @keys[kl] = "" random_fill(kl/8, @keys[kl]) end @iv = ""; random_fill(16, @iv) @pt = ""; random_fill(64, @pt) @kl = KEY_LENGTH[(rand * KEY_LENGTH.length).to_i] @mode = MODES[(rand * MODES.length).to_i] end end slowaes-0.1a1/ruby/lib/0000755000175000017500000000000012126341052013770 5ustar bartmbartmslowaes-0.1a1/ruby/lib/ruby-aes/0000755000175000017500000000000012126341052015517 5ustar bartmbartmslowaes-0.1a1/ruby/lib/ruby-aes/aes_cons.rb0000644000175000017500000003373112126341024017644 0ustar bartmbartm=begin This file is a part of ruby-aes Written by Alex Boussinet aes_cons.rb - AES Constant Arrays for ruby-aes =end module AesCons RCON = [ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ] S_BOX = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ] IS_BOX = [ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ] G2X = [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 ] G3X = [ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a ] G9X = [ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 ] GBX = [ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 ] GDX = [ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 ] GEX = [ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d ] end # AesCons slowaes-0.1a1/ruby/lib/ruby-aes/aes_shared.rb0000644000175000017500000000306212126341024020142 0ustar bartmbartm=begin This file is a part of ruby-aes Written by Alex Boussinet It contains the code shared by all the implementations =end module AesShared def encrypt_blocks(buffer) raise "Bad block length" unless (buffer.length % 16).zero? ct = "" block = "" buffer.each_byte do |char| block << char if block.length == 16 ct << encrypt_block(block) block = "" end end ct end def decrypt_blocks(buffer) raise "Bad block length" unless (buffer.length % 16).zero? pt = "" block = "" buffer.each_byte do |char| block << char if block.length == 16 pt << decrypt_block(block) block = "" end end pt end def encrypt_buffer(buffer) # Altered this to conform with OpenSSL padding ct = '' rounds = (buffer.length.to_f / 16).ceil rounds.times do |i| block = buffer[i*16, 16] if i < rounds - 1 ct << encrypt_block(block) elsif block.length < 16 m = 16 - block.length ct << encrypt_block(block << m.chr * m) else #block size is equal to 16 ct << encrypt_block(block) ct << encrypt_block("\017" * 16) end end ct end def decrypt_buffer(buffer) buffer = buffer[16, buffer.length - 16] pt = '' rounds = (buffer.length.to_f / 16).ceil rounds.times do |i| block = buffer[i*16, 16] pt << decrypt_block(block) end m = pt[pt.length-1] pt = pt[0, pt.length - m] end end slowaes-0.1a1/ruby/lib/ruby-aes/aes_alg.rb0000644000175000017500000001335212126341024017442 0ustar bartmbartm=begin This file is a part of ruby-aes Written by Alex Boussinet ruby-aes (non-optimized version) Adapted from the Rijndael Specifications (dfips-AES.pdf) =end require File.join(File.dirname(__FILE__), 'aes_cons') require File.join(File.dirname(__FILE__), 'aes_shared') class AesAlg include AesCons include AesShared def subBytes i = 0 @state.each_byte do |b| @state[i] = S_BOX[b] i+=1 end end protected :subBytes def isubBytes i = 0 @state.each_byte do |b| @state[i] = IS_BOX[b] i+=1 end end protected :isubBytes def shiftRows @state[1], @state[5], @state[9], @state[13] = @state[5], @state[9], @state[13], @state[1] @state[2], @state[6], @state[10], @state[14] = @state[10], @state[14], @state[2], @state[6] @state[3], @state[7], @state[11], @state[15] = @state[15], @state[3], @state[7], @state[11] end protected :shiftRows def ishiftRows @state[1], @state[5], @state[9], @state[13] = @state[13], @state[1], @state[5], @state[9] @state[2], @state[6], @state[10], @state[14] = @state[10], @state[14], @state[2], @state[6] @state[3], @state[7], @state[11], @state[15] = @state[7], @state[11], @state[15], @state[3] end protected :ishiftRows def mixColumns t = "\000" * 16 4.times do |c| t[c*4] = G2X.at(@state[c*4]) ^ G3X.at(@state[1+c*4]) ^ @state[2+c*4] ^ @state[3+c*4] t[1+c*4] = @state[c*4] ^ G2X.at(@state[1+c*4]) ^ G3X.at(@state[2+c*4]) ^ @state[3+c*4] t[2+c*4] = @state[c*4] ^ @state[1+c*4] ^ G2X.at(@state[2+c*4]) ^ G3X.at(@state[3+c*4]) t[3+c*4] = G3X.at(@state[c*4]) ^ @state[1+c*4] ^ @state[2+c*4] ^ G2X.at(@state[3+c*4]) end @state = t end protected :mixColumns def imixColumns t = "\000" * 16 4.times do |c| t[c*4] = GEX.at(@state[c*4]) ^ GBX.at(@state[1+c*4]) ^ GDX.at(@state[2+c*4]) ^ G9X.at(@state[3+c*4]) t[1+c*4] = G9X.at(@state[c*4]) ^ GEX.at(@state[1+c*4]) ^ GBX.at(@state[2+c*4]) ^ GDX.at(@state[3+c*4]) t[2+c*4] = GDX.at(@state[c*4]) ^ G9X.at(@state[1+c*4]) ^ GEX.at(@state[2+c*4]) ^ GBX.at(@state[3+c*4]) t[3+c*4] = GBX.at(@state[c*4]) ^ GDX.at(@state[1+c*4]) ^ G9X.at(@state[2+c*4]) ^ GEX.at(@state[3+c*4]) end @state = t end protected :imixColumns def addRoundKey(n) j = n*16 16.times do |i| @state[i] ^= @w[i+j] end end protected :addRoundKey def key_expansion(key) 0.upto(@nk*4-1) do |i| @w[i] = key[i] end @nk.upto(@nb*(@nr+1)-1) do |i| j = i*4 k = j-(@nk*4) t0, t1, t2, t3 = @w[j-4], @w[j-3], @w[j-2], @w[j-1] if (i % @nk == 0) t0, t1, t2, t3 = S_BOX[t1] ^ RCON[i/@nk - 1], S_BOX[t2], S_BOX[t3], S_BOX[t0] elsif (@nk > 6) && (i % @nk == 4) t0, t1, t2, t3 = S_BOX[t0], S_BOX[t1], S_BOX[t2], S_BOX[t3] end @w[j], @w[j+1], @w[j+2], @w[j+3] = @w[k] ^ t0, @w[k+1] ^ t1, @w[k+2] ^ t2, @w[k+3] ^ t3 end end protected :key_expansion def _encrypt_block addRoundKey 0 1.upto(@nr) do |n| subBytes shiftRows mixColumns unless n == @nr addRoundKey n end @state end protected :_encrypt_block def _decrypt_block addRoundKey @nr (@nr-1).downto(0) do |n| ishiftRows isubBytes addRoundKey n imixColumns unless n == 0 end @state end protected :_decrypt_block def xor(a,b) c = "" 16.times do |i| c << (a[i] ^ b[i]).chr end c end protected :xor def encrypt_block(block) @state = block.dup case @mode when 'ECB' _encrypt_block when 'CBC' @state = xor(block, @iv) @iv = _encrypt_block when 'OFB' @state = @iv.dup @iv = _encrypt_block xor(@iv, block) when 'CFB' @state = @iv.dup @iv = xor(_encrypt_block, block) end end def decrypt_block(block) @state = block.dup case @mode when 'ECB' _decrypt_block when 'CBC' o = xor(_decrypt_block, @iv) @iv = block o when 'OFB' @state = @iv.dup @iv = _encrypt_block xor(@iv, block) when 'CFB' @state = @iv.dup o = xor(_encrypt_block, block) @iv = block o end end def init(key_length, mode, key, iv = nil) @iv = "\000" * 16 @iv = iv if iv @nb = 4 @nk = 4 @nr = 10 @mode = 'ECB' @state = nil @w = [] case key_length when 128 @nk = 4 @nr = 10 when 192 @nk = 6 @nr = 12 when 256 @nk = 8 @nr = 14 else raise 'Bad Key length' end case mode when 'ECB', 'CBC', 'OFB', 'CFB' @mode = mode else raise 'Bad AES mode' end key_expansion key end def initialize(key_length, mode, key, iv = nil) init(key_length, mode, key, iv) end end # class aes slowaes-0.1a1/ruby/lib/ruby-aes.rb0000644000175000017500000001452612126341024016053 0ustar bartmbartm=begin This file is a part of ruby-aes Written by Alex Boussinet Modified by Mark Percival to support OpenSSL ==Valid modes are: * ECB (Electronic Code Book) * CBC (Cipher Block Chaining) * OFB (Output Feedback) * CFB (Cipher Feedback) ==Valid key length: * 128 bits * 192 bits * 256 bits ==API calls: Default key_length: 128 Default mode: 'ECB' Default IV: 16 null chars ("00" * 16 in hex format) Default key: 16 null chars ("00" * 16 in hex format) Default input text: "PLAINTEXT" Aes.check_key(key_string, key_length) Aes.check_iv(iv_string) Aes.check_kl(key_length) Aes.check_mode(mode) Aes.init(key_length, mode, key, iv) Aes.encrypt_block(key_length, mode, key, iv, block) # no padding Aes.decrypt_block(key_length, mode, key, iv, block) # no padding Aes.encrypt_buffer(key_length, mode, key, iv, block) # padding Aes.decrypt_buffer(key_length, mode, key, iv, block) # padding Aes.encrypt_stream(key_length, mode, key, iv, sin, sout) Aes.decrypt_stream(key_length, mode, key, iv, sin, sout) Aes.bs() # block size for read operations (stream) Aes.bs=(bs) ==OpenSSL calls Aes.openssl_encrypt(password, text, [{size, mode, salt}]) Aes.openssl_decrypt(password, ciphertext, [{size, mode, salt}]) Salt should be passed in as a hex string Ex. "AABBCCDDEEFF1122" =end module Aes require File.join(File.dirname(__FILE__), 'ruby-aes', 'aes_alg') @@aes = nil @@bs = 4096 def Aes.bs(); return @@bs end def Aes.bs=(bs); @@bs = bs.to_i; @@bs==0 ? 4096 : @@bs = @@bs - @@bs%16 end def Aes.check_key(key_string, kl = 128) kl = Aes.check_kl(kl) k = key_string ? key_string.length : 0 raise "Bad key string or bad key length" if (k != kl/8) && (k != kl/4) hex = (key_string =~ /[a-f0-9A-F]{#{k}}/) == 0 && (k == kl/4) bin = ! hex if ! (([32, 48, 64].include?(k) && hex) || ([16, 24, 32].include?(k) && bin)) raise "Bad key string" end hex ? [key_string].pack("H*") : key_string end def Aes.check_iv(iv_string) k = iv_string.length hex = (iv_string =~ /[a-f0-9A-F]{#{k}}/) == 0 bin = ! hex if k == 32 && hex return [iv_string].pack("H*") elsif k == 16 && bin return iv_string else raise "Bad IV string" end end def Aes.check_mode (mode) case mode when 'ECB', 'CBC', 'OFB', 'CFB' else raise "Bad cipher mode" end mode end def Aes.check_kl(key_length) case key_length when 128, 192, 256 else raise "Bad key length" end key_length end def Aes.init(keyl, mode, key, iv) unless @@aes @@aes = AesAlg.new(Aes.check_kl(keyl), Aes.check_mode(mode), Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil) else @@aes.init(Aes.check_kl(keyl), Aes.check_mode(mode), Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil) end end def Aes.encrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT") raise "Bad Block size" if block.length < 16 || block.length > 16 Aes.init(keyl, mode, key, iv) @@aes.encrypt_block(block) end def Aes.decrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT") Aes.init(keyl, mode, key, iv) @@aes.decrypt_block(block) end def Aes.encrypt_buffer(keyl, mode, key, iv, buffer = "PLAINTEXT") Aes.init(keyl, mode, key, iv) @@aes.encrypt_buffer(buffer) end def Aes.decrypt_buffer(keyl, mode, key, iv, buffer = "DEFAULT PLAINTXT") Aes.init(keyl, mode, key, iv) @@aes.decrypt_buffer(buffer) end def Aes.encrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT) Aes.init(keyl, mode, key, iv) case sout when String, Array, IO else raise "Bad output stream (String, Array, IO)" end case sin when String sout << @@aes.encrypt_buffer(sin) when IO while buf = sin.read(@@bs) if buf.length == @@bs sout << @@aes.encrypt_blocks(buf) else sout << @@aes.encrypt_buffer(buf) end end else raise "Bad input stream (String, IO)" end end def Aes.decrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT) Aes.init(keyl, mode, key, iv) case sout when String, Array, IO else raise "Bad output stream (String, Array, IO)" end case sin when String sout << @@aes.decrypt_buffer(sin) when IO while buf = sin.read(@@bs)#+1) if buf.length == @@bs sout << @@aes.decrypt_blocks(buf) else sout << @@aes.decrypt_buffer(buf) end end else raise "Bad input stream (String, IO)" end end require 'digest/md5' def Aes.openssl_key(password, size = 256, salt = nil) rounds = (size/128.0).ceil + 1 md5_hash = [] unless salt salt = '' 8.times {salt += rand(255).chr} end ps = password + salt result = md5_hash[0] = Digest::MD5.digest(ps) 1.upto(rounds) do |i| md5_hash[i] = Digest::MD5.digest(md5_hash[i-1] + ps) result = result + md5_hash[i] end { :key => result[0, (size/8)], :iv => result[(size/8), 16], :salt => salt } end def Aes.openssl_encrypt(password, buffer = "PLAINTEXT", options = {}) options[:mode] = options[:mode] ? options[:mode] : 'CBC' options[:size] = options[:size] ? options[:size] : 256 options[:salt] = options[:salt].unpack('a2'*8).map{|x| x.hex}.pack('c'*8) if options[:salt] k = openssl_key(password, options[:size], options[:salt]) raw_enc = Aes.encrypt_buffer(options[:size], options[:mode], k[:key], k[:iv], buffer) { :salted => "Salted__" + k[:salt] + raw_enc, :raw => raw_enc, :salt => k[:salt].unpack("H*").first, :key => k[:key].unpack("H*").first, :iv => k[:iv].unpack("H*").first } end def Aes.openssl_decrypt(password, buffer = "CIPHER TEXT", options = {}) options[:mode] = options[:mode] ? options[:mode] : 'CBC' options[:size] = options[:size] ? options[:size] : 256 k = openssl_key(password, options[:size], buffer[8,8]) raw_dec = Aes.decrypt_buffer(options[:size], options[:mode], k[:key], k[:iv], buffer) { :raw => raw_dec, :salt => k[:salt].unpack("H*").first, :key => k[:key].unpack("H*").first, :iv => k[:iv].unpack("H*").first } end end # end Aes slowaes-0.1a1/js/0000755000175000017500000000000012126341052012655 5ustar bartmbartmslowaes-0.1a1/js/cryptoHelpers.js0000644000175000017500000001134512126341025016062 0ustar bartmbartm/* * cryptoHelpers.js: implements AES - Advanced Encryption Standard * from the SlowAES project, http://code.google.com/p/slowaes/ * * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), * Mark Percival ( http://mpercival.com ), * Johan Sundstrom ( http://ecmanaut.blogspot.com ), * John Resig ( http://ejohn.org ) * * Licensed under the Apache License, Version 2.0 * http://www.apache.org/licenses/ */ var cryptoHelpers = { // encodes a unicode string to UTF8 (8 bit characters are critical to AES functioning properly) encode_utf8:function(s) { try{return unescape(encodeURIComponent(s));} catch(e){throw 'error during utf8 encoding: cryptoHelpers.encode_utf8.';} }, // decodes a UTF8 string back to unicode decode_utf8:function(s) { try{return decodeURIComponent(escape(s));} catch(e){throw('error during utf8 decoding: cryptoHelpers.decode_utf8.');} }, //convert a number array to a hex string toHex:function() { var array = []; if(arguments.length == 1 && arguments[0].constructor == Array) array = arguments[0]; else array = arguments; var ret = ''; for(var i = 0;i < array.length;i++) ret += (array[i] < 16 ? '0' : '') + array[i].toString(16); return ret.toLowerCase(); }, //convert a hex string to a number array toNumbers:function(s) { var ret = []; s.replace(/(..)/g,function(s){ ret.push(parseInt(s,16)); }); return ret; }, // get a random number in the range [min,max] getRandom:function(min,max) { if(min === null) min = 0; if(max === null) max = 1; return Math.floor(Math.random()*(max+1)) + min; }, generateSharedKey:function(len) { if(len === null) len = 16; var key = []; for(var i = 0; i < len*2; i++) key.push(this.getRandom(0,255)); return key; }, generatePrivateKey:function(s,size) { var sha = jsHash.sha2.arr_sha256(s); return sha.slice(0,size); }, convertStringToByteArray: function(s) { var byteArray = []; for(var i = 0;i < s.length;i++) { byteArray.push(s.charCodeAt(i)); } return byteArray; }, convertByteArrayToString: function(byteArray) { var s = ''; for(var i = 0;i < byteArray.length;i++) { s += String.fromCharCode(byteArray[i]) } return s; }, base64: { // Takes a Nx16x1 byte array and converts it to Base64 chars: [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=', // for decoding purposes ], encode_line: function(flatArr){ var b64 = ''; for (var i = 0; i < flatArr.length; i += 3){ b64 += this.chars[flatArr[i] >> 2]; b64 += this.chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)]; if (!(flatArr[i + 1] == null)){ b64 += this.chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)]; }else{ b64 += '='; } if (!(flatArr[i + 2] == null)){ b64 += this.chars[flatArr[i + 2] & 63]; }else{ b64 += '='; } } return b64; }, encode: function(flatArr) { var b64 = this.encode_line(flatArr); // OpenSSL is super particular about line breaks var broken_b64 = b64.slice(0, 64) + '\n'; for (var i = 1; i < (Math.ceil(b64.length / 64)); i++) { broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n'); } return broken_b64; }, decode: function(string) { string = string.replace(/[\r\n\t ]+/g, '') + '===='; // drop all whitespaces and pad with '=' (end of b64 marker) var flatArr = []; var c = []; var b = []; for (var i = 0; ; i = i + 4){ c[0] = this.chars.indexOf(string.charAt(i)); if(c[0] == 64){ return flatArr; } c[1] = this.chars.indexOf(string.charAt(i + 1)); c[2] = this.chars.indexOf(string.charAt(i + 2)); c[3] = this.chars.indexOf(string.charAt(i + 3)); if( (c[0] < 0) || // char1 is wrong (c[1] < 0) || (c[1] == 64) || // char2 is wrong (c[2] < 0) || // char3 is neither an valid char nor '=' (c[3] < 0) // char4 is neither an valid char nor '=' ){ throw 'error during base64 decoding at pos '+i+': cryptoHelpers.base64.decode.'; } flatArr.push((c[0] << 2) | (c[1] >> 4)); if(c[2] >= 0 && c[2] < 64){ flatArr.push(((c[1] & 15) << 4) | (c[2] >> 2)); if(c[3] >= 0 && c[2] < 64){ flatArr.push(((c[2] & 3) << 6) | c[3]); } } } }, }, }; slowaes-0.1a1/js/jsHash.js0000644000175000017500000001164312126341025014440 0ustar bartmbartm/* * jsHash.js: implements AES - Advanced Encryption Standard * from the SlowAES project, http://code.google.com/p/slowaes/ * * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ) * * Licensed under the Apache License, Version 2.0 * http://www.apache.org/licenses/ * * sha2 portions adapted from jsSHA2 ( http://anmar.eu.org/projects/jssha2/ ) * Copyright Angel Marin 2003-2004 - http://anmar.eu.org/ * Distributed under the BSD License */ var jsHash = { sha2:{ chrsz:8, /* bits per input character. 8 - ASCII; 16 - Unicode */ hexcase:0,/* hex output format. 0 - lowercase; 1 - uppercase */ safe_add:function(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); }, S:function(X, n) {return ( X >>> n ) | (X << (32 - n));}, R:function(X, n) {return ( X >>> n );}, Ch:function(x, y, z) {return ((x & y) ^ ((~x) & z));}, Maj:function(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}, Sigma0256:function(x) {return (this.S(x, 2) ^ this.S(x, 13) ^ this.S(x, 22));}, Sigma1256:function(x) {return (this.S(x, 6) ^ this.S(x, 11) ^ this.S(x, 25));}, Gamma0256:function(x) {return (this.S(x, 7) ^ this.S(x, 18) ^ this.R(x, 3));}, Gamma1256:function(x) {return (this.S(x, 17) ^ this.S(x, 19) ^ this.R(x, 10));}, core_sha256:function(m, l) { var K = [ 0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5, 0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174, 0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA, 0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967, 0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85, 0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070, 0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3, 0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2]; var HASH = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19]; var W = []; var a, b, c, d, e, f, g, h, i, j; var T1, T2; /* append padding */ m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; for ( var i = 0; i>5] |= (str.charCodeAt(i / this.chrsz) & mask) << (24 - i%32); return bin; }, binb2str:function(bin) { var str = ""; var mask = (1 << this.chrsz) - 1; for(var i = 0; i < bin.length * 32; i += this.chrsz) str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask); return str; }, binb2arr:function(bin) { var array = []; var mask = (1 << this.chrsz) - 1; for(var i = 0; i < bin.length * 32; i += this.chrsz) array.push((bin[i>>5] >>> (24 - i%32)) & mask); return array; }, binb2hex:function(binarray) { var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for(var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); } return str; }, hex_sha256:function(s){return this.binb2hex(this.core_sha256(this.str2binb(s),s.length * this.chrsz));}, arr_sha256:function(s){return this.binb2arr(this.core_sha256(this.str2binb(s),s.length * this.chrsz));}, str_sha256:function(s){return this.binb2str(this.core_sha256(this.str2binb(s),s.length * this.chrsz));} } };slowaes-0.1a1/js/aes.js0000644000175000017500000007470612126341025014001 0ustar bartmbartm/* * aes.js: implements AES - Advanced Encryption Standard * from the SlowAES project, http://code.google.com/p/slowaes/ * * Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), * Mark Percival ( http://mpercival.com ), * * Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) * * Licensed under the Apache License, Version 2.0 * http://www.apache.org/licenses/ */ var slowAES = { /* * START AES SECTION */ aes:{ // structure of valid key sizes keySize:{ SIZE_128:16, SIZE_192:24, SIZE_256:32 }, // Rijndael S-box sbox:[ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ], // Rijndael Inverted S-box rsbox: [ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d ], /* rotate the word eight bits to the left */ rotate:function(word) { var c = word[0]; for (var i = 0; i < 3; i++) word[i] = word[i+1]; word[3] = c; return word; }, // Rijndael Rcon Rcon:[ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb ], G2X: [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 ], G3X: [ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a ], G9X: [ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 ], GBX: [ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 ], GDX: [ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 ], GEX: [ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d ], // Key Schedule Core core:function(word,iteration) { /* rotate the 32-bit word 8 bits to the left */ word = this.rotate(word); /* apply S-Box substitution on all 4 parts of the 32-bit word */ for (var i = 0; i < 4; ++i) word[i] = this.sbox[word[i]]; /* XOR the output of the rcon operation with i to the first part (leftmost) only */ word[0] = word[0]^this.Rcon[iteration]; return word; }, /* Rijndael's key expansion * expands an 128,192,256 key into an 176,208,240 bytes key * * expandedKey is a pointer to an char array of large enough size * key is a pointer to a non-expanded key */ expandKey:function(key,size) { var expandedKeySize = (16*(this.numberOfRounds(size)+1)); /* current expanded keySize, in bytes */ var currentSize = 0; var rconIteration = 1; var t = []; // temporary 4-byte variable var expandedKey = []; for(var i = 0;i < expandedKeySize;i++) expandedKey[i] = 0; /* set the 16,24,32 bytes of the expanded key to the input key */ for (var j = 0; j < size; j++) expandedKey[j] = key[j]; currentSize += size; while (currentSize < expandedKeySize) { /* assign the previous 4 bytes to the temporary value t */ for (var k = 0; k < 4; k++) t[k] = expandedKey[(currentSize - 4) + k]; /* every 16,24,32 bytes we apply the core schedule to t * and increment rconIteration afterwards */ if(currentSize % size == 0) t = this.core(t, rconIteration++); /* For 256-bit keys, we add an extra sbox to the calculation */ if(size == this.keySize.SIZE_256 && ((currentSize % size) == 16)) for(var l = 0; l < 4; l++) t[l] = this.sbox[t[l]]; /* We XOR t with the four-byte block 16,24,32 bytes before the new expanded key. * This becomes the next four bytes in the expanded key. */ for(var m = 0; m < 4; m++) { expandedKey[currentSize] = expandedKey[currentSize - size] ^ t[m]; currentSize++; } } return expandedKey; }, // Adds (XORs) the round key to the state addRoundKey:function(state,roundKey) { for (var i = 0; i < 16; i++) state[i] ^= roundKey[i]; return state; }, // Creates a round key from the given expanded key and the // position within the expanded key. createRoundKey:function(expandedKey,roundKeyPointer) { var roundKey = []; for (var i = 0; i < 4; i++) for (var j = 0; j < 4; j++) roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]; return roundKey; }, /* substitute all the values from the state with the value in the SBox * using the state value as index for the SBox */ subBytes:function(state,isInv) { for (var i = 0; i < 16; i++) state[i] = isInv?this.rsbox[state[i]]:this.sbox[state[i]]; return state; }, /* iterate over the 4 rows and call shiftRow() with that row */ shiftRows:function(state,isInv) { for (var i = 0; i < 4; i++) state = this.shiftRow(state,i*4, i,isInv); return state; }, /* each iteration shifts the row to the left by 1 */ shiftRow:function(state,statePointer,nbr,isInv) { for (var i = 0; i < nbr; i++) { if(isInv) { var tmp = state[statePointer + 3]; for (var j = 3; j > 0; j--) state[statePointer + j] = state[statePointer + j-1]; state[statePointer] = tmp; } else { var tmp = state[statePointer]; for (var j = 0; j < 3; j++) state[statePointer + j] = state[statePointer + j+1]; state[statePointer + 3] = tmp; } } return state; }, // galois multiplication of 8 bit characters a and b galois_multiplication:function(a,b) { var p = 0; for(var counter = 0; counter < 8; counter++) { if((b & 1) == 1) p ^= a; if(p > 0x100) p ^= 0x100; var hi_bit_set = (a & 0x80); //keep p 8 bit a <<= 1; if(a > 0x100) a ^= 0x100; //keep a 8 bit if(hi_bit_set == 0x80) a ^= 0x1b; if(a > 0x100) a ^= 0x100; //keep a 8 bit b >>= 1; if(b > 0x100) b ^= 0x100; //keep b 8 bit } return p; }, // galois multipication of the 4x4 matrix mixColumns:function(state,isInv) { var column = []; /* iterate over the 4 columns */ for (var i = 0; i < 4; i++) { /* construct one column by iterating over the 4 rows */ for (var j = 0; j < 4; j++) column[j] = state[(j*4)+i]; /* apply the mixColumn on one column */ column = this.mixColumn(column,isInv); /* put the values back into the state */ for (var k = 0; k < 4; k++) state[(k*4)+i] = column[k]; } return state; }, // galois multipication of 1 column of the 4x4 matrix mixColumn:function(column,isInv) { var mult = []; if(isInv) mult = [14,9,13,11]; else mult = [2,1,1,3]; var cpy = []; for(var i = 0; i < 4; i++) cpy[i] = column[i]; column[0] = this.galois_multiplication(cpy[0],mult[0]) ^ this.galois_multiplication(cpy[3],mult[1]) ^ this.galois_multiplication(cpy[2],mult[2]) ^ this.galois_multiplication(cpy[1],mult[3]); column[1] = this.galois_multiplication(cpy[1],mult[0]) ^ this.galois_multiplication(cpy[0],mult[1]) ^ this.galois_multiplication(cpy[3],mult[2]) ^ this.galois_multiplication(cpy[2],mult[3]); column[2] = this.galois_multiplication(cpy[2],mult[0]) ^ this.galois_multiplication(cpy[1],mult[1]) ^ this.galois_multiplication(cpy[0],mult[2]) ^ this.galois_multiplication(cpy[3],mult[3]); column[3] = this.galois_multiplication(cpy[3],mult[0]) ^ this.galois_multiplication(cpy[2],mult[1]) ^ this.galois_multiplication(cpy[1],mult[2]) ^ this.galois_multiplication(cpy[0],mult[3]); return column; }, // applies the 4 operations of the forward round in sequence round:function(state, roundKey) { state = this.subBytes(state,false); state = this.shiftRows(state,false); state = this.mixColumns(state,false); state = this.addRoundKey(state, roundKey); return state; }, // applies the 4 operations of the inverse round in sequence invRound:function(state,roundKey) { state = this.shiftRows(state,true); state = this.subBytes(state,true); state = this.addRoundKey(state, roundKey); state = this.mixColumns(state,true); return state; }, /* * Perform the initial operations, the standard round, and the final operations * of the forward aes, creating a round key for each round */ main:function(state,expandedKey,nbrRounds) { state = this.addRoundKey(state, this.createRoundKey(expandedKey,0)); for (var i = 1; i < nbrRounds; i++) state = this.round(state, this.createRoundKey(expandedKey,16*i)); state = this.subBytes(state,false); state = this.shiftRows(state,false); state = this.addRoundKey(state, this.createRoundKey(expandedKey,16*nbrRounds)); return state; }, /* * Perform the initial operations, the standard round, and the final operations * of the inverse aes, creating a round key for each round */ invMain:function(state, expandedKey, nbrRounds) { state = this.addRoundKey(state, this.createRoundKey(expandedKey,16*nbrRounds)); for (var i = nbrRounds-1; i > 0; i--) state = this.invRound(state, this.createRoundKey(expandedKey,16*i)); state = this.shiftRows(state,true); state = this.subBytes(state,true); state = this.addRoundKey(state, this.createRoundKey(expandedKey,0)); return state; }, numberOfRounds:function(size) { var nbrRounds; switch (size) /* set the number of rounds */ { case this.keySize.SIZE_128: nbrRounds = 10; break; case this.keySize.SIZE_192: nbrRounds = 12; break; case this.keySize.SIZE_256: nbrRounds = 14; break; default: return null; break; } return nbrRounds; }, // encrypts a 128 bit input block against the given key of size specified encrypt:function(input,key,size) { var output = []; var block = []; /* the 128 bit block to encode */ var nbrRounds = this.numberOfRounds(size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for (var i = 0; i < 4; i++) /* iterate over the columns */ for (var j = 0; j < 4; j++) /* iterate over the rows */ block[(i+(j*4))] = input[(i*4)+j]; /* expand the key into an 176, 208, 240 bytes key */ var expandedKey = this.expandKey(key, size); /* the expanded key */ /* encrypt the block using the expandedKey */ block = this.main(block, expandedKey, nbrRounds); for (var k = 0; k < 4; k++) /* unmap the block again into the output */ for (var l = 0; l < 4; l++) /* iterate over the rows */ output[(k*4)+l] = block[(k+(l*4))]; return output; }, // decrypts a 128 bit input block against the given key of size specified decrypt:function(input, key, size) { var output = []; var block = []; /* the 128 bit block to decode */ var nbrRounds = this.numberOfRounds(size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for (var i = 0; i < 4; i++) /* iterate over the columns */ for (var j = 0; j < 4; j++) /* iterate over the rows */ block[(i+(j*4))] = input[(i*4)+j]; /* expand the key into an 176, 208, 240 bytes key */ var expandedKey = this.expandKey(key, size); /* decrypt the block using the expandedKey */ block = this.invMain(block, expandedKey, nbrRounds); for (var k = 0; k < 4; k++)/* unmap the block again into the output */ for (var l = 0; l < 4; l++)/* iterate over the rows */ output[(k*4)+l] = block[(k+(l*4))]; return output; } }, /* * END AES SECTION */ /* * START MODE OF OPERATION SECTION */ //structure of supported modes of operation modeOfOperation:{ OFB:0, CFB:1, CBC:2 }, // get a 16 byte block (aes operates on 128bits) getBlock: function(bytesIn,start,end,mode) { if(end - start > 16) end = start + 16; return bytesIn.slice(start, end); }, /* * Mode of Operation Encryption * bytesIn - Input String as array of bytes * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ encrypt: function (bytesIn, mode, key, iv) { var size = key.length; if(iv.length%16) { throw 'iv length must be 128 bits.'; } // the AES input/output var byteArray = []; var input = []; var output = []; var ciphertext = []; var cipherOut = []; // char firstRound var firstRound = true; if (mode == this.modeOfOperation.CBC) this.padBytesIn(bytesIn); if (bytesIn !== null) { for (var j = 0;j < Math.ceil(bytesIn.length/16); j++) { var start = j*16; var end = j*16+16; if(j*16+16 > bytesIn.length) end = bytesIn.length; byteArray = this.getBlock(bytesIn,start,end,mode); if (mode == this.modeOfOperation.CFB) { if (firstRound) { output = this.aes.encrypt(iv, key, size); firstRound = false; } else output = this.aes.encrypt(input, key, size); for (var i = 0; i < 16; i++) ciphertext[i] = byteArray[i] ^ output[i]; for(var k = 0;k < end-start;k++) cipherOut.push(ciphertext[k]); input = ciphertext; } else if (mode == this.modeOfOperation.OFB) { if (firstRound) { output = this.aes.encrypt(iv, key, size); firstRound = false; } else output = this.aes.encrypt(input, key, size); for (var i = 0; i < 16; i++) ciphertext[i] = byteArray[i] ^ output[i]; for(var k = 0;k < end-start;k++) cipherOut.push(ciphertext[k]); input = output; } else if (mode == this.modeOfOperation.CBC) { for (var i = 0; i < 16; i++) input[i] = byteArray[i] ^ ((firstRound) ? iv[i] : ciphertext[i]); firstRound = false; ciphertext = this.aes.encrypt(input, key, size); // always 16 bytes because of the padding for CBC for(var k = 0;k < 16;k++) cipherOut.push(ciphertext[k]); } } } return cipherOut; }, /* * Mode of Operation Decryption * cipherIn - Encrypted String as array of bytes * originalsize - The unencrypted string length - required for CBC * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ decrypt:function(cipherIn,mode,key,iv) { var size = key.length; if(iv.length%16) { throw 'iv length must be 128 bits.'; } // the AES input/output var ciphertext = []; var input = []; var output = []; var byteArray = []; var bytesOut = []; // char firstRound var firstRound = true; if (cipherIn !== null) { for (var j = 0;j < Math.ceil(cipherIn.length/16); j++) { var start = j*16; var end = j*16+16; if(j*16+16 > cipherIn.length) end = cipherIn.length; ciphertext = this.getBlock(cipherIn,start,end,mode); if (mode == this.modeOfOperation.CFB) { if (firstRound) { output = this.aes.encrypt(iv, key, size); firstRound = false; } else output = this.aes.encrypt(input, key, size); for (i = 0; i < 16; i++) byteArray[i] = output[i] ^ ciphertext[i]; for(var k = 0;k < end-start;k++) bytesOut.push(byteArray[k]); input = ciphertext; } else if (mode == this.modeOfOperation.OFB) { if (firstRound) { output = this.aes.encrypt(iv, key, size); firstRound = false; } else output = this.aes.encrypt(input, key, size); for (i = 0; i < 16; i++) byteArray[i] = output[i] ^ ciphertext[i]; for(var k = 0;k < end-start;k++) bytesOut.push(byteArray[k]); input = output; } else if(mode == this.modeOfOperation.CBC) { output = this.aes.decrypt(ciphertext, key, size); for (i = 0; i < 16; i++) byteArray[i] = ((firstRound) ? iv[i] : input[i]) ^ output[i]; firstRound = false; for(var k = 0;k < end-start;k++) bytesOut.push(byteArray[k]); input = ciphertext; } } if(mode == this.modeOfOperation.CBC) this.unpadBytesOut(bytesOut); } return bytesOut; }, padBytesIn: function(data) { var len = data.length; var padByte = 16 - (len % 16); for (var i = 0; i < padByte; i++) { data.push(padByte); } }, unpadBytesOut: function(data) { var padCount = 0; var padByte = -1; var blockSize = 16; for (var i = data.length - 1; i >= data.length-1 - blockSize; i--) { if (data[i] <= blockSize) { if (padByte == -1) padByte = data[i]; if (data[i] != padByte) { padCount = 0; break; } padCount++; } else break; if (padCount == padByte) break; } if (padCount > 0) data.splice(data.length - padCount, padCount); } /* * END MODE OF OPERATION SECTION */ }; slowaes-0.1a1/php/0000755000175000017500000000000012126341052013030 5ustar bartmbartmslowaes-0.1a1/php/cryptoHelpers.php0000644000175000017500000000523712126341025016413 0ustar bartmbartm 0; $j--) $state[$statePointer + $j] = $state[$statePointer + $j-1]; $state[$statePointer] = $tmp; } else { $tmp = $state[$statePointer]; for ($j = 0; $j < 3; $j++) $state[$statePointer + $j] = $state[$statePointer + $j+1]; $state[$statePointer + 3] = $tmp; } } return $state; } // galois multiplication of 8 bit characters a and b private static function galois_multiplication($a,$b){ $p = 0; for($counter = 0; $counter < 8; $counter++) { if(($b & 1) == 1) $p ^= $a; if($p > 0x100) $p ^= 0x100; $hi_bit_set = ($a & 0x80); //keep p 8 bit $a <<= 1; if($a > 0x100) $a ^= 0x100; //keep a 8 bit if($hi_bit_set == 0x80) $a ^= 0x1b; if($a > 0x100) $a ^= 0x100; //keep a 8 bit $b >>= 1; if($b > 0x100) $b ^= 0x100; //keep b 8 bit } return $p; } // galois multipication of 1 column of the 4x4 matrix private static function mixColumn($column,$isInv){ if($isInv) $mult = array(14,9,13,11); else $mult = array(2,1,1,3); $cpy = array(); for($i = 0; $i < 4; $i++) $cpy[$i] = $column[$i]; $column[0] = self::galois_multiplication($cpy[0],$mult[0]) ^ self::galois_multiplication($cpy[3],$mult[1]) ^ self::galois_multiplication($cpy[2],$mult[2]) ^ self::galois_multiplication($cpy[1],$mult[3]); $column[1] = self::galois_multiplication($cpy[1],$mult[0]) ^ self::galois_multiplication($cpy[0],$mult[1]) ^ self::galois_multiplication($cpy[3],$mult[2]) ^ self::galois_multiplication($cpy[2],$mult[3]); $column[2] = self::galois_multiplication($cpy[2],$mult[0]) ^ self::galois_multiplication($cpy[1],$mult[1]) ^ self::galois_multiplication($cpy[0],$mult[2]) ^ self::galois_multiplication($cpy[3],$mult[3]); $column[3] = self::galois_multiplication($cpy[3],$mult[0]) ^ self::galois_multiplication($cpy[2],$mult[1]) ^ self::galois_multiplication($cpy[1],$mult[2]) ^ self::galois_multiplication($cpy[0],$mult[3]); return $column; } // galois multipication of the 4x4 matrix private static function mixColumns($state,$isInv){ $column = array(); /* iterate over the 4 columns */ for ($i = 0; $i < 4; $i++) { /* construct one column by iterating over the 4 rows */ for ($j = 0; $j < 4; $j++) $column[$j] = $state[($j*4)+$i]; /* apply the mixColumn on one column */ $column = self::mixColumn($column,$isInv); /* put the values back into the state */ for ($k = 0; $k < 4; $k++) $state[($k*4)+$i] = $column[$k]; } return $state; } // applies the 4 operations of the forward round in sequence private static function round($state, $roundKey){ $state = self::subBytes($state,false); $state = self::shiftRows($state,false); $state = self::mixColumns($state,false); $state = self::addRoundKey($state, $roundKey); return $state; } // applies the 4 operations of the inverse round in sequence private static function invRound($state,$roundKey){ $state = self::shiftRows($state,true); $state = self::subBytes($state,true); $state = self::addRoundKey($state, $roundKey); $state = self::mixColumns($state,true); return $state; } /* * Perform the initial operations, the standard round, and the final operations * of the forward aes, creating a round key for each round */ private static function main($state,$expandedKey,$nbrRounds){ $state = self::addRoundKey($state, self::createRoundKey($expandedKey,0)); for ($i = 1; $i < $nbrRounds; $i++) $state = self::round($state, self::createRoundKey($expandedKey,16*$i)); $state = self::subBytes($state,false); $state = self::shiftRows($state,false); $state = self::addRoundKey($state, self::createRoundKey($expandedKey,16*$nbrRounds)); return $state; } /* * Perform the initial operations, the standard round, and the final operations * of the inverse aes, creating a round key for each round */ private static function invMain($state, $expandedKey, $nbrRounds){ $state = self::addRoundKey($state, self::createRoundKey($expandedKey,16*$nbrRounds)); for ($i = $nbrRounds-1; $i > 0; $i--) $state = self::invRound($state, self::createRoundKey($expandedKey,16*i)); $state = self::shiftRows($state,true); $state = self::subBytes($state,true); $state = self::addRoundKey($state, self::createRoundKey($expandedKey,0)); return $state; } private static function numberOfRounds($size){ $nbrRounds; switch ($size) /* set the number of rounds */ { case self::keySize_128: $nbrRounds = 10; break; case self::keySize_192: $nbrRounds = 12; break; case self::keySize_256: $nbrRounds = 14; break; default: return null; break; } return $nbrRounds; } // encrypts a 128 bit input block against the given key of size specified private static function encryptBlock($input,$key,$size){ $output = array(); $block = array(); /* the 128 bit block to encode */ $nbrRounds = self::numberOfRounds($size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for ($i = 0; $i < 4; $i++) /* iterate over the columns */ for ($j = 0; $j < 4; $j++) /* iterate over the rows */ $block[($i+($j*4))] = $input[($i*4)+$j]; /* expand the key into an 176, 208, 240 bytes key */ $expandedKey = self::expandKey($key, $size); /* the expanded key */ /* encrypt the block using the expandedKey */ $block = self::main($block, $expandedKey, $nbrRounds); for ($k = 0; $k < 4; $k++) /* unmap the block again into the output */ for ($l = 0; $l < 4; $l++) /* iterate over the rows */ $output[($k*4)+$l] = $block[($k+($l*4))]; return $output; } // decrypts a 128 bit input block against the given key of size specified private static function decryptBlock($input, $key, $size){ $output = array(); $block = array(); /* the 128 bit block to decode */ $nbrRounds = self::numberOfRounds($size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for ($i = 0; $i < 4; $i++) /* iterate over the columns */ for ($j = 0; $j < 4; $j++) /* iterate over the rows */ $block[($i+($j*4))] = $input[($i*4)+$j]; /* expand the key into an 176, 208, 240 bytes key */ $expandedKey = self::expandKey($key, $size); /* decrypt the block using the expandedKey */ $block = self::invMain($block, $expandedKey, $nbrRounds); for ($k = 0; $k < 4; $k++)/* unmap the block again into the output */ for ($l = 0; $l < 4; $l++)/* iterate over the rows */ $output[($k*4)+$l] = $block[($k+($l*4))]; return $output; } /* * END AES SECTION */ /* * START MODE OF OPERATION SECTION */ //structure of supported modes of operation const modeOfOperation_OFB = 0; const modeOfOperation_CFB = 1; const modeOfOperation_CBC = 2; // gets a properly padded block private static function getPaddedBlock($bytesIn,$start,$end,$mode){ if($end - $start > 16) $end = $start + 16; $xarray = array_slice($bytesIn, $start, $end-$start); $cpad = 16 - count($xarray); while(count($xarray) < 16){ array_push($xarray, $cpad); } return $xarray; } /* * Mode of Operation Encryption * bytesIn - Input String as array of bytes * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ public static function encrypt($bytesIn, $mode, $key, $size, $iv){ if(count($key)%$size) { throw new Exception('Key length does not match specified size.'); } if(count($iv)%16) { throw new Exception('iv length must be 128 bits.'); } // the AES input/output $byteArray = array(); $input = array(); $output = array(); $ciphertext = array(); $cipherOut = array(); // char firstRound $firstRound = true; if ($bytesIn !== null) { for ($j = 0;$j < ceil(count($bytesIn)/16); $j++) { $start = $j*16; $end = $j*16+16; if($j*16+16 > count($bytesIn)) $end = count($bytesIn); $byteArray = self::getPaddedBlock($bytesIn,$start,$end,$mode); if ($mode == self::modeOfOperation_CFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $ciphertext[$i] = $byteArray[$i] ^ $output[$i]; for($k = 0;$k < $end-$start;$k++) array_push($cipherOut, $ciphertext[$k]); $input = $ciphertext; } else if ($mode == self::modeOfOperation_OFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $ciphertext[$i] = $byteArray[$i] ^ $output[$i]; for($k = 0;$k < $end-$start;$k++) array_push($cipherOut, $ciphertext[$k]); $input = $output; } else if ($mode == self::modeOfOperation_CBC) { for ($i = 0; $i < 16; $i++) $input[$i] = $byteArray[$i] ^ (($firstRound) ? $iv[$i] : $ciphertext[$i]); $firstRound = false; $ciphertext = self::encryptBlock($input, $key, $size); // always 16 bytes because of the padding for CBC for($k = 0;$k < 16;$k++) array_push($cipherOut, $ciphertext[$k]); } } } return array('mode' => $mode, 'originalsize' => count($bytesIn), 'cipher' => $cipherOut); } /* * Mode of Operation Decryption * cipherIn - Encrypted String as array of bytes * originalsize - The unencrypted string length - required for CBC * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ public static function decrypt($cipherIn,$originalsize,$mode,$key,$size,$iv) { if(count($key)%$size) { throw new Exception('Key length does not match specified size.'); return null; } if(count($iv)%16) { throw new Exception('iv length must be 128 bits.'); } // the AES input/output $ciphertext = array(); $input = array(); $output = array(); $byteArray = array(); $bytesOut = array(); // char firstRound $firstRound = true; if ($cipherIn !== null) { for ($j = 0;$j < ceil(count($cipherIn)/16); $j++) { $start = $j*16; $end = $j*16+16; if($j*16+16 > count($cipherIn)) $end = count($cipherIn); $ciphertext = self::getPaddedBlock($cipherIn,$start,$end,$mode); if ($mode == self::modeOfOperation_CFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = $output[$i] ^ $ciphertext[$i]; for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $ciphertext; } else if ($mode == self::modeOfOperation_OFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = $output[$i] ^ $ciphertext[$i]; for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $output; } else if($mode == self::modeOfOperation_CBC) { $output = self::decryptBlock($ciphertext, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = (($firstRound) ? $iv[$i] : $input[$i]) ^ $output[$i]; $firstRound = false; if ($originalsize < $end) for($k = 0;$k < $originalsize-$start;$k++) array_push($bytesOut, $byteArray[$k]); else for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $ciphertext; } } } return $bytesOut; } /* * END MODE OF OPERATION SECTION */ } ?>slowaes-0.1a1/php/aes_fast.php0000644000175000017500000007274612126341025015346 0ustar bartmbartm 0; $j--) $state[$statePointer + $j] = $state[$statePointer + $j-1]; $state[$statePointer] = $tmp; } else { $tmp = $state[$statePointer]; for ($j = 0; $j < 3; $j++) $state[$statePointer + $j] = $state[$statePointer + $j+1]; $state[$statePointer + 3] = $tmp; } } return $state; } // galois multipication of the 4x4 matrix private static function mixColumns($state,$isInv){ $t = array(); if (!$isInv) { for ($c = 0; $c < 4; $c++) { $t[ $c] = self::$G2X[$state[$c]] ^ self::$G3X[$state[4+$c]] ^ $state[8+$c] ^ $state[12+$c]; $t[ 4+$c] = $state[$c] ^ self::$G2X[$state[4+$c]] ^ self::$G3X[$state[8+$c]] ^ $state[12+$c]; $t[ 8+$c] = $state[$c] ^ $state[4+$c] ^ self::$G2X[$state[8+$c]] ^ self::$G3X[$state[12+$c]]; $t[12+$c] = self::$G3X[$state[$c]] ^ $state[4+$c] ^ $state[8+$c] ^ self::$G2X[$state[12+$c]]; } }else { for ($c = 0; $c < 16; $c+=4) { $t[ $c] = self::$GEX[$state[$c]] ^ self::$GBX[$state[4+$c]] ^ self::$GDX[$state[8+$c]] ^ self::$G9X[$state[12+$c]]; $t[1+$c] = self::$G9X[$state[$c]] ^ self::$GEX[$state[4+$c]] ^ self::$GBX[$state[8+$c]] ^ self::$GDX[$state[12+$c]]; $t[2+$c] = self::$GDX[$state[$c]] ^ self::$G9X[$state[4+$c]] ^ self::$GEX[$state[8+$c]] ^ self::$GBX[$state[12+$c]]; $t[3+$c] = self::$GBX[$state[$c]] ^ self::$GDX[$state[4+$c]] ^ self::$G9X[$state[8+$c]] ^ self::$GEX[$state[12+$c]]; } } return $t; } // applies the 4 operations of the forward round in sequence private static function round($state, $roundKey){ $state = self::subBytes($state,false); $state = self::shiftRows($state,false); $state = self::mixColumns($state,false); $state = self::addRoundKey($state, $roundKey); return $state; } // applies the 4 operations of the inverse round in sequence private static function invRound($state,$roundKey){ $state = self::shiftRows($state,true); $state = self::subBytes($state,true); $state = self::addRoundKey($state, $roundKey); $state = self::mixColumns($state,true); return $state; } /* * Perform the initial operations, the standard round, and the final operations * of the forward aes, creating a round key for each round */ private static function main($state,$expandedKey,$nbrRounds){ $state = self::addRoundKey($state, self::createRoundKey($expandedKey,0)); for ($i = 1; $i < $nbrRounds; $i++) $state = self::round($state, self::createRoundKey($expandedKey,16*$i)); $state = self::subBytes($state,false); $state = self::shiftRows($state,false); $state = self::addRoundKey($state, self::createRoundKey($expandedKey,16*$nbrRounds)); return $state; } /* * Perform the initial operations, the standard round, and the final operations * of the inverse aes, creating a round key for each round */ private static function invMain($state, $expandedKey, $nbrRounds){ $state = self::addRoundKey($state, self::createRoundKey($expandedKey,16*$nbrRounds)); for ($i = $nbrRounds-1; $i > 0; $i--) $state = self::invRound($state, self::createRoundKey($expandedKey,16*i)); $state = self::shiftRows($state,true); $state = self::subBytes($state,true); $state = self::addRoundKey($state, self::createRoundKey($expandedKey,0)); return $state; } private static function numberOfRounds($size){ $nbrRounds; switch ($size) /* set the number of rounds */ { case self::keySize_128: $nbrRounds = 10; break; case self::keySize_192: $nbrRounds = 12; break; case self::keySize_256: $nbrRounds = 14; break; default: return null; break; } return $nbrRounds; } // encrypts a 128 bit input block against the given key of size specified private static function encryptBlock($input,$key,$size){ $output = array(); $block = array(); /* the 128 bit block to encode */ $nbrRounds = self::numberOfRounds($size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for ($i = 0; $i < 4; $i++) /* iterate over the columns */ for ($j = 0; $j < 4; $j++) /* iterate over the rows */ $block[($i+($j*4))] = $input[($i*4)+$j]; /* expand the key into an 176, 208, 240 bytes key */ $expandedKey = self::expandKey($key, $size); /* the expanded key */ /* encrypt the block using the expandedKey */ $block = self::main($block, $expandedKey, $nbrRounds); for ($k = 0; $k < 4; $k++) /* unmap the block again into the output */ for ($l = 0; $l < 4; $l++) /* iterate over the rows */ $output[($k*4)+$l] = $block[($k+($l*4))]; return $output; } // decrypts a 128 bit input block against the given key of size specified private static function decryptBlock($input, $key, $size){ $output = array(); $block = array(); /* the 128 bit block to decode */ $nbrRounds = self::numberOfRounds($size); /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 */ for ($i = 0; $i < 4; $i++) /* iterate over the columns */ for ($j = 0; $j < 4; $j++) /* iterate over the rows */ $block[($i+($j*4))] = $input[($i*4)+$j]; /* expand the key into an 176, 208, 240 bytes key */ $expandedKey = self::expandKey($key, $size); /* decrypt the block using the expandedKey */ $block = self::invMain($block, $expandedKey, $nbrRounds); for ($k = 0; $k < 4; $k++)/* unmap the block again into the output */ for ($l = 0; $l < 4; $l++)/* iterate over the rows */ $output[($k*4)+$l] = $block[($k+($l*4))]; return $output; } /* * END AES SECTION */ /* * START MODE OF OPERATION SECTION */ //structure of supported modes of operation const modeOfOperation_OFB = 0; const modeOfOperation_CFB = 1; const modeOfOperation_CBC = 2; // gets a properly padded block private static function getPaddedBlock($bytesIn,$start,$end,$mode){ if($end - $start > 16) $end = $start + 16; $xarray = array_slice($bytesIn, $start, $end-$start); $cpad = 16 - count($xarray); while(count($xarray) < 16){ array_push($xarray, $cpad); } return $xarray; } /* * Mode of Operation Encryption * bytesIn - Input String as array of bytes * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ public static function encrypt($bytesIn, $mode, $key, $size, $iv){ if(count($key)%$size) { throw new Exception('Key length does not match specified size.'); } if(count($iv)%16) { throw new Exception('iv length must be 128 bits.'); } // the AES input/output $byteArray = array(); $input = array(); $output = array(); $ciphertext = array(); $cipherOut = array(); // char firstRound $firstRound = true; if ($bytesIn !== null) { for ($j = 0;$j < ceil(count($bytesIn)/16); $j++) { $start = $j*16; $end = $j*16+16; if($j*16+16 > count($bytesIn)) $end = count($bytesIn); $byteArray = self::getPaddedBlock($bytesIn,$start,$end,$mode); if ($mode == self::modeOfOperation_CFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $ciphertext[$i] = $byteArray[$i] ^ $output[$i]; for($k = 0;$k < $end-$start;$k++) array_push($cipherOut, $ciphertext[$k]); $input = $ciphertext; } else if ($mode == self::modeOfOperation_OFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $ciphertext[$i] = $byteArray[$i] ^ $output[$i]; for($k = 0;$k < $end-$start;$k++) array_push($cipherOut, $ciphertext[$k]); $input = $output; } else if ($mode == self::modeOfOperation_CBC) { for ($i = 0; $i < 16; $i++) $input[$i] = $byteArray[$i] ^ (($firstRound) ? $iv[$i] : $ciphertext[$i]); $firstRound = false; $ciphertext = self::encryptBlock($input, $key, $size); // always 16 bytes because of the padding for CBC for($k = 0;$k < 16;$k++) array_push($cipherOut, $ciphertext[$k]); } } } return array('mode' => $mode, 'originalsize' => count($bytesIn), 'cipher' => $cipherOut); } /* * Mode of Operation Decryption * cipherIn - Encrypted String as array of bytes * originalsize - The unencrypted string length - required for CBC * mode - mode of type modeOfOperation * key - a number array of length 'size' * size - the bit length of the key * iv - the 128 bit number array Initialization Vector */ public static function decrypt($cipherIn,$originalsize,$mode,$key,$size,$iv) { if(count($key)%$size) { throw new Exception('Key length does not match specified size.'); return null; } if(count($iv)%16) { throw new Exception('iv length must be 128 bits.'); } // the AES input/output $ciphertext = array(); $input = array(); $output = array(); $byteArray = array(); $bytesOut = array(); // char firstRound $firstRound = true; if ($cipherIn !== null) { for ($j = 0;$j < ceil(count($cipherIn)/16); $j++) { $start = $j*16; $end = $j*16+16; if($j*16+16 > count($cipherIn)) $end = count($cipherIn); $ciphertext = self::getPaddedBlock($cipherIn,$start,$end,$mode); if ($mode == self::modeOfOperation_CFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = $output[$i] ^ $ciphertext[$i]; for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $ciphertext; } else if ($mode == self::modeOfOperation_OFB) { if ($firstRound) { $output = self::encryptBlock($iv, $key, $size); $firstRound = false; } else $output = self::encryptBlock($input, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = $output[$i] ^ $ciphertext[$i]; for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $output; } else if($mode == self::modeOfOperation_CBC) { $output = self::decryptBlock($ciphertext, $key, $size); for ($i = 0; $i < 16; $i++) $byteArray[$i] = (($firstRound) ? $iv[$i] : $input[$i]) ^ $output[$i]; $firstRound = false; if ($originalsize < $end) for($k = 0;$k < $originalsize-$start;$k++) array_push($bytesOut, $byteArray[$k]); else for($k = 0;$k < $end-$start;$k++) array_push($bytesOut, $byteArray[$k]); $input = $ciphertext; } } } return $bytesOut; } /* * END MODE OF OPERATION SECTION */ } ?>slowaes-0.1a1/python/0000755000175000017500000000000012126341143013563 5ustar bartmbartmslowaes-0.1a1/python/aes.py0000644000175000017500000006605412126341025014717 0ustar bartmbartm#!/usr/bin/python # # aes.py: implements AES - Advanced Encryption Standard # from the SlowAES project, http://code.google.com/p/slowaes/ # # Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), # Alex Martelli ( http://www.aleax.it ) # # Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) # # Licensed under the Apache License, Version 2.0 # http://www.apache.org/licenses/ # import os import sys import math def append_PKCS7_padding(s): """return s padded to a multiple of 16-bytes by PKCS7 padding""" numpads = 16 - (len(s)%16) return s + numpads*chr(numpads) def strip_PKCS7_padding(s): """return s stripped of PKCS7 padding""" if len(s)%16 or not s: raise ValueError("String of len %d can't be PCKS7-padded" % len(s)) numpads = ord(s[-1]) if numpads > 16: raise ValueError("String ending with %r can't be PCKS7-padded" % s[-1]) return s[:-numpads] class AES(object): # valid key sizes keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32) # Rijndael S-box sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16] # Rijndael Inverted S-box rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d] def getSBoxValue(self,num): """Retrieves a given S-Box Value""" return self.sbox[num] def getSBoxInvert(self,num): """Retrieves a given Inverted S-Box Value""" return self.rsbox[num] def rotate(self, word): """ Rijndael's key schedule rotate operation. Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d Word is an char list of size 4 (32 bits overall). """ return word[1:] + word[:1] # Rijndael Rcon Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb ] def getRconValue(self, num): """Retrieves a given Rcon Value""" return self.Rcon[num] def core(self, word, iteration): """Key schedule core.""" # rotate the 32-bit word 8 bits to the left word = self.rotate(word) # apply S-Box substitution on all 4 parts of the 32-bit word for i in range(4): word[i] = self.getSBoxValue(word[i]) # XOR the output of the rcon operation with i to the first part # (leftmost) only word[0] = word[0] ^ self.getRconValue(iteration) return word def expandKey(self, key, size, expandedKeySize): """Rijndael's key expansion. Expands an 128,192,256 key into an 176,208,240 bytes key expandedKey is a char list of large enough size, key is the non-expanded key. """ # current expanded keySize, in bytes currentSize = 0 rconIteration = 1 expandedKey = [0] * expandedKeySize # set the 16, 24, 32 bytes of the expanded key to the input key for j in range(size): expandedKey[j] = key[j] currentSize += size while currentSize < expandedKeySize: # assign the previous 4 bytes to the temporary value t t = expandedKey[currentSize-4:currentSize] # every 16,24,32 bytes we apply the core schedule to t # and increment rconIteration afterwards if currentSize % size == 0: t = self.core(t, rconIteration) rconIteration += 1 # For 256-bit keys, we add an extra sbox to the calculation if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16): for l in range(4): t[l] = self.getSBoxValue(t[l]) # We XOR t with the four-byte block 16,24,32 bytes before the new # expanded key. This becomes the next four bytes in the expanded # key. for m in range(4): expandedKey[currentSize] = expandedKey[currentSize - size] ^ \ t[m] currentSize += 1 return expandedKey def addRoundKey(self, state, roundKey): """Adds (XORs) the round key to the state.""" for i in range(16): state[i] ^= roundKey[i] return state def createRoundKey(self, expandedKey, roundKeyPointer): """Create a round key. Creates a round key from the given expanded key and the position within the expanded key. """ roundKey = [0] * 16 for i in range(4): for j in range(4): roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j] return roundKey def galois_multiplication(self, a, b): """Galois multiplication of 8 bit characters a and b.""" p = 0 for counter in range(8): if b & 1: p ^= a hi_bit_set = a & 0x80 a <<= 1 # keep a 8 bit a &= 0xFF if hi_bit_set: a ^= 0x1b b >>= 1 return p # # substitute all the values from the state with the value in the SBox # using the state value as index for the SBox # def subBytes(self, state, isInv): if isInv: getter = self.getSBoxInvert else: getter = self.getSBoxValue for i in range(16): state[i] = getter(state[i]) return state # iterate over the 4 rows and call shiftRow() with that row def shiftRows(self, state, isInv): for i in range(4): state = self.shiftRow(state, i*4, i, isInv) return state # each iteration shifts the row to the left by 1 def shiftRow(self, state, statePointer, nbr, isInv): for i in range(nbr): if isInv: state[statePointer:statePointer+4] = \ state[statePointer+3:statePointer+4] + \ state[statePointer:statePointer+3] else: state[statePointer:statePointer+4] = \ state[statePointer+1:statePointer+4] + \ state[statePointer:statePointer+1] return state # galois multiplication of the 4x4 matrix def mixColumns(self, state, isInv): # iterate over the 4 columns for i in range(4): # construct one column by slicing over the 4 rows column = state[i:i+16:4] # apply the mixColumn on one column column = self.mixColumn(column, isInv) # put the values back into the state state[i:i+16:4] = column return state # galois multiplication of 1 column of the 4x4 matrix def mixColumn(self, column, isInv): if isInv: mult = [14, 9, 13, 11] else: mult = [2, 1, 1, 3] cpy = list(column) g = self.galois_multiplication column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \ g(cpy[2], mult[2]) ^ g(cpy[1], mult[3]) column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \ g(cpy[3], mult[2]) ^ g(cpy[2], mult[3]) column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \ g(cpy[0], mult[2]) ^ g(cpy[3], mult[3]) column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \ g(cpy[1], mult[2]) ^ g(cpy[0], mult[3]) return column # applies the 4 operations of the forward round in sequence def aes_round(self, state, roundKey): state = self.subBytes(state, False) state = self.shiftRows(state, False) state = self.mixColumns(state, False) state = self.addRoundKey(state, roundKey) return state # applies the 4 operations of the inverse round in sequence def aes_invRound(self, state, roundKey): state = self.shiftRows(state, True) state = self.subBytes(state, True) state = self.addRoundKey(state, roundKey) state = self.mixColumns(state, True) return state # Perform the initial operations, the standard round, and the final # operations of the forward aes, creating a round key for each round def aes_main(self, state, expandedKey, nbrRounds): state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0)) i = 1 while i < nbrRounds: state = self.aes_round(state, self.createRoundKey(expandedKey, 16*i)) i += 1 state = self.subBytes(state, False) state = self.shiftRows(state, False) state = self.addRoundKey(state, self.createRoundKey(expandedKey, 16*nbrRounds)) return state # Perform the initial operations, the standard round, and the final # operations of the inverse aes, creating a round key for each round def aes_invMain(self, state, expandedKey, nbrRounds): state = self.addRoundKey(state, self.createRoundKey(expandedKey, 16*nbrRounds)) i = nbrRounds - 1 while i > 0: state = self.aes_invRound(state, self.createRoundKey(expandedKey, 16*i)) i -= 1 state = self.shiftRows(state, True) state = self.subBytes(state, True) state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0)) return state # encrypts a 128 bit input block against the given key of size specified def encrypt(self, iput, key, size): output = [0] * 16 # the number of rounds nbrRounds = 0 # the 128 bit block to encode block = [0] * 16 # set the number of rounds if size == self.keySize["SIZE_128"]: nbrRounds = 10 elif size == self.keySize["SIZE_192"]: nbrRounds = 12 elif size == self.keySize["SIZE_256"]: nbrRounds = 14 else: return None # the expanded keySize expandedKeySize = 16*(nbrRounds+1) # Set the block values, for the block: # a0,0 a0,1 a0,2 a0,3 # a1,0 a1,1 a1,2 a1,3 # a2,0 a2,1 a2,2 a2,3 # a3,0 a3,1 a3,2 a3,3 # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 # # iterate over the columns for i in range(4): # iterate over the rows for j in range(4): block[(i+(j*4))] = iput[(i*4)+j] # expand the key into an 176, 208, 240 bytes key # the expanded key expandedKey = self.expandKey(key, size, expandedKeySize) # encrypt the block using the expandedKey block = self.aes_main(block, expandedKey, nbrRounds) # unmap the block again into the output for k in range(4): # iterate over the rows for l in range(4): output[(k*4)+l] = block[(k+(l*4))] return output # decrypts a 128 bit input block against the given key of size specified def decrypt(self, iput, key, size): output = [0] * 16 # the number of rounds nbrRounds = 0 # the 128 bit block to decode block = [0] * 16 # set the number of rounds if size == self.keySize["SIZE_128"]: nbrRounds = 10 elif size == self.keySize["SIZE_192"]: nbrRounds = 12 elif size == self.keySize["SIZE_256"]: nbrRounds = 14 else: return None # the expanded keySize expandedKeySize = 16*(nbrRounds+1) # Set the block values, for the block: # a0,0 a0,1 a0,2 a0,3 # a1,0 a1,1 a1,2 a1,3 # a2,0 a2,1 a2,2 a2,3 # a3,0 a3,1 a3,2 a3,3 # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 # iterate over the columns for i in range(4): # iterate over the rows for j in range(4): block[(i+(j*4))] = iput[(i*4)+j] # expand the key into an 176, 208, 240 bytes key expandedKey = self.expandKey(key, size, expandedKeySize) # decrypt the block using the expandedKey block = self.aes_invMain(block, expandedKey, nbrRounds) # unmap the block again into the output for k in range(4): # iterate over the rows for l in range(4): output[(k*4)+l] = block[(k+(l*4))] return output class AESModeOfOperation(object): aes = AES() # structure of supported modes of operation modeOfOperation = dict(OFB=0, CFB=1, CBC=2) # converts a 16 character string into a number array def convertString(self, string, start, end, mode): if end - start > 16: end = start + 16 if mode == self.modeOfOperation["CBC"]: ar = [0] * 16 else: ar = [] i = start j = 0 while len(ar) < end - start: ar.append(0) while i < end: ar[j] = ord(string[i]) j += 1 i += 1 return ar # Mode of Operation Encryption # stringIn - Input String # mode - mode of type modeOfOperation # hexKey - a hex key of the bit length size # size - the bit length of the key # hexIV - the 128 bit hex Initilization Vector def encrypt(self, stringIn, mode, key, size, IV): if len(key) % size: return None if len(IV) % 16: return None # the AES input/output plaintext = [] iput = [0] * 16 output = [] ciphertext = [0] * 16 # the output cipher string cipherOut = [] # char firstRound firstRound = True if stringIn != None: for j in range(int(math.ceil(float(len(stringIn))/16))): start = j*16 end = j*16+16 if end > len(stringIn): end = len(stringIn) plaintext = self.convertString(stringIn, start, end, mode) # print 'PT@%s:%s' % (j, plaintext) if mode == self.modeOfOperation["CFB"]: if firstRound: output = self.aes.encrypt(IV, key, size) firstRound = False else: output = self.aes.encrypt(iput, key, size) for i in range(16): if len(plaintext)-1 < i: ciphertext[i] = 0 ^ output[i] elif len(output)-1 < i: ciphertext[i] = plaintext[i] ^ 0 elif len(plaintext)-1 < i and len(output) < i: ciphertext[i] = 0 ^ 0 else: ciphertext[i] = plaintext[i] ^ output[i] for k in range(end-start): cipherOut.append(ciphertext[k]) iput = ciphertext elif mode == self.modeOfOperation["OFB"]: if firstRound: output = self.aes.encrypt(IV, key, size) firstRound = False else: output = self.aes.encrypt(iput, key, size) for i in range(16): if len(plaintext)-1 < i: ciphertext[i] = 0 ^ output[i] elif len(output)-1 < i: ciphertext[i] = plaintext[i] ^ 0 elif len(plaintext)-1 < i and len(output) < i: ciphertext[i] = 0 ^ 0 else: ciphertext[i] = plaintext[i] ^ output[i] for k in range(end-start): cipherOut.append(ciphertext[k]) iput = output elif mode == self.modeOfOperation["CBC"]: for i in range(16): if firstRound: iput[i] = plaintext[i] ^ IV[i] else: iput[i] = plaintext[i] ^ ciphertext[i] # print 'IP@%s:%s' % (j, iput) firstRound = False ciphertext = self.aes.encrypt(iput, key, size) # always 16 bytes because of the padding for CBC for k in range(16): cipherOut.append(ciphertext[k]) return mode, len(stringIn), cipherOut # Mode of Operation Decryption # cipherIn - Encrypted String # originalsize - The unencrypted string length - required for CBC # mode - mode of type modeOfOperation # key - a number array of the bit length size # size - the bit length of the key # IV - the 128 bit number array Initilization Vector def decrypt(self, cipherIn, originalsize, mode, key, size, IV): # cipherIn = unescCtrlChars(cipherIn) if len(key) % size: return None if len(IV) % 16: return None # the AES input/output ciphertext = [] iput = [] output = [] plaintext = [0] * 16 # the output plain text string stringOut = '' # char firstRound firstRound = True if cipherIn != None: for j in range(int(math.ceil(float(len(cipherIn))/16))): start = j*16 end = j*16+16 if j*16+16 > len(cipherIn): end = len(cipherIn) ciphertext = cipherIn[start:end] if mode == self.modeOfOperation["CFB"]: if firstRound: output = self.aes.encrypt(IV, key, size) firstRound = False else: output = self.aes.encrypt(iput, key, size) for i in range(16): if len(output)-1 < i: plaintext[i] = 0 ^ ciphertext[i] elif len(ciphertext)-1 < i: plaintext[i] = output[i] ^ 0 elif len(output)-1 < i and len(ciphertext) < i: plaintext[i] = 0 ^ 0 else: plaintext[i] = output[i] ^ ciphertext[i] for k in range(end-start): stringOut += chr(plaintext[k]) iput = ciphertext elif mode == self.modeOfOperation["OFB"]: if firstRound: output = self.aes.encrypt(IV, key, size) firstRound = False else: output = self.aes.encrypt(iput, key, size) for i in range(16): if len(output)-1 < i: plaintext[i] = 0 ^ ciphertext[i] elif len(ciphertext)-1 < i: plaintext[i] = output[i] ^ 0 elif len(output)-1 < i and len(ciphertext) < i: plaintext[i] = 0 ^ 0 else: plaintext[i] = output[i] ^ ciphertext[i] for k in range(end-start): stringOut += chr(plaintext[k]) iput = output elif mode == self.modeOfOperation["CBC"]: output = self.aes.decrypt(ciphertext, key, size) for i in range(16): if firstRound: plaintext[i] = IV[i] ^ output[i] else: plaintext[i] = iput[i] ^ output[i] firstRound = False if originalsize is not None and originalsize < end: for k in range(originalsize-start): stringOut += chr(plaintext[k]) else: for k in range(end-start): stringOut += chr(plaintext[k]) iput = ciphertext return stringOut def encryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]): """encrypt `data` using `key` `key` should be a string of bytes. returned cipher is a string of bytes prepended with the initialization vector. """ key = map(ord, key) if mode == AESModeOfOperation.modeOfOperation["CBC"]: data = append_PKCS7_padding(data) keysize = len(key) assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize # create a new iv using random data iv = [ord(i) for i in os.urandom(16)] moo = AESModeOfOperation() (mode, length, ciph) = moo.encrypt(data, mode, key, keysize, iv) # With padding, the original length does not need to be known. It's a bad # idea to store the original message length. # prepend the iv. return ''.join(map(chr, iv)) + ''.join(map(chr, ciph)) def decryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]): """decrypt `data` using `key` `key` should be a string of bytes. `data` should have the initialization vector prepended as a string of ordinal values. """ key = map(ord, key) keysize = len(key) assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize # iv is first 16 bytes iv = map(ord, data[:16]) data = map(ord, data[16:]) moo = AESModeOfOperation() decr = moo.decrypt(data, None, mode, key, keysize, iv) if mode == AESModeOfOperation.modeOfOperation["CBC"]: decr = strip_PKCS7_padding(decr) return decr def generateRandomKey(keysize): """Generates a key from random data of length `keysize`. The returned key is a string of bytes. """ if keysize not in (16, 24, 32): emsg = 'Invalid keysize, %s. Should be one of (16, 24, 32).' raise ValueError, emsg % keysize return os.urandom(keysize) if __name__ == "__main__": moo = AESModeOfOperation() cleartext = "This is a test!" cypherkey = [143,194,34,208,145,203,230,143,177,246,97,206,145,92,255,84] iv = [103,35,148,239,76,213,47,118,255,222,123,176,106,134,98,92] mode, orig_len, ciph = moo.encrypt(cleartext, moo.modeOfOperation["CBC"], cypherkey, moo.aes.keySize["SIZE_128"], iv) print 'm=%s, ol=%s (%s), ciph=%s' % (mode, orig_len, len(cleartext), ciph) decr = moo.decrypt(ciph, orig_len, mode, cypherkey, moo.aes.keySize["SIZE_128"], iv) print decr slowaes-0.1a1/python/setup.py0000644000175000017500000000044712126341025015301 0ustar bartmbartmfrom setuptools import setup setup( name = "slowaes", version = "0.1a1", license = "Apache License, Version 2.0", py_modules=['aes'], url = "http://code.google.com/p/slowaes/", author = "Josh Davis, Alex Martelli", description = "implementation of AES in Python", ) slowaes-0.1a1/tests/0000755000175000017500000000000012126341052013403 5ustar bartmbartmslowaes-0.1a1/tests/compare_pj.py0000644000175000017500000000300112126341025016066 0ustar bartmbartm""" Some very-elementary "smoke tests". """ import pyutil import smutil def main(): plaintext = 'Hello, World! Have a great day...' moo = pyutil.aes.AESModeOfOperation() for smode in smutil.modes: mode = smutil.slowaesdo('modeOfOperation.%s', smode) print 'JS mode %r (%s)' % (smode, mode) skey = 'Call me Ishmael.'[:16] nkey = smutil.cryptohelpersdo('convertStringToByteArray(%r, 0, 16, %s)', skey, mode) assert nkey == smutil.str2nums(skey) iv = [12, 34, 96, 15] * 4 enc = smutil.slowaesdo('encrypt(%r, %s, %r, %s, %r)', plaintext, mode, nkey, len(nkey), iv) encos = enc['originalsize'] encmo = enc['mode'] encen = enc['cipher'] print ' JS enc (mode=%s, orgsize=%s):' % (encmo, encos) print ' ', encen # smutil.str2nums(encen) pymode = moo.modeOfOperation[smode] print 'PY mode %r (%s)' % (smode, pymode) pymo, pyos, pyen = moo.encrypt(plaintext, pymode, nkey, len(nkey), iv) print ' PY enc (mode=%s, orgsize=%s):' % (pymo, pyos) print ' ', pyen dec = smutil.slowaesdo('decrypt(%r, %s, %r, %r, %s, %r)', encen, encos, encmo, nkey, len(nkey), iv) print ' JS dec (mode=%s, orgsize=%s):' % (encmo, encos) print ' ', repr(dec) pydec = moo.decrypt(pyen, pyos, pymo, nkey, len(nkey), iv) print ' PY dec (mode=%s, orgsize=%s):' % (pymo, pyos) print ' ', repr(pydec) main() slowaes-0.1a1/tests/pyutil.py0000644000175000017500000000061512126341025015305 0ustar bartmbartm""" Common utility routines for Python use on the Python AES module """ import os import sys modes = 'OFB CFB CBC'.split() def init(): directory, fn = os.path.split(__file__) pydir = os.path.join(directory, '../python/') sys.path.insert(1, pydir) import aes return aes aes = init() def str2nums(s): return map(ord, s) def nums2str(ns): return ''.join(map(chr, ns)) slowaes-0.1a1/tests/smoketest_py.py0000644000175000017500000000623412126341025016510 0ustar bartmbartm""" Some very-elementary "smoke tests". """ import os import sys import pyutil def runHighLevelFunctionTests(): generateRandomKey = pyutil.aes.generateRandomKey encryptData = pyutil.aes.encryptData decryptData = pyutil.aes.decryptData AES = pyutil.aes.AES def testString(cleartext): ##print 'testing for data of length %s' % len(cleartext) for (keyname, keylen) in AES.keySize.items(): ##print 'trying with key size %s' % keyname, key = generateRandomKey(keylen) ciph = encryptData(key, cleartext) decr = decryptData(key, ciph) assert decr == cleartext ##print 'ok' # full block - adds full block of padding print 'testing full block padding.' testString(''.join('a' for i in range(16))) # partial block print 'testing partial block padding.' cleartext = ("This is a test! Let's try something without a perfect " "block size...") assert len(cleartext) % 16 testString(cleartext) character_range = map(chr, range(256)) def getRandomChars(count): import random random_chars = [] for i in range(count): random_chars.append(random.choice(character_range)) return random_chars sizes = [8, 16, 22, 32, 33, 1600, 4092] # test sizes print 'testing various messages sizes' for size in sizes: print 'testing message of size %s (with 3 key sizes)' % size cleartext = 'a' * size testString(cleartext) # test charset print 'testing each of 256 characters with both full and partial padding' failed_chars = [] for i in range(256): # test both full and partial padding for count in (12, 16): cleartext = chr(i) * count try: testString(cleartext) except: print 'failed with %s' % cleartext, i failed_chars.append(i) if failed_chars: raise StandardError, 'these failed %s' % str(failed_chars) # test random chars print 'testing random chracters of various sizes' for size in sizes: print 'testing message of size %s (with 3 key sizes)' % size cleartext = ''.join(getRandomChars(size)) try: testString(cleartext) except Exception: print 'failed with %s' % cleartext raise def main(): plaintext = 'Hello, World! Have a great day...' moo = pyutil.aes.AESModeOfOperation() for smode in pyutil.modes: pymode = moo.modeOfOperation[smode] print 'mode %r (%s)' % (smode, pymode) skey = 'Call me Ishmael.'[:16] nkey = pyutil.str2nums(skey) assert skey == pyutil.nums2str(nkey) iv = [12, 34, 96, 15] * 4 pymo, pyos, pyen = moo.encrypt(plaintext, pymode, nkey, len(nkey), iv) print ' PY enc (mode=%s, orgsize=%s):' % (pymo, pyos) print ' ', pyen pydec = moo.decrypt(pyen, pyos, pymo, nkey, len(nkey), iv) print ' PY dec (mode=%s, orgsize=%s):' % (pymo, pyos) print ' ', repr(pydec) if __name__ == '__main__': main() runHighLevelFunctionTests() slowaes-0.1a1/tests/README0000644000175000017500000000240012126341025014257 0ustar bartmbartmThe tests are coded in Python and use Python-Spidermonkey (see: http://code.google.com/p/python-spidermonkey/) to run Javascript and Python code "in parallel" to ensure intermediate and final results match, &c. (Note that to install Python-Spidermonkey you first need to install Pyrex, see http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/). Future scripting languages could use a similar approach (e.g. see http://www.goto.info.waseda.ac.jp/~fukusima/ruby/python/doc/index.html for the Ruby/Python module). Tests rely on smutil.py (for testing JS AES) and pyutil.py (for testing Python AES) to properly import the aes.* modules and offer access to them, as well as auxiliary helpful utilities. Tests currently present: smoketest_js.py (a tiny smoke-test of encryption and decryption in all 3 modes); compare_pj.py (a similar smoke-test, but comparing the JS and Python implementations of AES to ensure identical results). To run the tests: $ cd slowaes/tests $ python smoketests_py.py $ python smoketests_js.py $ pyton compare_pj.py [[Note: the latter is currently known to be broken with a mysterious JS error "array.push is not a function" (?)]] TODO: write many more tests, including integration tests ensuring interoperability with other AES implementations. slowaes-0.1a1/tests/smutil.py0000644000175000017500000000210512126341025015270 0ustar bartmbartm""" Common utility routines for spidermonkey use on the JS AES module """ import os import spidermonkey modes = 'OFB CFB CBC'.split() def do(s): return cx.eval_script(s) class ConsoleClass: """Let JS code call console.log(...) for output.""" def log(self, s): print s console = ConsoleClass() def init(): rt = spidermonkey.Runtime() cx = rt.new_context() cx.bind_class(ConsoleClass) cx.bind_object('console', console) directory, fn = os.path.split(__file__) jsdir = os.path.join(directory, '../js/') chFile = os.path.join(jsdir, 'cryptoHelpers.js') f = open(chFile) chScript = f.read() f.close() aesFile = os.path.join(jsdir, 'aes.js') f = open(aesFile) aesScript = f.read() f.close() cx.eval_script(chScript) cx.eval_script(aesScript) return cx cx = init() def slowaesdo(method, *args): return do('slowAES.%s' % (method%args)) def cryptohelpersdo(method, *args): return do('cryptoHelpers.%s' % (method%args)) def str2nums(s): return map(ord, s) def nums2str(ns): return ''.join(map(chr, ns)) slowaes-0.1a1/tests/smoketest_js.py0000644000175000017500000001402412126341025016470 0ustar bartmbartm""" Some very-elementary "smoke tests". """ import smutil def main(): print 'Begin all modes check' plaintext = 'Hello, World! Have a great day...' for smode in smutil.modes: mode = smutil.slowaesdo('modeOfOperation.%s', smode) skey = 'Call me Ishmael.'[:16] akey = smutil.cryptohelpersdo('convertStringToByteArray(%r)', skey); keysize = smutil.slowaesdo('aes.keySize.SIZE_128') nkey = smutil.slowaesdo('getPaddedBlock(%r, 0, 16, %s)', akey, mode) assert nkey == smutil.str2nums(skey), 'FAILED: mode %r (%s) key conversion' % (smode, mode) print 'PASSED: mode %r (%s) key conversion' % (smode, mode) iv = [12, 34, 96, 15] * 4 utf8string = smutil.cryptohelpersdo('encode_utf8(%r)', plaintext) byteArray = smutil.cryptohelpersdo('convertStringToByteArray(%r)', utf8string) enc = smutil.slowaesdo('encrypt(%r, %s, %r, %s, %r)', byteArray, mode, nkey, keysize, iv) dec = smutil.slowaesdo('decrypt(%r, %s, %r, %r, %s, %r)', enc['cipher'], enc['originalsize'], enc['mode'], nkey, keysize, iv) decstring = smutil.cryptohelpersdo('convertByteArrayToString(%r)', dec) unicodestring = smutil.cryptohelpersdo('decode_utf8(%r)', decstring) assert unicodestring == plaintext, 'FAILED: mode %r (%s) round trip encryption/decryption' % (smode, mode) print 'PASSED: mode %r (%s) round trip encryption/decryption' % (smode, mode) print '\nBegin FIPS 128 verification' mode = smutil.slowaesdo('modeOfOperation.CBC') f128keysize = smutil.slowaesdo('aes.keySize.SIZE_128') f128block = smutil.cryptohelpersdo('toNumbers("00112233445566778899aabbccddeeff")') f128ciph = smutil.cryptohelpersdo('toNumbers("69c4e0d86a7b0430d8cdb78070b4c55a")') f128key = smutil.cryptohelpersdo('toNumbers("000102030405060708090a0b0c0d0e0f")') f128enc = smutil.slowaesdo('aes.encrypt(%r, %r, %s)', f128block, f128key, f128keysize) assert f128enc == f128ciph, 'FAILED: FIPS 128 encryption' print 'PASSED: FIPS 128 encryption' f128dec = smutil.slowaesdo('aes.decrypt(%r, %r, %s)', f128ciph, f128key, f128keysize) assert f128dec == f128block, 'FAILED: FIPS 128 decryption' print 'PASSED: FIPS 128 decryption' print '\nBegin FIPS 192 verification' mode = smutil.slowaesdo('modeOfOperation.CBC') f192keysize = smutil.slowaesdo('aes.keySize.SIZE_192') f192block = smutil.cryptohelpersdo('toNumbers("00112233445566778899aabbccddeeff")') f192ciph = smutil.cryptohelpersdo('toNumbers("dda97ca4864cdfe06eaf70a0ec0d7191")') f192key = smutil.cryptohelpersdo('toNumbers("000102030405060708090a0b0c0d0e0f1011121314151617")') f192enc = smutil.slowaesdo('aes.encrypt(%r, %r, %s)', f192block, f192key, f192keysize) assert f192enc == f192ciph, 'FAILED: FIPS 192 encryption' print 'PASSED: FIPS 192 encryption' f192dec = smutil.slowaesdo('aes.decrypt(%r, %r, %s)', f192ciph, f192key, f192keysize) assert f192dec == f192block, 'FAILED: FIPS 192 decryption' print 'PASSED: FIPS 192 decryption' print '\nBegin FIPS 256 verification' mode = smutil.slowaesdo('modeOfOperation.CBC') f256keysize = smutil.slowaesdo('aes.keySize.SIZE_256') f256block = smutil.cryptohelpersdo('toNumbers("00112233445566778899aabbccddeeff")') f256ciph = smutil.cryptohelpersdo('toNumbers("8ea2b7ca516745bfeafc49904b496089")') f256key = smutil.cryptohelpersdo('toNumbers("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")') f256enc = smutil.slowaesdo('aes.encrypt(%r, %r, %s)', f256block, f256key, f256keysize) assert f256enc == f256ciph, 'FAILED: FIPS 256 encryption' print 'PASSED: FIPS 256 encryption' f256dec = smutil.slowaesdo('aes.decrypt(%r, %r, %s)', f256ciph, f256key, f256keysize) assert f256dec == f256block, 'FAILED: FIPS 256 decryption' print 'PASSED: FIPS 256 decryption' print '\nBegin OpenSSL 128 verification' keysize = smutil.slowaesdo('aes.keySize.SIZE_128') mode = smutil.slowaesdo('modeOfOperation.CBC') key = smutil.cryptohelpersdo('toNumbers("5e884898da28047151d0e56f8dc62927")') iv = smutil.cryptohelpersdo('toNumbers("6bbda7892ad344e06c31e64564a69a9a")') plaintext = smutil.cryptohelpersdo('convertStringToByteArray("secretsecretsecret")') openssl = '4j+jnKTSsTBVUJ9MuV8hFEHuxdyT065rYbUqo0gJo1I=\n' enc = smutil.slowaesdo('encrypt(%r, %s, %r, %s, %r).cipher', plaintext, mode, key, keysize, iv) base64 = smutil.cryptohelpersdo('base64.encode(%r)', enc); assert base64 == openssl, 'FAILED: OpenSSL 128 encryption' print 'PASSED: OpenSSL 128 encryption' print '\nBegin OpenSSL 192 verification' keysize = smutil.slowaesdo('aes.keySize.SIZE_192') mode = smutil.slowaesdo('modeOfOperation.CBC') key = smutil.cryptohelpersdo('toNumbers("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd6")') iv = smutil.cryptohelpersdo('toNumbers("6bbda7892ad344e06c31e64564a69a9a")') plaintext = smutil.cryptohelpersdo('convertStringToByteArray("secretsecretsecret")') openssl = 'g1D8nfnp31TH8jaV3304KP23i6aQhSaU3gubyGtV6WE=\n' enc = smutil.slowaesdo('encrypt(%r, %s, %r, %s, %r).cipher', plaintext, mode, key, keysize, iv) base64 = smutil.cryptohelpersdo('base64.encode(%r)', enc); assert base64 == openssl, 'FAILED: OpenSSL 192 encryption' print 'PASSED: OpenSSL 192 encryption' print '\nBegin OpenSSL 256 verification' keysize = smutil.slowaesdo('aes.keySize.SIZE_256') mode = smutil.slowaesdo('modeOfOperation.CBC') key = smutil.cryptohelpersdo('toNumbers("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8")') iv = smutil.cryptohelpersdo('toNumbers("6bbda7892ad344e06c31e64564a69a9a")') plaintext = smutil.cryptohelpersdo('convertStringToByteArray("secretsecretsecret")') openssl = 'XUfDIa3urWyzHC1bmfmSQJjaTEXPmKkQYvbCnYd6gFY=\n' enc = smutil.slowaesdo('encrypt(%r, %s, %r, %s, %r).cipher', plaintext, mode, key, keysize, iv) base64 = smutil.cryptohelpersdo('base64.encode(%r)', enc); assert base64 == openssl, 'FAILED: OpenSSL 256 encryption' print 'PASSED: OpenSSL 256 encryption' main()