| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of LibCat nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef CAT_KEY_AGREEMENT_HPP
- #define CAT_KEY_AGREEMENT_HPP
- #include <cat/math/BigTwistedEdwards.hpp>
- #include <cat/crypt/rand/Fortuna.hpp>
- namespace cat {
- /*
- Tunnel Key Agreement "Tabby" protocol:
- An unauthenticated Diffie-Hellman key agreement protocol with forward secrecy
- Immune to active attacks (man-in-the-middle) if server key is known ahead of time
- Using Elliptic Curve Cryptography over finite field Fp, p = 2^n - c, c small
- Shape of curve: a' * x^2 + y^2 = 1 + d' * x^2 * y^2, a' = -1 (square in Fp)
- d' (non square in Fp) -> order of curve = q * cofactor h, order of generator point = q
- Curves satisfy MOV conditions and are not anomalous
- Point operations performed with Extended Twisted Edwards group laws
- See BigTwistedEdwards.hpp for more information
- H: Skein-Key, either 256-bit or 512-bit based on security level
- MAC: Skein-MAC, keyed from output of H()
- Here the protocol initiator is the (c)lient, and the responder is the (s)erver:
- s: long-term private key 1 < b < q, long-term public key B = b * G
- 256-bit security: B = 64 bytes for public key, b = 32 bytes for private key
- 384-bit security: B = 96 bytes for public key, b = 48 bytes for private key
- 512-bit security: B = 128 bytes for public key, b = 64 bytes for private key
- c: Client already knows the server's public key B before Key Agreement
- c: ephemeral private key 1 < a < q, ephemeral public key A = a * G
- Initiator Challenge: c2s A
- 256-bit security: A = 64 bytes
- 384-bit security: A = 96 bytes
- 512-bit security: A = 128 bytes
- s: validate A, ignore invalid
- Invalid A(x,y) would be the additive identity x=0 or any point not on the curve
- s: ephemeral private key 1 < y < q, ephemeral public key Y = y * G
- Ephemeral key is re-used for several connections before being regenerated
- s: hA = h * A
- s: random n-bit number r
- s: d = H(A,B,Y,r)
- Repeat the previous two steps until d >= 1000
- s: e = b + d*y (mod q)
- s: T = AffineX(e * hA)
- s: k = H(d,T)
- Responder Answer: s2c Y || r || MAC(k) {"responder proof"}
- 256-bit security: Y(64by) r(32by) MAC(32by) = 128 bytes
- 384-bit security: Y(96by) r(48by) MAC(48by) = 192 bytes
- 512-bit security: Y(128by) r(64by) MAC(64by) = 256 bytes
- c: validate Y, ignore invalid
- Invalid Y(x,y) would be the additive identity x=0 or any point not on the curve
- c: hY = h * Y
- c: d = H(A,B,Y,r)
- c: Verify d >= 1000
- c: T = AffineX(a * hB + d*a * hY)
- c: k = H(d,T)
- c: validate MAC, ignore invalid
- Initiator Proof: c2s MAC(k) {"initiator proof"}
- This packet can also include the client's first encrypted message
- 256-bit security: MAC(32by) = 32 bytes
- 384-bit security: MAC(48by) = 48 bytes
- 512-bit security: MAC(64by) = 64 bytes
- s: validate MAC, ignore invalid
- Notes:
- The strategy of this protocol is to perform two EC Diffie-Hellman exchanges,
- one with the long-term server key and the second with an ephemeral key that
- should be much harder to obtain by an attacker. The resulting two shared
- secret points are added together into one point that is used for the key.
- It is perfectly acceptable to re-use an ephemeral key for several runs of
- the protocol. This means that most of the processing done by the server is
- just one point multiplication.
- */
- /*
- Schnorr signatures:
- For signing, the signer reuses its Key Agreement key pair (b,B)
- H: Skein-Key, either 256-bit or 512-bit based on security level
- To sign a message M, signer computes:
- ephemeral secret random 1 < k < q, ephemeral point K = k * G
- e = H(M || K)
- s = k - b*e (mod q)
- This process is repeated until e and s are non-zero
- Signature: s2c e || s
- 256-bit security: e(32by) s(32by) = 64 bytes
- 384-bit security: e(48by) s(48by) = 96 bytes
- 512-bit security: e(64by) s(64by) = 128 bytes
- To verify a signature:
- Check e, s are in the range [1,q-1]
- K' = s*G + e*B
- e' = H(M || K')
- The signature is verified if e == e'
- Notes:
- K ?= K'
- = s*G + e*B
- = (k - b*e)*G + e*(b*G)
- = k*G - b*e*G + e*b*G
- = K
- */
- // If CAT_DETERMINISTIC_KEY_GENERATION is undefined, the time to generate a
- // key is unbounded, but tends to be 1 try. I think this is a good thing
- // because it randomizes the runtime and helps avoid timing attacks
- //#define CAT_DETERMINISTIC_KEY_GENERATION
- // If CAT_USER_ERROR_CHECKING is defined, the key agreement objects will
- // check to make sure that the input parameters are all the right length
- // and that the math and prng objects are not null
- #define CAT_USER_ERROR_CHECKING
- class CAT_EXPORT KeyAgreementCommon
- {
- public:
- static BigTwistedEdwards *InstantiateMath(int bits);
- // Math library register usage
- static const int ECC_REG_OVERHEAD = 21;
- // c: field prime modulus p = 2^bits - C, p = 5 mod 8 s.t. a=-1 is a square in Fp
- // d: curve coefficient (yy-xx=1+Dxxyy), not a square in Fp
- static const int EDWARD_C_256 = 435;
- static const int EDWARD_D_256 = 31720;
- static const int EDWARD_C_384 = 2147;
- static const int EDWARD_D_384 = 13036;
- static const int EDWARD_C_512 = 875;
- static const int EDWARD_D_512 = 32;
- // Limits on field prime
- static const int MAX_BITS = 512;
- static const int MAX_BYTES = MAX_BITS / 8;
- static const int MAX_LEGS = MAX_BYTES / sizeof(Leg);
- protected:
- int KeyBits, KeyBytes, KeyLegs;
- bool Initialize(int bits);
- public:
- // Generates an unbiased random key in the range 1 < key < q
- void GenerateKey(BigTwistedEdwards *math, IRandom *prng, Leg *key);
- };
- } // namespace cat
- #endif // CAT_KEY_AGREEMENT_HPP
|