Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
79
Task/SQL-based-authentication/Go/sql-based-authentication.go
Normal file
79
Task/SQL-based-authentication/Go/sql-based-authentication.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
func connectDB() (*sql.DB, error) {
|
||||
return sql.Open("mysql", "rosetta:code@/rc")
|
||||
}
|
||||
|
||||
func createUser(db *sql.DB, user, pwd string) error {
|
||||
salt := make([]byte, 16)
|
||||
rand.Reader.Read(salt)
|
||||
_, err := db.Exec(`insert into users (username, pass_salt, pass_md5)
|
||||
values (?, ?, ?)`, user, salt, saltHash(salt, pwd))
|
||||
if err != nil {
|
||||
return fmt.Errorf("User %s already exits", user)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func authenticateUser(db *sql.DB, user, pwd string) error {
|
||||
var salt, hash []byte
|
||||
row := db.QueryRow(`select pass_salt, pass_md5 from users
|
||||
where username=?`, user)
|
||||
if err := row.Scan(&salt, &hash); err != nil {
|
||||
return fmt.Errorf("User %s unknown", user)
|
||||
}
|
||||
if !bytes.Equal(saltHash(salt, pwd), hash) {
|
||||
return fmt.Errorf("User %s invalid password", user)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func saltHash(salt []byte, pwd string) []byte {
|
||||
h := md5.New()
|
||||
h.Write(salt)
|
||||
h.Write([]byte(pwd))
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// demonstrate
|
||||
db, err := connectDB()
|
||||
defer db.Close()
|
||||
createUser(db, "sam", "123")
|
||||
err = authenticateUser(db, "sam", "123")
|
||||
if err == nil {
|
||||
fmt.Println("User sam authenticated")
|
||||
}
|
||||
|
||||
// extra
|
||||
fmt.Println()
|
||||
// show contents of database
|
||||
rows, _ := db.Query(`select username, pass_salt, pass_md5 from users`)
|
||||
var user string
|
||||
var salt, hash []byte
|
||||
for rows.Next() {
|
||||
rows.Scan(&user, &salt, &hash)
|
||||
fmt.Printf("%s %x %x\n", user, salt, hash)
|
||||
}
|
||||
// try creating same user again
|
||||
err = createUser(db, "sam", "123")
|
||||
fmt.Println(err)
|
||||
// try authenticating unknown user
|
||||
err = authenticateUser(db, "pam", "123")
|
||||
fmt.Println(err)
|
||||
// try wrong password
|
||||
err = authenticateUser(db, "sam", "1234")
|
||||
fmt.Println(err)
|
||||
// clear table to run program again
|
||||
db.Exec(`truncate table users`)
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
use ODBC;
|
||||
use Encryption;
|
||||
|
||||
class SqlTest {
|
||||
@conn : Connection;
|
||||
|
||||
function : Main(args : String[]) ~ Nil {
|
||||
SqlTest->New()->Run();
|
||||
}
|
||||
|
||||
New() {
|
||||
@conn := Connection->New("test", "root", "helloworld");
|
||||
}
|
||||
|
||||
method : Run() ~ Nil {
|
||||
CreateUser("objeck", "beer");
|
||||
AuthenticateUser("objeck", "beer");
|
||||
leaving {
|
||||
@conn->Close();
|
||||
};
|
||||
}
|
||||
|
||||
method : AuthenticateUser(username : String, password : String) ~ Nil {
|
||||
status := false;
|
||||
ps : ParameterStatement;
|
||||
result : ResultSet;
|
||||
if(@conn->IsOpen()) {
|
||||
sql := "SELECT pass_salt, pass_md5 FROM users WHERE username = ?";
|
||||
ps := @conn->CreateParameterStatement(sql);
|
||||
ps->SetVarchar(1, username);
|
||||
|
||||
result := ps->Select();
|
||||
if(result <> Nil & result->Next()) {
|
||||
salt_buffer := Byte->New[16];
|
||||
result->GetBlob(1, salt_buffer);
|
||||
salt := "";
|
||||
for(i := 0; i < 16; i+=1;) {
|
||||
salt->Append(salt_buffer[i]);
|
||||
};
|
||||
|
||||
db_password_buffer := Byte->New[16];
|
||||
result->GetBlob(2, db_password_buffer);
|
||||
|
||||
password->Append(salt);
|
||||
user_password_buffer := Hash->MD5(password->ToByteArray());
|
||||
|
||||
IO.Console->Print("user: authenticated=")->PrintLine(IsEqual(db_password_buffer, user_password_buffer));
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
leaving {
|
||||
if(ps <> Nil) {
|
||||
ps->Close();
|
||||
};
|
||||
|
||||
if(ps <> Nil) {
|
||||
ps->Close();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
method : CreateUser(username : String, password : String) ~ Nil {
|
||||
salt := "";
|
||||
for(i := 0; i < 16; i+=1;) { salt->Append((Float->Random() * 100)->As(Int)); };
|
||||
salt := salt->SubString(16);
|
||||
|
||||
password->Append(salt);
|
||||
md5_password := Hash->MD5(password->ToByteArray());
|
||||
|
||||
ps : ParameterStatement;
|
||||
if(@conn->IsOpen()) {
|
||||
sql := "INSERT INTO users(username, pass_salt, pass_md5) VALUES (?, ?, ?)";
|
||||
ps := @conn->CreateParameterStatement(sql);
|
||||
ps->SetVarchar(1, username);
|
||||
ps->SetBytes(2, salt->ToByteArray());
|
||||
ps->SetBytes(3, md5_password);
|
||||
|
||||
IO.Console->Print("adding user: username=")->Print(username)
|
||||
->Print(", salt=")->Print(salt)
|
||||
->Print(", status=")->PrintLine(ps->Update());
|
||||
};
|
||||
|
||||
leaving {
|
||||
if(ps <> Nil) {
|
||||
ps->Close();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
method : IsEqual(left : Byte[], right : Byte[]) ~ Bool {
|
||||
if(left->Size() <> right->Size()) {
|
||||
return false;
|
||||
};
|
||||
|
||||
each(i : left) {
|
||||
if(left[i] <> right[i]) {
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue