(notonline)--> -- demo\rosetta\SQL-based_authentication.exw without js -- (file i/o) include pSQLite.e include md5.exw sqlite3_stmt pAddUser = NULL procedure add_user(sqlite3 db, string name, pw) if pAddUser=NULL then pAddUser = sqlite3_prepare(db,"INSERT INTO users (username,pass_salt,pass_md5) VALUES(:name, :salt, :md5);") end if string salt = sq_rand(repeat(#FF,16)), md5s = md5(salt&pw) sqlite3_bind_text(pAddUser,":name", name) sqlite3_bind_text(pAddUser,":salt", salt) sqlite3_bind_text(pAddUser,":md5", md5s) {} = sqlite3_step(pAddUser) -- (nb: ignores any errors.) sqlite3_reset(pAddUser) end procedure sqlite3_stmt pAuthUser = NULL function authenticate_user(sqlite3 db, string name, pw) if pAuthUser=NULL then pAuthUser = sqlite3_prepare(db,"SELECT pass_salt, pass_md5 FROM users WHERE username = :name;") end if sqlite3_bind_text(pAuthUser,":name", name) integer res = sqlite3_step(pAuthUser) if res!=SQLITE_ROW then res = false -- (no such user) else string salt = sqlite3_column_text(pAuthUser,1) string pass_md5 = sqlite3_column_text(pAuthUser,2) res = (pass_md5==md5(salt&pw)) end if sqlite3_reset(pAuthUser) return res end function constant create_cmd = """ CREATE TABLE IF NOT EXISTS users( userid INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(32) UNIQUE NOT NULL, pass_salt tinyblob, -- a string of 16 random bytes pass_md5 tinyblob); -- binary MD5 hash of pass_salt concatenated with the password """ procedure main() sequence sqlversion = sqlite3_libversion(true) if sqlversion<{3,3,0} then crash("a newer sqlite.dll/so is required (for IF NOT EXISTS)") end if sqlite3 db = sqlite3_open("users.sqlite") integer res = sqlite3_exec(db,create_cmd) if res!=SQLITE_OK then ?9/0 end if sqlite3_set_fatal_id(SQLITE3_NON_FATAL) -- (else trying to re-add user crashes) add_user(db,"user","password") printf(1,"user with correct password:%t\n",authenticate_user(db, "user", "password")) printf(1,"user with incorrect password:%t\n",authenticate_user(db, "user", "wrong")) if pAddUser!=NULL then if sqlite3_finalize(pAddUser)!=SQLITE_OK then ?9/0 end if end if if pAuthUser!=NULL then if sqlite3_finalize(pAuthUser)!=SQLITE_OK then ?9/0 end if end if sqlite3_close(db) ?"done" {} = wait_key() end procedure main()