Botan
1.11.15
|
00001 /* 00002 * SRP-6a (RFC 5054 compatatible) 00003 * (C) 2011,2012 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/srp6.h> 00009 #include <botan/dl_group.h> 00010 #include <botan/numthry.h> 00011 #include <botan/lookup.h> 00012 00013 namespace Botan { 00014 00015 namespace { 00016 00017 BigInt hash_seq(const std::string& hash_id, 00018 size_t pad_to, 00019 const BigInt& in1, 00020 const BigInt& in2) 00021 { 00022 std::unique_ptr<HashFunction> hash_fn(get_hash(hash_id)); 00023 00024 hash_fn->update(BigInt::encode_1363(in1, pad_to)); 00025 hash_fn->update(BigInt::encode_1363(in2, pad_to)); 00026 00027 return BigInt::decode(hash_fn->final()); 00028 } 00029 00030 BigInt compute_x(const std::string& hash_id, 00031 const std::string& identifier, 00032 const std::string& password, 00033 const std::vector<byte>& salt) 00034 { 00035 std::unique_ptr<HashFunction> hash_fn(get_hash(hash_id)); 00036 00037 hash_fn->update(identifier); 00038 hash_fn->update(":"); 00039 hash_fn->update(password); 00040 00041 secure_vector<byte> inner_h = hash_fn->final(); 00042 00043 hash_fn->update(salt); 00044 hash_fn->update(inner_h); 00045 00046 secure_vector<byte> outer_h = hash_fn->final(); 00047 00048 return BigInt::decode(outer_h); 00049 } 00050 00051 } 00052 00053 std::string srp6_group_identifier(const BigInt& N, const BigInt& g) 00054 { 00055 /* 00056 This function assumes that only one 'standard' SRP parameter set has 00057 been defined for a particular bitsize. As of this writing that is the case. 00058 */ 00059 try 00060 { 00061 const std::string group_name = "modp/srp/" + std::to_string(N.bits()); 00062 00063 DL_Group group(group_name); 00064 00065 if(group.get_p() == N && group.get_g() == g) 00066 return group_name; 00067 00068 throw std::runtime_error("Unknown SRP params"); 00069 } 00070 catch(...) 00071 { 00072 throw Invalid_Argument("Bad SRP group parameters"); 00073 } 00074 } 00075 00076 std::pair<BigInt, SymmetricKey> 00077 srp6_client_agree(const std::string& identifier, 00078 const std::string& password, 00079 const std::string& group_id, 00080 const std::string& hash_id, 00081 const std::vector<byte>& salt, 00082 const BigInt& B, 00083 RandomNumberGenerator& rng) 00084 { 00085 DL_Group group(group_id); 00086 const BigInt& g = group.get_g(); 00087 const BigInt& p = group.get_p(); 00088 00089 const size_t p_bytes = group.get_p().bytes(); 00090 00091 if(B <= 0 || B >= p) 00092 throw std::runtime_error("Invalid SRP parameter from server"); 00093 00094 BigInt k = hash_seq(hash_id, p_bytes, p, g); 00095 00096 BigInt a(rng, 256); 00097 00098 BigInt A = power_mod(g, a, p); 00099 00100 BigInt u = hash_seq(hash_id, p_bytes, A, B); 00101 00102 const BigInt x = compute_x(hash_id, identifier, password, salt); 00103 00104 BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p); 00105 00106 SymmetricKey Sk(BigInt::encode_1363(S, p_bytes)); 00107 00108 return std::make_pair(A, Sk); 00109 } 00110 00111 BigInt generate_srp6_verifier(const std::string& identifier, 00112 const std::string& password, 00113 const std::vector<byte>& salt, 00114 const std::string& group_id, 00115 const std::string& hash_id) 00116 { 00117 const BigInt x = compute_x(hash_id, identifier, password, salt); 00118 00119 DL_Group group(group_id); 00120 return power_mod(group.get_g(), x, group.get_p()); 00121 } 00122 00123 BigInt SRP6_Server_Session::step1(const BigInt& v, 00124 const std::string& group_id, 00125 const std::string& hash_id, 00126 RandomNumberGenerator& rng) 00127 { 00128 DL_Group group(group_id); 00129 const BigInt& g = group.get_g(); 00130 const BigInt& p = group.get_p(); 00131 00132 m_p_bytes = p.bytes(); 00133 m_v = v; 00134 m_b = BigInt(rng, 256); 00135 m_p = p; 00136 m_hash_id = hash_id; 00137 00138 const BigInt k = hash_seq(hash_id, m_p_bytes, p, g); 00139 00140 m_B = (v*k + power_mod(g, m_b, p)) % p; 00141 00142 return m_B; 00143 } 00144 00145 SymmetricKey SRP6_Server_Session::step2(const BigInt& A) 00146 { 00147 if(A <= 0 || A >= m_p) 00148 throw std::runtime_error("Invalid SRP parameter from client"); 00149 00150 const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B); 00151 00152 const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p); 00153 00154 return BigInt::encode_1363(S, m_p_bytes); 00155 } 00156 00157 }