8
8
*
9
9
*****************************************************************************/
10
10
#include " StdInc.h"
11
+ #include < charconv>
11
12
#include < SharedUtil.Crypto.h>
12
13
#include < lua/CLuaFunctionParser.h>
13
14
@@ -21,7 +22,7 @@ void CLuaCryptDefs::LoadFunctions()
21
22
{" teaDecode" , ArgumentParserWarn<false , TeaDecode>},
22
23
{" base64Encode" , ArgumentParserWarn<false , Base64encode>},
23
24
{" base64Decode" , ArgumentParserWarn<false , Base64decode>},
24
- {" passwordHash" , PasswordHash},
25
+ {" passwordHash" , ArgumentParserWarn< false , PasswordHash> },
25
26
{" passwordVerify" , PasswordVerify},
26
27
{" encodeString" , EncodeString},
27
28
{" decodeString" , DecodeString},
@@ -77,100 +78,75 @@ std::string CLuaCryptDefs::Base64decode(std::string str)
77
78
return SharedUtil::Base64decode (str);
78
79
}
79
80
80
- int CLuaCryptDefs::PasswordHash (lua_State* luaVM)
81
+ std::variant<std::string, bool > CLuaCryptDefs::PasswordHash (lua_State* luaVM, std::string password, PasswordHashFunction algorithm, std::unordered_map<std::string, std::string> options, std::optional<CLuaFunctionRef> callback )
81
82
{
82
- // string password_hash(string password, string algorithm, table options = {} [, function callback])
83
- SString password;
84
- PasswordHashFunction algorithm;
85
- CStringMap options;
86
- CLuaFunctionRef luaFunctionRef;
87
-
88
- CScriptArgReader argStream (luaVM);
89
- argStream.ReadString (password);
90
- argStream.ReadEnumString (algorithm);
91
- argStream.ReadStringMap (options);
92
-
93
- if (argStream.NextIsFunction ())
94
- {
95
- argStream.ReadFunction (luaFunctionRef);
96
- argStream.ReadFunctionComplete ();
97
- }
98
-
99
- if (!argStream.HasErrors ())
83
+ switch (algorithm)
100
84
{
101
- if (algorithm == PasswordHashFunction::Bcrypt)
85
+ case PasswordHashFunction::Bcrypt:
102
86
{
103
- // Set default value to 10
104
- if (options[" cost" ].empty ())
105
- options[" cost" ] = " 10" ;
87
+ std::size_t cost = 10 ;
106
88
107
- std::stringstream ss (options[" cost" ]);
108
- std::size_t cost;
109
- ss >> cost;
89
+ if (auto it = options.find (" cost" ); it != options.end ())
90
+ {
91
+ auto [__, err] = std::from_chars (it->second .data (), it->second .data () + it->second .length (), cost);
92
+ if (err != std::errc{})
93
+ throw std::invalid_argument (" Invalid value for field 'cost'" );
94
+ }
110
95
111
- if (!ss. fail ())
96
+ if (auto it = options. find ( " salt " ); it != options. end ())
112
97
{
113
- // Using custom salts are deprecated (Luxy.c)
98
+ // Using custom salts is deprecated
114
99
// See: https://stackoverflow.com/questions/40993645/understanding-bcrypt-salt-as-used-by-php-password-hash
115
- if (options[" salt" ].length () > 0 )
116
- {
117
- m_pScriptDebugging->LogWarning (luaVM, " Custom generated salts are deprecated and will be removed in the future." );
118
- }
100
+ m_pScriptDebugging->LogWarning (luaVM, " Custom generated salts are deprecated and will be removed in the future." );
101
+ }
119
102
120
- // Sync
121
- if (luaFunctionRef == CLuaFunctionRef{})
122
- {
123
- SString hash = SharedUtil::BcryptHash (password, options[" salt" ], cost);
124
- if (!hash.empty ())
125
- {
126
- lua_pushstring (luaVM, hash);
127
- return 1 ;
128
- }
129
- else
130
- m_pScriptDebugging->LogCustom (luaVM, " Invalid value for field 'salt'" );
131
- }
132
- else // Async
103
+ if (callback.has_value ())
104
+ {
105
+ // Async
106
+ CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaVM);
107
+ if (pLuaMain)
133
108
{
134
- CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaVM);
135
- if (pLuaMain)
136
- {
137
- CLuaShared::GetAsyncTaskScheduler ()->PushTask <SString>(
138
- [password, salt = options[" salt" ], cost] {
139
- // Execute time-consuming task
140
- return SharedUtil::BcryptHash (password, salt, cost);
141
- },
142
- [luaFunctionRef](const SString& hash) {
143
- CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaFunctionRef.GetLuaVM ());
144
- if (pLuaMain)
145
- {
146
- CLuaArguments arguments;
147
-
148
- if (hash.empty ())
149
- {
150
- m_pScriptDebugging->LogCustom (pLuaMain->GetVM (), " Invalid value for field 'salt'" );
151
- arguments.PushBoolean (false );
152
- }
153
- else
154
- arguments.PushString (hash);
109
+ CLuaShared::GetAsyncTaskScheduler ()->PushTask <SString>(
110
+ [password, salt = options[" salt" ], cost] {
111
+ // Execute time-consuming task
112
+ return SharedUtil::BcryptHash (password, salt, cost);
113
+ },
114
+ [luaFunctionRef = callback.value ()](const SString& hash) {
115
+ CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaFunctionRef.GetLuaVM ());
116
+ if (pLuaMain)
117
+ {
118
+ CLuaArguments arguments;
155
119
156
- arguments.Call (pLuaMain, luaFunctionRef);
120
+ if (hash.empty ())
121
+ {
122
+ m_pScriptDebugging->LogCustom (pLuaMain->GetVM (), " Invalid value for field 'salt'" );
123
+ arguments.PushBoolean (false );
157
124
}
158
- });
125
+ else
126
+ arguments.PushString (hash);
159
127
160
- lua_pushboolean (luaVM, true );
161
- return 1 ;
162
- }
128
+ arguments. Call (pLuaMain, luaFunctionRef );
129
+ }
130
+ });
163
131
}
164
132
}
165
133
else
166
- m_pScriptDebugging->LogWarning (luaVM, " Invalid value for field 'cost'" );
134
+ {
135
+ // Sync
136
+ SString hash = SharedUtil::BcryptHash (password, options[" salt" ], cost);
137
+ if (!hash.empty ())
138
+ {
139
+ return hash;
140
+ }
141
+ else
142
+ throw std::invalid_argument (" Invalid value for field 'salt'" );
143
+ }
144
+ return true ;
167
145
}
168
- }
169
- else
170
- m_pScriptDebugging->LogCustom (luaVM, argStream.GetFullErrorMessage ());
171
146
172
- lua_pushboolean (luaVM, false );
173
- return 1 ;
147
+ default :
148
+ throw std::invalid_argument (" Unknown algorithm" );
149
+ }
174
150
}
175
151
176
152
0 commit comments