Skip to content

Add owner-scan login gate with secure signature matching#1

Merged
Syko12345 merged 4 commits into
mainfrom
copilot/create-security-tool
Jun 4, 2026
Merged

Add owner-scan login gate with secure signature matching#1
Syko12345 merged 4 commits into
mainfrom
copilot/create-security-tool

Conversation

Copilot AI commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

This change introduces a minimal login-side ownership check: each account stores a trusted scan signature, and login is denied when the captured scan does not match the enrolled owner profile. The goal is to add a discreet identity-verification layer before granting access.

  • Owner scan enrollment + verification CLI

    • Added owner_scan_auth.py with two commands:
      • enroll <account_id> <scan_data>: stores the account’s trusted scan signature.
      • login <account_id> <scan_data>: compares login scan to enrolled signature and returns deny on mismatch.
    • Persists signatures in a JSON-backed database (--database path configurable).
  • Security-focused matching behavior

    • Normalizes scan input before hashing to reduce trivial formatting variance.
    • Uses SHA-256 for stored signatures (no raw scan data persistence).
    • Uses constant-time comparison (hmac.compare_digest) for verification.
  • Focused automated coverage

    • Added tests/test_owner_scan_auth.py covering:
      • match → allow
      • mismatch → deny
      • unknown account → deny
  • Documentation

    • Updated README.md with quick-start commands for enrollment and login verification.
python owner_scan_auth.py --database owner_scans.json enroll alice "FaceVector:12345"
python owner_scan_auth.py --database owner_scans.json login  alice "FaceVector:12345"   # Access granted
python owner_scan_auth.py --database owner_scans.json login  alice "FaceVector:wrong"  # Access denied
Original prompt

I want to. Create a tool for added security so that a device will secretly scan the person trying to log in and deny if the person is not the actual account owner

Copilot AI changed the title [WIP] Add tool for enhanced login security Add owner-scan login gate with secure signature matching Jun 4, 2026
Copilot AI requested a review from Syko12345 June 4, 2026 20:45
@Syko12345

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request

@Syko12345 Syko12345 marked this pull request as ready for review June 4, 2026 20:48
@Syko12345

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Add owner-scan login gate with secure signature matching

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Introduces owner-scan authentication tool for device login verification
• Implements secure signature matching with SHA-256 hashing and constant-time comparison
• Adds CLI commands for enrollment and login verification with JSON database persistence
• Includes comprehensive test coverage for matching, mismatching, and unknown account scenarios
Diagram
flowchart LR
  A["Scan Data Input"] --> B["Normalize & Hash"]
  B --> C["SHA-256 Signature"]
  C --> D{Enroll or Login?}
  D -->|Enroll| E["Store in Database"]
  D -->|Login| F["Compare with Stored"]
  F --> G{Constant-Time Match?}
  G -->|Yes| H["Access Granted"]
  G -->|No| I["Access Denied"]

Loading

Grey Divider

File Changes

1. owner_scan_auth.py ✨ Enhancement +104/-0

Owner scan authentication tool implementation

• Implements owner scan enrollment and verification with SHA-256 hashing
• Provides enroll_owner_scan() and verify_owner_scan() core functions
• Uses hmac.compare_digest() for constant-time signature comparison
• Includes CLI interface with subcommands for enroll and login operations
• Manages JSON-backed database for storing hashed scan signatures

owner_scan_auth.py


2. tests/test_owner_scan_auth.py 🧪 Tests +31/-0

Owner scan authentication test coverage

• Tests successful login when scan matches enrolled owner signature
• Tests login denial when scan does not match owner signature
• Tests login denial for unknown accounts without enrollment
• Uses temporary directory for isolated test database

tests/test_owner_scan_auth.py


3. README.md 📝 Documentation +14/-0

Documentation for owner scan tool

• Adds "Owner login scan tool" section documenting the new feature
• Provides quick-start examples for enrollment and login verification
• References the tool location and explains hashed signature storage behavior

README.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 4, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0)

Grey Divider


Action required

1. Empty scan crashes login 🐞 Bug ☼ Reliability
Description
verify_owner_scan() calls create_scan_signature(), which raises ValueError on empty/whitespace-only
scan input, and main() does not catch it. This makes the login command crash instead of returning an
"Access denied" decision.
Code

owner_scan_auth.py[R59-60]

+    attempted_signature = create_scan_signature(attempted_scan_data)
+    return hmac.compare_digest(expected_signature, attempted_signature)
Evidence
The code explicitly raises on empty scan data and then calls that function during verification
without handling the exception, so an empty attempted scan triggers an unhandled ValueError in the
login flow.

