diff options
-rw-r--r-- | doc/log.txt | 3 | ||||
-rw-r--r-- | src/constructs/srp6/info.txt | 7 | ||||
-rw-r--r-- | src/constructs/srp6/srp6.cpp | 177 | ||||
-rw-r--r-- | src/constructs/srp6/srp6.h | 94 | ||||
-rw-r--r-- | src/libstate/policy.cpp | 10 |
5 files changed, 291 insertions, 0 deletions
diff --git a/doc/log.txt b/doc/log.txt index 47c80d4fb..94c760a8a 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -10,6 +10,9 @@ Series 1.10 Version 1.10.2, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* An implementation of SRP-6a compatible with the specification in + RFC 5054 is now available in srp6.h + * The exception catching syntax of configure.py has been changed to the Python 3.x syntax. This syntax also works with Python 2.6 and 2.7, but not with any earlier Python 2 release. A simple search and diff --git a/src/constructs/srp6/info.txt b/src/constructs/srp6/info.txt new file mode 100644 index 000000000..7962bd383 --- /dev/null +++ b/src/constructs/srp6/info.txt @@ -0,0 +1,7 @@ +define SRP6 + +<requires> +bigint +hash +dl_group +</requires> diff --git a/src/constructs/srp6/srp6.cpp b/src/constructs/srp6/srp6.cpp new file mode 100644 index 000000000..995244688 --- /dev/null +++ b/src/constructs/srp6/srp6.cpp @@ -0,0 +1,177 @@ +/* +* SRP-6a +* (C) 2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/srp6.h> +#include <botan/dl_group.h> +#include <botan/libstate.h> +#include <botan/numthry.h> +#include <memory> + +namespace Botan { + +namespace { + +BigInt hash_seq(const std::string& hash_id, + size_t pad_to, + const BigInt& in1, + const BigInt& in2) + { + std::auto_ptr<HashFunction> hash_fn( + global_state().algorithm_factory().make_hash_function(hash_id)); + + hash_fn->update(BigInt::encode_1363(in1, pad_to)); + hash_fn->update(BigInt::encode_1363(in2, pad_to)); + + return BigInt::decode(hash_fn->final()); + } + +BigInt hash_seq(const std::string& hash_id, + size_t pad_to, + const BigInt& in1, + const BigInt& in2, + const BigInt& in3) + { + std::auto_ptr<HashFunction> hash_fn( + global_state().algorithm_factory().make_hash_function(hash_id)); + + hash_fn->update(BigInt::encode_1363(in1, pad_to)); + hash_fn->update(BigInt::encode_1363(in2, pad_to)); + hash_fn->update(BigInt::encode_1363(in3, pad_to)); + + return BigInt::decode(hash_fn->final()); + } + +BigInt compute_x(const std::string& hash_id, + const std::string& identifier, + const std::string& password, + const MemoryRegion<byte>& salt) + { + std::auto_ptr<HashFunction> hash_fn( + global_state().algorithm_factory().make_hash_function(hash_id)); + + hash_fn->update(identifier); + hash_fn->update(":"); + hash_fn->update(password); + + SecureVector<byte> inner_h = hash_fn->final(); + + hash_fn->update(salt); + hash_fn->update(inner_h); + + SecureVector<byte> outer_h = hash_fn->final(); + + return BigInt::decode(outer_h); + } + +} + +std::pair<BigInt, BigInt> +SRP6_Client_Session:: step1(const std::string& identifier, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const MemoryRegion<byte>& salt, + const BigInt& B, + RandomNumberGenerator& rng) + { + DL_Group group(group_id); + const BigInt& g = group.get_g(); + const BigInt& p = group.get_p(); + + p_bytes = group.get_p().bytes(); + + if(B % p == 0) + throw std::runtime_error("Invalid SRP parameter from server"); + + BigInt k = hash_seq(hash_id, p_bytes, p, g); + + BigInt a(rng, p.bits() - 1); + + A = power_mod(g, a, p); + + BigInt u = hash_seq(hash_id, p_bytes, A, B); + + const BigInt x = compute_x(hash_id, identifier, password, salt); + + S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p); + + this->hash_id = hash_id; + + M1 = hash_seq(hash_id, p_bytes, A, B, S); + + return std::make_pair<BigInt, BigInt>(A, M1); + } + +SymmetricKey SRP6_Client_Session::step2(const BigInt& M2) + { + BigInt M2x = hash_seq(hash_id, p_bytes, A, M1, S); + + if(M2 != M2x) + throw std::runtime_error("Bad verification value from server"); + + return SymmetricKey(BigInt::encode_1363(S, p_bytes)); + } + +BigInt SRP6_Client_Session::generate_verifier(const std::string& identifier, + const std::string& password, + const MemoryRegion<byte>& salt, + const std::string& group_id, + const std::string& hash_id) + { + const BigInt x = compute_x(hash_id, identifier, password, salt); + + DL_Group group(group_id); + return power_mod(group.get_g(), x, group.get_p()); + } + +BigInt SRP6_Server_Session::step1(const BigInt& v, + const std::string& group_id, + const std::string& hash_id, + RandomNumberGenerator& rng) + { + DL_Group group(group_id); + const BigInt& g = group.get_g(); + const BigInt& p = group.get_p(); + + p_bytes = p.bytes(); + + BigInt k = hash_seq(hash_id, p_bytes, p, g); + + BigInt b(rng, p.bits() - 1); + + B = (v*k + power_mod(g, b, p)) % p; + + this->v = v; + this->b = b; + this->p = p; + this->hash_id = hash_id; + + return B; + } + +std::pair<SymmetricKey, BigInt> SRP6_Server_Session::step2(const BigInt& A, const BigInt& M1) + { + if(A % p == 0) + throw std::runtime_error("Invalid SRP parameter from client"); + + BigInt u = hash_seq(hash_id, p_bytes, A, B); + + BigInt S = power_mod(A * power_mod(v, u, p), b, p); + + BigInt M1x = hash_seq(hash_id, p_bytes, A, B, S); + + if(M1 != M1x) + throw std::runtime_error("Bad verification value from client"); + + BigInt M2 = hash_seq(hash_id, p_bytes, A, M1, S); + + SymmetricKey Sk = BigInt::encode_1363(S, p_bytes); + + return std::make_pair<SymmetricKey, BigInt>(Sk, M2); + } + +} diff --git a/src/constructs/srp6/srp6.h b/src/constructs/srp6/srp6.h new file mode 100644 index 000000000..fbb4a686d --- /dev/null +++ b/src/constructs/srp6/srp6.h @@ -0,0 +1,94 @@ +/* +* SRP-6a (RFC 5054 compatatible) +* (C) 2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_RFC5054_SRP6_H__ +#define BOTAN_RFC5054_SRP6_H__ + +#include <botan/bigint.h> +#include <botan/hash.h> +#include <botan/rng.h> +#include <botan/symkey.h> +#include <string> + +namespace Botan { + +/** + +*/ +class BOTAN_DLL SRP6_Client_Session + { + public: + + /** + * Client side step 1 + * @param username the username we are attempting login for + * @param password the password we are attempting to use + * @param group_id specifies the shared SRP group + * @param hash_id specifies a secure hash function + * @param salt is the salt value sent by the server + * @param B is the server's public value + * @param rng is a random number generator + * + * @return (A,M1) the client public key and verification values, + which are sent to the server + */ + std::pair<BigInt, BigInt> step1(const std::string& username, + const std::string& password, + const std::string& group_id, + const std::string& hash_id, + const MemoryRegion<byte>& salt, + const BigInt& B, + RandomNumberGenerator& rng); + + /** + * Client side step 2 + * @param M2 the server verification value + * @return shared secret key + */ + SymmetricKey step2(const BigInt& M2); + + /** + * Generate a new SRP-6 verifier + * @param identifier a username or other client identifier + * @param password the secret used to authenticate user + * @param salt a randomly chosen value, at least 128 bits long + */ + static BigInt generate_verifier(const std::string& identifier, + const std::string& password, + const MemoryRegion<byte>& salt, + const std::string& group_id, + const std::string& hash_id); + + private: + std::string hash_id; + BigInt A, M1, S; + size_t p_bytes; + }; + +class BOTAN_DLL SRP6_Server_Session + { + public: + /** + * Server side step 1 + * @param v the verification value saved from client registration + */ + BigInt step1(const BigInt& v, + const std::string& group_id, + const std::string& hash_id, + RandomNumberGenerator& rng); + + std::pair<SymmetricKey, BigInt> step2(const BigInt& A, const BigInt& M1); + + private: + std::string hash_id; + BigInt B, b, v, S, p; + size_t p_bytes; + }; + +} + +#endif diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp index 208414143..f91eed1d8 100644 --- a/src/libstate/policy.cpp +++ b/src/libstate/policy.cpp @@ -302,6 +302,16 @@ void set_default_dl_groups(Library_State& config) "Nf2tRM/S10+SCL4lj/MklDMo9nMpwP//////////" "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/srp/1024", + "-----BEGIN X942 DH PARAMETERS-----" + "MIIBCgKBgQDurwq5rbON1pwz+Ar6j8XoYHJhh3X/PAueojFMnCVldtZ033SW6oHT" + "ODtIE9aSxuDg1djiULmL5I5JXB1gidrRXcfXtGFU1rbOjvStabFdSYJVmyl7zxiF" + "xSn1ZmYOV+xo7bw8BXJswC/Uy/SXbqqa/VE4/oN2Q1ufxh0vwOsG4wIBAgKBgHdX" + "hVzW2cbrThn8BX1H4vQwOTDDuv+eBc9RGKZOErK7azpvukt1QOmcHaQJ60ljcHBq" + "7HEoXMXyRySuDrBE7Wiu4+vaMKprW2dHela02K6kwSrNlL3njELilPqzMwcr9jR2" + "3h4CuTZgF+pl+ku3VU1+qJx/Qbshrc/jDpfgdYNx" + "-----END X942 DH PARAMETERS-----"); + config.set("dl", "modp/ietf/1536", "-----BEGIN X942 DH PARAMETERS-----" "MIIBigKBwQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5si" |