aboutsummaryrefslogtreecommitdiffstats
path: root/src/constructs
diff options
context:
space:
mode:
Diffstat (limited to 'src/constructs')
-rw-r--r--src/constructs/srp6/info.txt7
-rw-r--r--src/constructs/srp6/srp6.cpp177
-rw-r--r--src/constructs/srp6/srp6.h94
3 files changed, 278 insertions, 0 deletions
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