3 Copyright (C) 2015, 2016 est31 <MTest31@outlook.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "util/string.h"
29 // Get an sha-1 hash of the player's name combined with
30 // the password entered. That's what the server uses as
31 // their password. (Exception : if the password field is
32 // blank, we send a blank password - this is for backwards
33 // compatibility with password-less players).
34 std::string
translate_password(const std::string
&name
,
35 const std::string
&password
)
37 if (password
.length() == 0)
40 std::string slt
= name
+ password
;
42 sha1
.addBytes(slt
.c_str(), slt
.length());
43 unsigned char *digest
= sha1
.getDigest();
44 std::string pwd
= base64_encode(digest
, 20);
49 // Call lower level SRP code to generate a verifier with the
50 // given pointers. Contains the preparations, call parameters
51 // and error checking common to all srp verifier generation code.
52 // See docs of srp_create_salted_verification_key for more info.
53 static inline void gen_srp_v(const std::string
&name
,
54 const std::string
&password
, char **salt
, size_t *salt_len
,
55 char **bytes_v
, size_t *len_v
)
57 std::string n_name
= lowercase(name
);
58 SRP_Result res
= srp_create_salted_verification_key(SRP_SHA256
, SRP_NG_2048
,
59 n_name
.c_str(), (const unsigned char *)password
.c_str(),
60 password
.size(), (unsigned char **)salt
, salt_len
,
61 (unsigned char **)bytes_v
, len_v
, NULL
, NULL
);
62 FATAL_ERROR_IF(res
!= SRP_OK
, "Couldn't create salted SRP verifier");
65 /// Creates a verification key with given salt and password.
66 std::string
generate_srp_verifier(const std::string
&name
,
67 const std::string
&password
, const std::string
&salt
)
69 size_t salt_len
= salt
.size();
70 // The API promises us that the salt doesn't
71 // get modified if &salt_ptr isn't NULL.
72 char *salt_ptr
= (char *)salt
.c_str();
74 char *bytes_v
= nullptr;
75 size_t verifier_len
= 0;
76 gen_srp_v(name
, password
, &salt_ptr
, &salt_len
, &bytes_v
, &verifier_len
);
77 std::string verifier
= std::string(bytes_v
, verifier_len
);
82 /// Creates a verification key and salt with given password.
83 void generate_srp_verifier_and_salt(const std::string
&name
,
84 const std::string
&password
, std::string
*verifier
,
87 char *bytes_v
= nullptr;
89 char *salt_ptr
= nullptr;
91 gen_srp_v(name
, password
, &salt_ptr
, &salt_len
, &bytes_v
, &verifier_len
);
92 *verifier
= std::string(bytes_v
, verifier_len
);
93 *salt
= std::string(salt_ptr
, salt_len
);
98 /// Gets an SRP verifier, generating a salt,
99 /// and encodes it as DB-ready string.
100 std::string
get_encoded_srp_verifier(const std::string
&name
,
101 const std::string
&password
)
103 std::string verifier
;
105 generate_srp_verifier_and_salt(name
, password
, &verifier
, &salt
);
106 return encode_srp_verifier(verifier
, salt
);
109 /// Converts the passed SRP verifier into a DB-ready format.
110 std::string
encode_srp_verifier(const std::string
&verifier
,
111 const std::string
&salt
)
113 std::ostringstream ret_str
;
115 << base64_encode((unsigned char *)salt
.c_str(), salt
.size()) << "#"
116 << base64_encode((unsigned char *)verifier
.c_str(), verifier
.size());
117 return ret_str
.str();
120 /// Reads the DB-formatted SRP verifier and gets the verifier
121 /// and salt components.
122 bool decode_srp_verifier_and_salt(const std::string
&encoded
,
123 std::string
*verifier
, std::string
*salt
)
125 std::vector
<std::string
> components
= str_split(encoded
, '#');
127 if ((components
.size() != 4)
128 || (components
[1] != "1") // 1 means srp
129 || !base64_is_valid(components
[2])
130 || !base64_is_valid(components
[3]))
133 *salt
= base64_decode(components
[2]);
134 *verifier
= base64_decode(components
[3]);