Typing Pattern Authentication (Keystroke Biometrics)

import keyboard

import time

import numpy as np

from sklearn.linear_model import LogisticRegression

from sklearn.model_selection import train_test_split

from sklearn.metrics import accuracy_score

import pickle


PHRASE = "securetyping"

MODEL_FILE = "keystroke_model.pkl"


# --------------------------------------------------

# Capture keystroke timing

# --------------------------------------------------

def capture_keystrokes(prompt):

    print("\n" + prompt)

    print(f"Type exactly: '{PHRASE}' and press Enter")


    timings = []

    press_times = {}


    def on_press(e):

        if e.name == "enter":

            return

        press_times[e.name] = time.time()


    def on_release(e):

        if e.name == "enter":

            return

        if e.name in press_times:

            dwell = time.time() - press_times[e.name]

            timings.append(dwell)


    keyboard.on_press(on_press)

    keyboard.on_release(on_release)


    typed = input("> ")


    keyboard.unhook_all()


    if typed != PHRASE:

        print(" Incorrect phrase typed.")

        return None


    return timings



# --------------------------------------------------

# Collect training samples

# --------------------------------------------------

def collect_samples(samples=10):

    data = []

    print("\n Training Phase")

    for i in range(samples):

        t = capture_keystrokes(f"Sample {i + 1}/{samples}")

        if t:

            data.append(t)


    min_len = min(len(x) for x in data)

    data = [x[:min_len] for x in data]


    return np.array(data)



# --------------------------------------------------

# Train ML model

# --------------------------------------------------

def train_model(data):

    X = data

    y = np.ones(len(X))  # Legitimate user = 1


    # Add fake impostor data (noise)

    impostor = np.random.uniform(0.05, 0.4, size=X.shape)

    X = np.vstack((X, impostor))

    y = np.hstack((y, np.zeros(len(impostor))))


    X_train, X_test, y_train, y_test = train_test_split(

        X, y, test_size=0.25, random_state=42

    )


    model = LogisticRegression()

    model.fit(X_train, y_train)


    acc = accuracy_score(y_test, model.predict(X_test))

    print(f"\nšŸ“Š Model Accuracy: {acc * 100:.2f}%")


    with open(MODEL_FILE, "wb") as f:

        pickle.dump(model, f)


    print("✅ Model saved.")



# --------------------------------------------------

# Authenticate user

# --------------------------------------------------

def authenticate():

    with open(MODEL_FILE, "rb") as f:

        model = pickle.load(f)


    t = capture_keystrokes("šŸ” Authentication Attempt")

    if not t:

        return


    t = np.array(t).reshape(1, -1)

    prediction = model.predict(t)[0]

    confidence = model.predict_proba(t)[0][1]


    if prediction == 1:

        print(f" Access Granted (Confidence: {confidence:.2f})")

    else:

        print(f" Access Denied (Confidence: {confidence:.2f})")



# --------------------------------------------------

# MAIN

# --------------------------------------------------

if __name__ == "__main__":

    print("""

Keystroke Biometrics Demo

1. Train new user

2. Authenticate

""")


    choice = input("Choose option (1/2): ").strip()


    if choice == "1":

        data = collect_samples(samples=8)

        train_model(data)


    elif choice == "2":

        authenticate()


    else:

        print("Invalid choice.")


No comments: