@@ -178,16 +178,23 @@ int CLuaCryptDefs::Base64decode ( lua_State* luaVM )
178178
179179int CLuaCryptDefs::PasswordHash (lua_State* luaVM)
180180{
181- // string password_hash(string password, string algorithm, table options = {})
181+ // string password_hash(string password, string algorithm, table options = {} [, function callback] )
182182 SString password;
183183 PasswordHashFunction algorithm;
184184 std::unordered_map<SString, SString> options;
185+ CLuaFunctionRef luaFunctionRef;
185186
186187 CScriptArgReader argStream (luaVM);
187188 argStream.ReadString (password);
188189 argStream.ReadEnumString (algorithm);
189190 argStream.ReadStringMap (options, true );
190191
192+ if (argStream.NextIsFunction ())
193+ {
194+ argStream.ReadFunction (luaFunctionRef);
195+ argStream.ReadFunctionComplete ();
196+ }
197+
191198 if (!argStream.HasErrors ())
192199 {
193200 if (algorithm == PasswordHashFunction::Bcrypt)
@@ -202,14 +209,45 @@ int CLuaCryptDefs::PasswordHash(lua_State* luaVM)
202209
203210 if (!ss.fail ())
204211 {
205- SString hash = SharedUtil::BcryptHash (password, options[" salt" ], cost);
206- if (!hash.empty ())
212+ // Sync
213+ if (luaFunctionRef == CLuaFunctionRef{})
214+ {
215+ SString hash = SharedUtil::BcryptHash (password, options[" salt" ], cost);
216+ if (!hash.empty ())
217+ {
218+ lua_pushstring (luaVM, hash);
219+ return 1 ;
220+ }
221+ else
222+ m_pScriptDebugging->LogCustom (luaVM, " Invalid value for field 'salt'" );
223+ }
224+ else // Async
207225 {
208- lua_pushstring (luaVM, hash);
209- return 1 ;
226+ CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaVM);
227+ if (pLuaMain)
228+ {
229+ CLuaShared::GetAsyncTaskScheduler ()->PushTask <SString>([password, salt = options[" salt" ], cost] {
230+ // Execute time-consuming task
231+ return SharedUtil::BcryptHash (password, salt, cost);
232+
233+ }, [luaFunctionRef, pLuaMain](const SString& hash) {
234+ CLuaArguments arguments;
235+
236+ if (hash.empty ())
237+ {
238+ m_pScriptDebugging->LogCustom (pLuaMain->GetVM (), " Invalid value for field 'salt'" );
239+ arguments.PushBoolean (false );
240+ }
241+ else
242+ arguments.PushString (hash);
243+
244+ arguments.Call (pLuaMain, luaFunctionRef);
245+ });
246+
247+ lua_pushboolean (luaVM, true );
248+ return 1 ;
249+ }
210250 }
211- else
212- m_pScriptDebugging->LogCustom (luaVM, " Invalid value for field 'salt'" );
213251 }
214252 else
215253 m_pScriptDebugging->LogWarning (luaVM, " Invalid value for field 'cost'" );
@@ -224,19 +262,49 @@ int CLuaCryptDefs::PasswordHash(lua_State* luaVM)
224262
225263int CLuaCryptDefs::PasswordVerify (lua_State* luaVM)
226264{
227- // bool passwordVerify(string password, string hash)
265+ // bool passwordVerify(string password, string hash [, function callback] )
228266 SString password;
229267 SString hash;
268+ CLuaFunctionRef luaFunctionRef;
230269
231270 CScriptArgReader argStream (luaVM);
232271 argStream.ReadString (password);
233272 argStream.ReadString (hash);
234273
274+ if (argStream.NextIsFunction ())
275+ {
276+ argStream.ReadFunction (luaFunctionRef);
277+ argStream.ReadFunctionComplete ();
278+ }
279+
235280 if (!argStream.HasErrors ())
236281 {
237282 if (hash.BeginsWith (" $2y$" ))
238283 {
239- lua_pushboolean (luaVM, SharedUtil::BcryptVerify (password, hash));
284+ // Sync
285+ if (luaFunctionRef == CLuaFunctionRef ())
286+ {
287+ lua_pushboolean (luaVM, SharedUtil::BcryptVerify (password, hash));
288+ }
289+ else // Async
290+ {
291+ CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine (luaVM);
292+ if (pLuaMain)
293+ {
294+ CLuaShared::GetAsyncTaskScheduler ()->PushTask <bool >([password, hash]{
295+ // Execute time-consuming task
296+ return SharedUtil::BcryptVerify (password, hash);
297+
298+ }, [luaFunctionRef, pLuaMain](const bool & correct) {
299+ CLuaArguments arguments;
300+ arguments.PushBoolean (correct);
301+
302+ arguments.Call (pLuaMain, luaFunctionRef);
303+ });
304+
305+ lua_pushboolean (luaVM, true );
306+ }
307+ }
240308 return 1 ;
241309 }
242310 else
0 commit comments