diff options
author | lloyd <[email protected]> | 2014-12-29 02:40:08 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-12-29 02:40:08 +0000 |
commit | dfc93a3c8992b067f66ca148ac91c24489f493fc (patch) | |
tree | d2af4bc335fc1ceebbaedc75dc7fa2d4f04ff2b4 | |
parent | 05b6811827fe7f4e107a9339142f6aec56f0f202 (diff) |
Add Poly1305, based on poly1305-donna by Andrew Moon.
-rw-r--r-- | doc/license.rst | 1 | ||||
-rw-r--r-- | doc/relnotes/1_11_12.rst | 4 | ||||
-rw-r--r-- | doc/website/algos.rst | 1 | ||||
-rw-r--r-- | src/lib/engine/core_engine/lookup_mac.cpp | 22 | ||||
-rw-r--r-- | src/lib/mac/poly1305/info.txt | 9 | ||||
-rw-r--r-- | src/lib/mac/poly1305/poly1305.cpp | 73 | ||||
-rw-r--r-- | src/lib/mac/poly1305/poly1305.h | 48 | ||||
-rw-r--r-- | src/lib/mac/poly1305/poly1305_donna.h | 152 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/info.txt | 4 | ||||
-rw-r--r-- | src/lib/utils/donna128.h (renamed from src/lib/pubkey/curve25519/donna128.h) | 0 | ||||
-rw-r--r-- | src/lib/utils/info.txt | 1 | ||||
-rw-r--r-- | src/tests/data/mac/poly1305.vec | 323 |
12 files changed, 626 insertions, 12 deletions
diff --git a/doc/license.rst b/doc/license.rst index 0bf7226fc..bd33743f2 100644 --- a/doc/license.rst +++ b/doc/license.rst @@ -30,6 +30,7 @@ Botan (http://botan.randombit.net/) is distributed under these terms:: 2012-2014 Markus Wanner 2013 Joel Low 2014 cryptosource GmbH + 2014 Andrew Moon All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/doc/relnotes/1_11_12.rst b/doc/relnotes/1_11_12.rst index 516f41e81..88ece0477 100644 --- a/doc/relnotes/1_11_12.rst +++ b/doc/relnotes/1_11_12.rst @@ -6,8 +6,10 @@ Version 1.11.12, Not Yet Released encrypting Curve25519 keys under PKCS #8 and including them in certificates and CRLs have been defined. +* Add Poly1305, based on the implementation poly1305-donna by + Andrew Moon. + * When encrypted as PKCS #8 structures, Curve25519 and McEliece private keys default to using AES-256/GCM instead of AES-256/CBC * Define OIDs for OCB mode with AES, Serpent and Twofish. - diff --git a/doc/website/algos.rst b/doc/website/algos.rst index 698342af4..d2afbd2ba 100644 --- a/doc/website/algos.rst +++ b/doc/website/algos.rst @@ -62,6 +62,7 @@ Authentication Codes * HMAC * CMAC (aka OMAC1) + * Poly1305 * Obsolete designs CBC-MAC, ANSI X9.19 DES-MAC, and the protocol-specific SSLv3 authentication code diff --git a/src/lib/engine/core_engine/lookup_mac.cpp b/src/lib/engine/core_engine/lookup_mac.cpp index 32275b559..acb8da019 100644 --- a/src/lib/engine/core_engine/lookup_mac.cpp +++ b/src/lib/engine/core_engine/lookup_mac.cpp @@ -21,6 +21,10 @@ #include <botan/hmac.h> #endif +#if defined(BOTAN_HAS_POLY1305) + #include <botan/poly1305.h> +#endif + #if defined(BOTAN_HAS_SSL3_MAC) #include <botan/ssl3_mac.h> #endif @@ -38,10 +42,9 @@ MessageAuthenticationCode* Core_Engine::find_mac(const SCAN_Name& request, Algorithm_Factory& af) const { - -#if defined(BOTAN_HAS_CBC_MAC) - if(request.algo_name() == "CBC-MAC" && request.arg_count() == 1) - return new CBC_MAC(af.make_block_cipher(request.arg(0))); +#if defined(BOTAN_HAS_HMAC) + if(request.algo_name() == "HMAC" && request.arg_count() == 1) + return new HMAC(af.make_hash_function(request.arg(0))); #endif #if defined(BOTAN_HAS_CMAC) @@ -49,9 +52,14 @@ Core_Engine::find_mac(const SCAN_Name& request, return new CMAC(af.make_block_cipher(request.arg(0))); #endif -#if defined(BOTAN_HAS_HMAC) - if(request.algo_name() == "HMAC" && request.arg_count() == 1) - return new HMAC(af.make_hash_function(request.arg(0))); +#if defined(BOTAN_HAS_POLY1305) + if(request.algo_name() == "Poly1305") + return new Poly1305; +#endif + +#if defined(BOTAN_HAS_CBC_MAC) + if(request.algo_name() == "CBC-MAC" && request.arg_count() == 1) + return new CBC_MAC(af.make_block_cipher(request.arg(0))); #endif #if defined(BOTAN_HAS_SSL3_MAC) diff --git a/src/lib/mac/poly1305/info.txt b/src/lib/mac/poly1305/info.txt new file mode 100644 index 000000000..84491aa41 --- /dev/null +++ b/src/lib/mac/poly1305/info.txt @@ -0,0 +1,9 @@ +define POLY1305 20141227 + +<header:public> +poly1305.h +</header:public> + +<header:internal> +poly1305_donna.h +</header:internal> diff --git a/src/lib/mac/poly1305/poly1305.cpp b/src/lib/mac/poly1305/poly1305.cpp new file mode 100644 index 000000000..32ab64d7e --- /dev/null +++ b/src/lib/mac/poly1305/poly1305.cpp @@ -0,0 +1,73 @@ +/* +* Poly1305 +* (C) 2014 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/poly1305.h> +#include <botan/internal/poly1305_donna.h> + +namespace Botan { + +void Poly1305::clear() + { + zap(m_poly); + zap(m_buf); + m_buf_pos = 0; + } + +void Poly1305::key_schedule(const byte key[], size_t key_len) + { + m_buf_pos = 0; + m_buf.resize(16); + m_poly.resize(8); + + poly1305_init(m_poly, key); + } + +void Poly1305::add_data(const byte input[], size_t length) + { + BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized"); + + if(m_buf_pos) + { + buffer_insert(m_buf, m_buf_pos, input, length); + + if(m_buf_pos + length >= m_buf.size()) + { + poly1305_blocks(m_poly, &m_buf[0], 1); + input += (m_buf.size() - m_buf_pos); + length -= (m_buf.size() - m_buf_pos); + m_buf_pos = 0; + } + } + + const size_t full_blocks = length / m_buf.size(); + const size_t remaining = length % m_buf.size(); + + if(full_blocks) + poly1305_blocks(m_poly, input, full_blocks); + + buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining); + m_buf_pos += remaining; + } + +void Poly1305::final_result(byte out[]) + { + BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized"); + + if(m_buf_pos != 0) + { + m_buf[m_buf_pos] = 1; + clear_mem(&m_buf[m_buf_pos+1], m_buf.size() - m_buf_pos); + poly1305_blocks(m_poly, &m_buf[0], 1, true); + } + + poly1305_finish(m_poly, out); + + m_poly.clear(); + m_buf_pos = 0; + } + +} diff --git a/src/lib/mac/poly1305/poly1305.h b/src/lib/mac/poly1305/poly1305.h new file mode 100644 index 000000000..8334edb03 --- /dev/null +++ b/src/lib/mac/poly1305/poly1305.h @@ -0,0 +1,48 @@ +/* +* Poly1305 +* (C) 2014 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MAC_POLY1305_H__ +#define BOTAN_MAC_POLY1305_H__ + +#include <botan/mac.h> +#include <memory> + +namespace Botan { + +/** +* DJB's Poly1305 +* Important note: each key can only be used once +*/ +class BOTAN_DLL Poly1305 : public MessageAuthenticationCode + { + public: + std::string name() const override { return "Poly1305"; } + + MessageAuthenticationCode* clone() const { return new Poly1305; } + + void clear(); + + size_t output_length() const { return 16; } + + Key_Length_Specification key_spec() const + { + return Key_Length_Specification(32); + } + + private: + void add_data(const byte[], size_t); + void final_result(byte[]); + void key_schedule(const byte[], size_t); + + secure_vector<u64bit> m_poly; + secure_vector<byte> m_buf; + size_t m_buf_pos = 0; + }; + +} + +#endif diff --git a/src/lib/mac/poly1305/poly1305_donna.h b/src/lib/mac/poly1305/poly1305_donna.h new file mode 100644 index 000000000..f0f3fe387 --- /dev/null +++ b/src/lib/mac/poly1305/poly1305_donna.h @@ -0,0 +1,152 @@ +/* +* Derived from poly1305-donna-64.h by Andrew Moon <[email protected]> +* in https://github.com/floodyberry/poly1305-donna +* +* (C) 2014 Andrew Moon +* (C) 2014 Jack Lloyd +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_POLY1305_DONNA_H__ +#define BOTAN_POLY1305_DONNA_H__ + +#include <botan/loadstor.h> +#include <botan/mul128.h> + +#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128) + #include <botan/internal/donna128.h> +#endif + +namespace Botan { + +namespace { + +#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128) +typedef donna128 uint128_t; +#else +inline u64bit carry_shift(const uint128_t a, size_t shift) + { + return static_cast<u64bit>(a >> shift); + } +#endif + +void poly1305_init(secure_vector<u64bit>& X, const byte key[32]) + { + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + const u64bit t0 = load_le<u64bit>(key, 0); + const u64bit t1 = load_le<u64bit>(key, 1); + + X[0] = ( t0 ) & 0xffc0fffffff; + X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; + X[2] = ((t1 >> 24) ) & 0x00ffffffc0f; + + /* h = 0 */ + X[3] = 0; + X[4] = 0; + X[5] = 0; + + /* save pad for later */ + X[6] = load_le<u64bit>(key, 2); + X[7] = load_le<u64bit>(key, 3); + } + +void poly1305_blocks(secure_vector<u64bit>& X, const byte *m, size_t blocks, bool is_final = false) + { + const u64bit hibit = is_final ? 0 : (static_cast<u64bit>(1) << 40); /* 1 << 128 */ + //u64bit c; + + const u64bit r0 = X[0]; + const u64bit r1 = X[1]; + const u64bit r2 = X[2]; + + u64bit h0 = X[3+0]; + u64bit h1 = X[3+1]; + u64bit h2 = X[3+2]; + + const u64bit s1 = r1 * (5 << 2); + const u64bit s2 = r2 * (5 << 2); + + while(blocks--) + { + /* h += m[i] */ + const u64bit t0 = load_le<u64bit>(m, 0); + const u64bit t1 = load_le<u64bit>(m, 1); + + h0 += (( t0 ) & 0xfffffffffff); + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); + h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; + + /* h *= r */ + uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1; + uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2; + uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0; + + /* (partial) h %= p */ + u64bit c = carry_shift(d0, 44); h0 = d0 & 0xfffffffffff; + d1 += c; c = carry_shift(d1, 44); h1 = d1 & 0xfffffffffff; + d2 += c; c = carry_shift(d2, 42); h2 = d2 & 0x3ffffffffff; + h0 += c * 5; c = carry_shift(h0, 44); h0 = h0 & 0xfffffffffff; + h1 += c; + + m += 16; + } + + X[3+0] = h0; + X[3+1] = h1; + X[3+2] = h2; + } + +void poly1305_finish(secure_vector<u64bit>& X, byte mac[16]) + { + /* fully carry h */ + u64bit h0 = X[3+0]; + u64bit h1 = X[3+1]; + u64bit h2 = X[3+2]; + + u64bit c; + c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; + + /* compute h + -p */ + u64bit g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; + u64bit g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; + u64bit g2 = h2 + c - ((u64bit)1 << 42); + + /* select h if h < p, or h + -p if h >= p */ + c = (g2 >> ((sizeof(u64bit) * 8) - 1)) - 1; + g0 &= c; + g1 &= c; + g2 &= c; + c = ~c; + h0 = (h0 & c) | g0; + h1 = (h1 & c) | g1; + h2 = (h2 & c) | g2; + + /* h = (h + pad) */ + const u64bit t0 = X[6]; + const u64bit t1 = X[7]; + + h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff; + + /* mac = h % (2^128) */ + h0 = ((h0 ) | (h1 << 44)); + h1 = ((h1 >> 20) | (h2 << 24)); + + store_le(&mac[0], h0, h1); + + /* zero out the state */ + zero_mem(&X[0], X.size()); + } + +} + +} + +#endif diff --git a/src/lib/pubkey/curve25519/info.txt b/src/lib/pubkey/curve25519/info.txt index 68c417056..6139dc32f 100644 --- a/src/lib/pubkey/curve25519/info.txt +++ b/src/lib/pubkey/curve25519/info.txt @@ -3,7 +3,3 @@ define CURVE_25519 20141227 <header:public> curve25519.h </header:public> - -<header:internal> -donna128.h -</header:internal> diff --git a/src/lib/pubkey/curve25519/donna128.h b/src/lib/utils/donna128.h index f2b2d88ea..f2b2d88ea 100644 --- a/src/lib/pubkey/curve25519/donna128.h +++ b/src/lib/utils/donna128.h diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt index 9ba51f193..84e1c8740 100644 --- a/src/lib/utils/info.txt +++ b/src/lib/utils/info.txt @@ -4,6 +4,7 @@ load_on always <header:internal> bit_ops.h +donna128.h prefetch.h rounding.h semaphore.h diff --git a/src/tests/data/mac/poly1305.vec b/src/tests/data/mac/poly1305.vec new file mode 100644 index 000000000..992000292 --- /dev/null +++ b/src/tests/data/mac/poly1305.vec @@ -0,0 +1,323 @@ + +[Poly1305] + +# self test included in poly1305-donna +Key = DDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFC +In = 797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1 +Out = DDB9DA7DDD5E52792730ED5CDA5F90A4 + +# onetimeauth test from libsodium +Key = EEA6A7251C1E72916D11C2CB214D3C252539121D8E234E652D651FA4C8CFF880 +In = 8E993B9F48681273C29650BA32FC76CE48332EA7164D96A4476FB8C531A1186AC0DFC17C98DCE87B4DA7F011EC48C97271D2C20F9B928FE2270D6FB863D51738B48EEEE314A7CC8AB932164548E526AE90224368517ACFEABD6BB3732BC0E9DA99832B61CA01B6DE56244A9E88D5F9B37973F622A43D14A6599B1F654CB45A74E355A5 +Out = F3FFC7703F9400E52A7DFB4B3D3305D9 + +# draft-agl-tls-chacha20poly1305-04 + +Key = 746869732069732033322d62797465206b657920666f7220506f6c7931333035 +In = 48656c6c6f20776f726c6421 +Out = a6f745008f81c916a20dcc74eef2b2f0 + +# draft-irtf-cfrg-chacha20-poly1305-03 + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 00000000000000000000000000000000 + +Key = 0000000000000000000000000000000036E5F6B5C5E06070F0EFCA96227A863E +In = 416E79207375626D697373696F6E20746F20746865204945544620696E74656E6465642062792074686520436F6E7472696275746F7220666F72207075626C69636174696F6E20617320616C6C206F722070617274206F6620616E204945544620496E7465726E65742D4472616674206F722052464320616E6420616E792073746174656D656E74206D6164652077697468696E2074686520636F6E74657874206F6620616E204945544620616374697669747920697320636F6E7369646572656420616E20224945544620436F6E747269627574696F6E222E20537563682073746174656D656E747320696E636C756465206F72616C2073746174656D656E747320696E20494554462073657373696F6E732C2061732077656C6C206173207772697474656E20616E6420656C656374726F6E696320636F6D6D756E69636174696F6E73206D61646520617420616E792074696D65206F7220706C6163652C207768696368206172652061646472657373656420746F +Out = 36E5F6B5C5E06070F0EFCA96227A863E + +Key = 36E5F6B5C5E06070F0EFCA96227A863E00000000000000000000000000000000 +In = 416E79207375626D697373696F6E20746F20746865204945544620696E74656E6465642062792074686520436F6E7472696275746F7220666F72207075626C69636174696F6E20617320616C6C206F722070617274206F6620616E204945544620496E7465726E65742D4472616674206F722052464320616E6420616E792073746174656D656E74206D6164652077697468696E2074686520636F6E74657874206F6620616E204945544620616374697669747920697320636F6E7369646572656420616E20224945544620436F6E747269627574696F6E222E20537563682073746174656D656E747320696E636C756465206F72616C2073746174656D656E747320696E20494554462073657373696F6E732C2061732077656C6C206173207772697474656E20616E6420656C656374726F6E696320636F6D6D756E69636174696F6E73206D61646520617420616E792074696D65206F7220706C6163652C207768696368206172652061646472657373656420746F +Out = F3477E7CD95417AF89A6B8794C310CF0 + +Key = 1C9240A5EB55D38AF333888604F6B5F0473917C1402B80099DCA5CBC207075C0 +In = 2754776173206272696C6C69672C20616E642074686520736C6974687920746F7665730A446964206779726520616E642067696D626C6520696E2074686520776162653A0A416C6C206D696D737920776572652074686520626F726F676F7665732C0A416E6420746865206D6F6D65207261746873206F757467726162652E +Out = 4541669A7EAAEE61E708DC7CBCC5EB62 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +In = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Out = 03000000000000000000000000000000 + +Key = 02000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +In = 02000000000000000000000000000000 +Out = 03000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +In = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000 +Out = 05000000000000000000000000000000 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +In = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101 +Out = 00000000000000000000000000000000 + +Key = 0200000000000000000000000000000000000000000000000000000000000000 +In = FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Out = FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +In = E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000 +Out = 14000000000000005500000000000000 + +Key = 0100000000000000040000000000000000000000000000000000000000000000 +In = E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000 +Out = 13000000000000000000000000000000 + +# Randomly generated by libsodium + +Key = 9E9D85AAD102FDF3867984CAD7436C36D1A00481C8F19ECE2070271B5D998FD0 +In = +Out = D1A00481C8F19ECE2070271B5D998FD0 + +Key = B1DF3FB9EA530109228401A375516AF7337AAA04EBD1F9BB79B0EE97AD6DD946 +In = E9 +Out = 5BC3ACAF241883EFAA11D4554704EF70 + +Key = 548E3E7495C8DDD028EF42C85BEC26CAF49B402592A25E37D54CD086C742620D +In = F062 +Out = 4844B6A0345BA7B688D345D4BB90B164 + +Key = 95C9DDBAF2A0D598517EB8E3869CE1E1DCE86384F8C7B9CE8F2B157DD297469B +In = D815EC +Out = C4BC6F4BA5258216624AED8416A23081 + +Key = FC7B0C21141632AE850B31A9CD0BA1BDCD68689AE88817ECC294AD5F1217395B +In = 15E0213E +Out = 67E592B5167E669BE51E6F907AB2795C + +Key = A2C48C332C649467416B072DB19F6376EC75BCCDB1CF03C4AD86BA2D1B69D00C +In = B5ED4BC907 +Out = A96C7AAA30F5F70D4F466CBDCD1F8431 + +Key = 6B554DA6070086A0D81DA6F3A18B57951DD94959499DFFA5946769E4CFE08420 +In = AA99E9E0635B +Out = 837AD6CE4A89DBE067817498CC3AA0AA + +Key = E86CEC57707D632B7F3CC2257A5D8025C15D723FAB8FACCC8398AA8B5A3FA765 +In = 525030B06AAC7D +Out = AD406A25FBFF944A474514F5AEA51E38 + +Key = 8CACA0437F997872FDA55C4E663733EBA37C7C7407D67A0C3DD65B211FDAF5CA +In = A877A82AE521AA02 +Out = DC35AF493BAB087D16F0C68E027C73B5 + +Key = 8B9F30F2065CCEB9F763D79F1B6433A058A8F2AF052A4555FDABDC624FF3B0CE +In = 4F0522E58738DCAD50 +Out = 939C9ADDD0CEB75BD7B82807AFD483D8 + +Key = E29D977D6439CB90358DBBD2538C8BD48DAA5CD09A0038232CAB61769128ACC5 +In = BEE52800EB0DC6FA3E43 +Out = 4ED9A237B5895EF61FDD100F16C53888 + +Key = 2995E27B27F510E25F926C0109679605DB8FF757CC83822DEDD9C1F6615FE39D +In = BAD92754E84F435F3284E6 +Out = 08096723A036D7FB8F15507BB8C0BC43 + +Key = C81413ADCE932303D367A96AB5485B5CF1C32005AB1B6CCDC921EAEE077ECC1E +In = 907A005DDDFB330FD9C0CCE9 +Out = 29C1DDD60375E77B69E38B522B32E709 + +Key = 7C7DF24D60A6A202564BF3124DCB06137A7FF53B1864E43E2E7B73FF2209B9B7 +In = 4DB2DE834EC7CBBD042D9581A5 +Out = 5BE481E149F955C65BEA350A4DAD4C21 + +Key = 1C20C733E41854683EBBC49A085E47704073359BDF26C24817DBD855DAD2FD76 +In = 47FE8BFF7501E52AC14FCC687384 +Out = 4A650D205CE287CB8C9BE568C4A451A3 + +Key = 079810FD6F1AD87D7A2E1A9D72C55249A8CFA875B41FA14568EF9741E6A769BF +In = 5B5EAB1283967770542A7A57702A93 +Out = BF159EA2671A07302FE2D6B5A5F40E75 + +Key = 828C4B03687DE973E34AC6FA5CF01699EB658EC84F3DCE60BAB5A35AA7D2585E +In = 3EC00AAE4DFA8952BCBA685521D9872A +Out = 359138B3E5E097BF48694AF31DBD915F + +Key = 73DCAC8AFDE03315932C4B6F032ECB86901D1A401DB20E45334A52967FB6A5A1 +In = DA71371BDA6B96B51D361660F7E2221A0A +Out = CAF6EF581BEBF03C00D33917EDED3E00 + +Key = 7FDE7001E3FB22D673FDFC2E6138F7E2C2409537B95C04C8FA6C8097E3880BF2 +In = 2826E1BD0C643140C2A750E1F4E08E9CBB35 +Out = 8734CDA02BE02553D41455C99971711C + +Key = CED5B7D685752522B80233F4F47262E5C1E1709C30F8E9415EA20AB1F7DA1D6F +In = A03B1F880AB72B0F12C22BC837F1DAE38FBA9E +Out = 9D0DCF5BBF90DE436BCC864FCB43DEBF + +Key = F5403228FA8A9879A3C8288319072C62A70F1605CB0C36F7612DD131AAE59C55 +In = 592C0D0BBD2CF2225EAB8912CDE12F9752F0E217 +Out = F88A11292AE0CF5854C626E6B079EB84 + +Key = B5CD17608F894FB90A014144F9677FDC490CCD20059FD3F99B569ED9B51D3B4F +In = 2063CDFD23683718F0994B3E2F6789A443DF0E447B +Out = 6E5E516FA39CD06B3E901ADE57FC8C08 + +Key = CF04CB06DE7AF28D2A9E022034389509FD2EF5168FA40D6F29D500A287BD647F +In = DE69747C2ED30A5B69567B528604BC968AFBC546CC90 +Out = 1186387E982661E6F80A5D38D4C63D4C + +Key = 8642E25ABA2FEBC3F8D7F1E7737D7CB55CB5991E6933CD7E1AFB4F68A046944C +In = ABD9F8E04CD681D50A679877B2EDBDA1A0A376EBECE6E0 +Out = E2843F3D16E7666EFB8EC48E6C507657 + +Key = 32029CBC18697477DDBB910A9494868DEEB0315D25A49F76BB43544B2F83B941 +In = 9E354F70B52AECB086DF664825C039824ABD6A0F9A7C7FCB +Out = 0194DB1F13222163729A8F0ED84DE466 + +Key = BA34D5CEED7A4F134CCADEAABF1C42B37AE8B1334B78B789DD29A989B50E029D +In = BBB666E23FD40458BA38D06A5DCC388BA103BC6D04095A7AA6 +Out = 9356DF51E8E76D5466F509EA513112AA + +Key = 158CD22AB957A0F9F977353BD9C83B688D51088DDEAF847BE81468EC345EA443 +In = 3E820F3AE6EA6EF9C59D7B527BDB76C5EFD65E76B3E3B93C9EF5 +Out = A3EBE4E930B3EB5B7A3E475B84A29F45 + +Key = 59E4BBD352419AE4E5819240A0033A301CC3AC86187426053B69F572E83F2470 +In = 9655D7D3D6C74F9A0C9502C9EC7FC22F4710BDC7A0AA0BAB35C929 +Out = 13B6F916539A5D06DBE3F801DE8D83C1 + +Key = F868AEE434D463FB1635F209481D60815A03869198B95141F89C1485CA969730 +In = 612E7057B89390E7FA920111D2F61598D3769568E1F2675B3D13C01E +Out = 835C1C8745B16B5AD0168C646C99EEF0 + +Key = 325AC69BA9B00B0609E3DD12DB3D75681F43A398EEC2C92C9E99A440440A1E4C +In = D8AE537E24503E12405BC80DD4ECE2D48C90CA74DCFD90E87C2E756EC4 +Out = 5549B4C997557CAF14DC198869C76CA8 + +Key = EB63EABF1FC590A086E7C8AD25F2A4BFFD4AB6016EBE9D274B630353A162234B +In = 0E2934DC1FB134A1C1CF6EDAB1D0E24423E4A39538822EA2D9B94931BD23 +Out = B07A079761EB76679343540A3F75CBDF + +Key = DE07129A2B4C79FB8789D4A9564BA185A2F1F4C674ECCFEB19D0940D64CC2DD1 +In = FB01B7D9D4B46307AFF6E4DC19A211969D479D2496433B8A4B5C1B7BE2F6B9 +Out = 4E412BD481F219BB9D88B636AFC0E1D6 + +Key = 344579DD843D176804888F814E4FCB11D7D41FBB4E157E0E71DAAF5AE49FC1DA +In = D1632FBFF20101520A1B7BB071BD9089E23435633B180941F4A4F00A127EC3B8 +Out = A24F40C6F63E7FEE5458D86FCD0C340D + +Key = D29B469F0E5067BFC7597B3415B5D3EB2F55388707446A614C8233EE1AC7A052 +In = 26B5CCE0A1A1722360E0C99D65EBC49CB253536177F5F95B42BF462B7C82947B29 +Out = 24A91FAC5D4BECB46307EEED954ED011 + +Key = C5824C96352B4639AF1172BF019C93FB5507EE82815764022C89EE001ACF3A14 +In = 59F890D5F008B064D8CB8A491522A944CFEB1846521B39AAE9E198B1F7B07171BFA9 +Out = E9A211BB3F2B0A11445C5D06378309AB + +Key = 884DB7C6C2D254824A7E514D29829FB5580D77B948CEE0377D1218E674849660 +In = 25822916523687B1A68E51C55C97A56DF6893B5E2716B7F2A1483138D4D45CA7DE813F +Out = 53FA73CF055F7A21521F8D4F33915A88 + +Key = 229222BE1B32557A5741EF3182FCFDFB63A6550BAA9892EFD3DDBD67608229A7 +In = 8E8B1188CF23A77C89D474F001373B52F9A6FB76F40B28FD83345E7673812B985BD558BE +Out = C659279CDCBD804F889877137449DF73 + +Key = C3C747651BA5B9975B87ED7EAFFC023569662970558BDD2992774D4F721449E6 +In = CE8ABB5B6AFA5614C682608B7F6D1374DC282EF0E033542B5BF2C4C3B2AD02CABE5C13EAF7 +Out = E746A81205ED30C8A1872D5E81516B05 + +Key = 4ECFD1C9A89F2F5CDB6C2A99C2A8AA6A7E5DD7184B87E265D68BCDA15D1040CE +In = E6484C98EF43276B36182B8E4B9BAA058330E192E2FE0B0AEC0AEBE64A6BDC2AA4A8CD65B10A +Out = 2564EE67D9C00EF3248F3239378E25AE + +Key = D6B7BCC368DA611151F58A58096DA802FE64DFE9D18BD8A8D8FB97157EE96099 +In = CA460B21E0D3BCA60B56667B12D3C42D4F525D6DBDD37F8E14DD7B201AA03CE2E69DD4C5FCD283 +Out = F5F74E3FDAA14CC0426C89C999BA2E30 + +Key = A63CB4A43CE1EDEF181D1BD339E9DFD9DD7667BC9E5B642DFDF26E7E6DE4BA8D +In = F40FC0763C321E2F668DAFEC1422A399405629E5D1C9B80C5C1DD5D8DF7643475D13E79BADF451C6 +Out = CF5E17C8890B63A4D3E061A53C51E9FD + +Key = 040F48958744F1E8169DB72BB800CF339A4B4CD86BC237180C2E7D279093BA61 +In = 0C7291DAEE8B5EABD8F8373ED30C240474287951D8739BFA9978C252AB2D92C89C3D3730CA9AE15C90 +Out = CD7BE663024A843F0244777FDED633FF + +Key = 8F235B87E0B652FB146A4A9E1367FEDC04F009F3807049DDD8AD83D93F2392DD +In = B58BB0431016BB591040F15C2CDC303214C0E290A802F97077B7F3B0D8B7E4AC83C2662B880837AF550F +Out = A31889EB51AE63DE762F912D2020BD7D + +Key = F149D8929882EBF4457D0579AC795ADEDBF724FC2A4422FC42BD9848A44C6A06 +In = 9549A9797916B7567B011A96D43D7615ECA15BE9DD955ABDC38517033E346C2F52C505021FFE351157C190 +Out = F299FB43775F3EE5101B7D12485E11BE + +Key = 3EB6529C93F120190EC3819B5356211F67F224A1CBE1BBE8400EA3F8375506C2 +In = 4E3C135056EF1EDE0B56E67C35B359F8778944A7C060CE3D9A455E31006DAB955194E830FE458E300460967F +Out = A7E9B419DED98F092AD1034B1A008A9E + +Key = CB89B844CD47C422D94F75D7E05EB722C564A924531EEFB8EA39F5CC8154A0FA +In = 920AB028BDD9F877845E1A8995F5255AF2C6BDB2C5C218E52AC72B58571E81F27AA30EA78C50C85EF504ED056F +Out = C038DCBDE5CBE58469ADC6491CEEF8CC + +Key = DC4667C6574DDC3E949DF0F51DFDED57E1DD4FB9C7F64C93C68EBF223E2180FF +In = EC3FC04B9B01BC7CEA445E9C5A713C782C083DC75408416BCD071A2D311642DCBA891825E0044DF800E5ED65314A +Out = 2B9301B71DB683131EEDC55227925F12 + +Key = 492AB714C763ABB9BAA4FE4311B89277C2926F1BE7105262CB50C80B4B70469C +In = A9E528BCD43297E7D2F33AC7488DF5EDBEF08AAF8D1994F60098653FF6913138AB3C03262ABFDE8BAAC10033098E7E +Out = 562BFE9F91BFF7318D44E52BF5E55603 + +Key = 7C939CA4F592B90C2C65D530983740155A3F1C7C63BA0CD84EEBED1A579D959F +In = DF99C5E78BDCA6D261F0B8BF5EC7631F572BC2A6C2F734372C35CF9E2F8D812943D23F17BE0636C7FDFCD53C73F79FD2 +Out = 02BA172589E102D0C071129C74F440A9 + +Key = 7C74F59B91FD56D09A14D318A457517E83656106B6E933E590DA6A2DA1D4B0A1 +In = 75C194EEA5B223358AC7D0920F9451B20318B97A72E63FD711095746BAF5358AAAFD4DEA1F3722688799A5B0685C7E843E +Out = 351B1117D44D528ADB283F0450C50B25 + +Key = A78D532E96553A435B44CC54BBB22FB23AA1F4F41C6087C60CC9FFC564C95051 +In = 6D8EE97A667FDF890356C7CC5E69C1EB4EEFF1C11C019D257E2537797A9EB45CC2FCDA4A7536DC0CE929D7C8A0CDB9834677 +Out = AAD5FDF14D229E87816245FB06D9B505 + +Key = 7D6880EFE74747D0713956B079D74D717358B69772480DC5B9E473D71BE84A94 +In = 410351D27DF685CBD0CFDC166B3F90C0FD4A334BEF5774EF2E59948DC7BD118B4D46B3AEE139EAEB54EA0A267F8D0A2E057933 +Out = 8B4CF9CF2500A25C86FC5AB6B6565AE3 + +Key = E96CEE991E966AAA662C1C0FB5C15F422A98C5529629826B645BED629192085B +In = C6551853EC02C8315B6219564C11D319C797FCD9E4528D2700B7A562FC4A0D4DD1DD6D445F13E27EE6373539470A4AB7A9366654 +Out = 4F8D294470CDCBBABA89A246BAEA9014 + +Key = 9E89E9C49DAF18CD8EED9733AEB53D3804AF2775D61C9A833F65B0E4560C4738 +In = 2AD404004B5589253AA91D392905200B8A28F94AEBE5D45CF674B158004BFC91CC48584E7451FDEE87132B7058EC9E48CDF16F3380 +Out = 3EDA0BB3F660A60E15D90BFAA2E996F2 + +Key = A3FDA18F925C1588291F26DFB43E1B7D70AF097462F52C276A89095ED7D01685 +In = 933A72A8351DB8367E9F6E63C2A36DCB02801470AB7846308A2DF7925B6D81E50340C22457F6E3A10EBC6D7E205B113B8E5B9C9EB41E +Out = 20235C71ADA97CB8796D0CF986A7FCB4 + +Key = EF411C2190426495EF79C6913615E9A6CAC435CC4796C421331DBEF519FEACB9 +In = 54B66666FDCE1754A62C75DBBE40D4380739FA959841DF05F267EDA6C6F9049A9D1E5770E42D237AB8E411FBA613ED55F60A12A26FFEF4 +Out = D551758D4AD5DD0A52DE7CA1424A03D2 + +Key = 427525D85A907836D5024566719C9373F5684F18CB1F8B4D3F2BF6F0A8B36274 +In = 5D5AE246E9E84F54B4C8015F4FC3AB5C63A3A2F5EA257E7574940F1A3C60C796DF3E0C96B73B3EC3597504F048F7A1437FDB268ED23733F0 +Out = 39351B13A888D194BE63F869B5D0C57B + +Key = BB78DD08395D96F18BD71C084FAF26490A492E1345CA8A1190CAA509A13C1A43 +In = E324F0BC28D8C51DAC56087928BB784D613FA00E4E0399D81CF24C6317A28DF48C3A2A35BF2E16E366F9E1DBFD20C01C7B6ABA6C98F72AAF6E +Out = 1FDC7616DF7809FE775F3694D2166EBC + +Key = 325544641FC9E14C344BB0BD42C88540D6B3E8FEB2DAA8AAC4E518952831EEE8 +In = C3708D1969C9D980F1108936055BAC50ED43A3BD7DB246E34FA282F77A0F9D5968D7A1856EDD36CD06D768125ADDD3368E41E025FC689368AE20 +Out = 1935CC6A925E182589CF85BD289E8430 + +Key = 932FB37709A9DFCD232E5B6FCBCEA06DD384818DDE1BA6A85AE813A054D8437F +In = 98945E5490056F4C616BA055D5F22F05EC99834F1702057AFBD0B812E95AE669F4E6C0A940318A162EA85FA8DFE0D5F9479C87402A1E9D45649EAD +Out = 163BA4F137C343172ADAD46BCE7F1CAA + +Key = E286704F857F611C6A10FCB650A6974496AAD9A285AC6F65977B11B6E5310B16 +In = 8883CEA30073C555537BEFB1A4CA25B50E71AC313446B6039CA4CF0BFA9074AFB448EFE2B02E124F0C3EB35BFBD878F2C632C8D0AA37D9DA6858554E +Out = 3C96DB1DB3EBE7260E6527DD93E5B95D + +Key = 375B7709A43196D08C8D91406AA82B307C4A7D5CDCBF59118077B69FBDF5A649 +In = 3AD186DC498A3DAB9142AEA55899EC0AB125A0AF010DC71E77C8F9DDA9A65DD7CF4FDC41029465F3998931285D6DCC2C454CF6D5E4F73A224312C343CB +Out = 3C5D43309DF559415E6E4D2300BFA847 + +Key = 7B5532DEB4AA9DAF0EDDA3D361FAF33E83B309BF3EF7E88912E00905562049FB +In = 4FB4B3F34F54C6A1ED4BD8E5AAE61E03E99643DD1EFC996A4579AC88E6702DDA06B66F84054CC3BFCCA6CD3EB67E0569FEB48191398A27C2D605CFD6AA38 +Out = C79753AF74F8E1CC65A48190200E8F94 + +Key = 3ACC533363DFB5012D00F8F67BF5F16167E9235AB0E7D535D0C2E8E2C0F2FFAA +In = 66CA0F0DD4D4013C18BB7B51CEE12492706FDCD59DC0927FA9637A3687F1FFE6C15AC64D97FDCD6602AA7CC3B1C7E4D11FC336F4CCF516A4A4710BF41678EC +Out = 5B00273784949EC5AB564DB7AA54F008 + |