owner_scan_auth.py[14-18]
owner_scan_auth.py[49-60]
owner_scan_auth.py[86-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`create_scan_signature()` raises `ValueError` when the normalized scan is empty, but `verify_owner_scan()` (and the CLI `main()`) do not handle this, causing a crash on login instead of a clean deny.

## Issue Context
This tool is intended to act as a login gate; a malformed/empty scan should deterministically deny access rather than terminate the process with an exception.

## Fix Focus Areas
- owner_scan_auth.py[14-18]
- owner_scan_auth.py[49-60]
- owner_scan_auth.py[86-100]

## Implementation notes
- Wrap `create_scan_signature(attempted_scan_data)` in `verify_owner_scan()` with `try/except ValueError` and return `False` on error.
- Optionally also wrap the CLI login path in `main()` to catch unexpected exceptions and return exit code 1 with an "Access denied" message (without a traceback).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Corrupt DB bricks login 🐞 Bug ☼ Reliability
Description
_load_database() can raise JSONDecodeError/ValueError/OSError on malformed or partially-written
database files, and these exceptions propagate to the CLI. Because _save_database() writes directly
to the target path (non-atomic), an interrupted write can leave a truncated JSON file that then
crashes future logins.
Code

owner_scan_auth.py[R21-36]

+def _load_database(database_path: str | Path) -> dict[str, str]:
+    db_path = Path(database_path)
+    if not db_path.exists():
+        return {}
+    with db_path.open("r", encoding="utf-8") as file:
+        data = json.load(file)
+    if not isinstance(data, dict):
+        raise ValueError("Database must be a JSON object")
+    return {str(account): str(signature) for account, signature in data.items()}
+
+
+def _save_database(database_path: str | Path, database: dict[str, str]) -> None:
+    db_path = Path(database_path)
+    db_path.parent.mkdir(parents=True, exist_ok=True)
+    with db_path.open("w", encoding="utf-8") as file:
+        json.dump(database, file, indent=2)
Evidence
The database read path uses json.load() with no exception handling, and the write path overwrites
the target file directly; this combination makes partial writes likely to produce a JSONDecodeError
on subsequent reads, which will crash the CLI.

owner_scan_auth.py[21-29]
owner_scan_auth.py[32-37]
owner_scan_auth.py[86-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The JSON-backed database is read/written without safety:
- Reads: `json.load()` can throw (corrupt JSON, permissions, etc.) and callers don't handle it.
- Writes: direct `open(..., "w")` is non-atomic and can leave a truncated/corrupt file if interrupted.

This can prevent the tool from making an allow/deny decision (crashes instead).

## Issue Context
Login-gating code should fail closed (deny) and should not permanently brick itself due to partial writes.

## Fix Focus Areas
- owner_scan_auth.py[21-30]
- owner_scan_auth.py[32-37]
- owner_scan_auth.py[86-100]

## Implementation notes
- Implement atomic save:
 - write JSON to a temp file in the same directory (e.g., `owner_scans.json.tmp`)
 - `flush()` + `os.fsync()` (optional but safer)
 - `Path.replace()` to atomically swap.
- Harden load:
 - catch `json.JSONDecodeError` and `OSError`; for login, treat as deny (or treat as empty DB and deny for unknown account).
 - keep a clear error message for enrollment failures (non-zero exit) rather than stack traces.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unsalted fast scan hashes 🐞 Bug ⛨ Security
Description
create_scan_signature() stores SHA-256(normalized_scan) directly, which is a fast unsalted hash and
enables offline guessing if the JSON database is ever read/obtained. This weakens the "secure
signature" claim because attackers can brute-force likely scan inputs and then replay the matching
scan string.
Code

owner_scan_auth.py[R14-18]

+def create_scan_signature(scan_data: str) -> str:
+    normalized = _normalize_scan(scan_data)
+    if not normalized:
+        raise ValueError("Scan data cannot be empty")
+    return hashlib.sha256(normalized.encode("utf-8")).hexdigest()
Evidence
The code computes a plain SHA-256 digest of normalized scan data and stores it in a JSON file,
without any salt or slow hashing, which makes offline guessing feasible if the file is exposed.

owner_scan_auth.py[14-18]
owner_scan_auth.py[39-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The stored owner "signature" is a plain SHA-256 of normalized scan input with no salt/pepper and no KDF. If the on-disk JSON database is exposed (e.g., readable by another local user/process, copied, or committed), attackers can perform rapid offline guessing and then supply the matching scan input.

## Issue Context
This tool persists authentication material to disk (`owner_scans.json` by default). Treat the persisted value like a password-equivalent verifier and store it using a modern, salted, slow KDF.

## Fix Focus Areas
- owner_scan_auth.py[10-18]
- owner_scan_auth.py[39-46]
- owner_scan_auth.py[49-60]

## Implementation notes
- Replace SHA-256 with a slow verifier such as `hashlib.pbkdf2_hmac()` using:
 - per-account random salt (store alongside the digest)
 - sufficiently high iterations
- Store structured records per account (e.g., `{salt, iterations, digest}`) rather than a single hex string.
- Continue using `hmac.compare_digest()` for digest comparison.
- (Optional) document that the database file should be stored with restrictive filesystem permissions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

4. README absolute path reference ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
README documents the tool location using a developer-specific absolute path under /tmp/workspace,
which will not exist for other users/environments. This makes the documented usage misleading.
Code

README.md[50]

+This repository now includes a minimal owner verification tool in `/tmp/workspace/Syko12345/SecretScanTool/owner_scan_auth.py`.
Evidence
The README explicitly points to /tmp/workspace/Syko12345/SecretScanTool/owner_scan_auth.py, which
is not a path that exists in a typical checkout of this repository.

README.md[48-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README references an environment-specific absolute filesystem path for `owner_scan_auth.py`, which breaks the documentation for anyone outside that machine.

## Issue Context
The script is located at the repository root as `owner_scan_auth.py`.

## Fix Focus Areas
- README.md[48-52]

## Implementation notes
- Replace the absolute path with a repo-relative reference (e.g., `owner_scan_auth.py` or `./owner_scan_auth.py`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Copilot AI commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Resolved. I merged origin/main, fixed the README.md conflict, and pushed commit 13352bb.

Comment thread owner_scan_auth.py
Comment thread owner_scan_auth.py

Copilot AI commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

There are no remaining merge conflicts on this PR branch. The conflict resolution was already pushed in commit 13352bb.

@Syko12345 Syko12345 requested a review from Copilot June 4, 2026 21:07
@Syko12345 Syko12345 merged commit e761381 into main Jun 4, 2026
2 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a small Python-based “owner scan” enrollment + verification gate intended to deny logins when a presented scan doesn’t match the enrolled owner signature, with a JSON-backed store and basic unit tests.

Changes:

  • Introduces owner_scan_auth.py CLI and helper functions for enrollment and login verification using normalized, hashed scan signatures.
  • Adds unittest coverage for match/mismatch/unknown-account cases.
  • Updates README.md with quick-start CLI examples.

Reviewed changes

Copilot reviewed 3 out of 5 changed files in this pull request and generated 5 comments.

File Description
owner_scan_auth.py Implements scan normalization, signature hashing, JSON-backed storage, and CLI commands for enroll/login verification.
tests/test_owner_scan_auth.py Adds automated tests for allow/deny behavior based on scan match and account presence.
README.md Documents the new CLI usage for enrollment and login verification.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread owner_scan_auth.py
Comment on lines +59 to +60
attempted_signature = create_scan_signature(attempted_scan_data)
return hmac.compare_digest(expected_signature, attempted_signature)
Comment thread owner_scan_auth.py
Comment on lines +25 to +26
with db_path.open("r", encoding="utf-8") as file:
data = json.load(file)
Comment thread owner_scan_auth.py
Comment on lines +35 to +36
with db_path.open("w", encoding="utf-8") as file:
json.dump(database, file, indent=2)
Comment thread owner_scan_auth.py
Comment on lines +14 to +18
def create_scan_signature(scan_data: str) -> str:
normalized = _normalize_scan(scan_data)
if not normalized:
raise ValueError("Scan data cannot be empty")
return hashlib.sha256(normalized.encode("utf-8")).hexdigest()
Comment thread owner_scan_auth.py
Comment on lines +86 to +100
def main() -> int:
parser = _build_parser()
args = parser.parse_args()

if args.command == "enroll":
enroll_owner_scan(args.account_id, args.scan_data, args.database)
print(f"Owner scan enrolled for account '{args.account_id}'.")
return 0

if verify_owner_scan(args.account_id, args.scan_data, args.database):
print("Access granted.")
return 0

print("Access denied: account owner scan mismatch.")
return 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants