fix: unify PIN hashing across CLI, FSM, and web (closes #2) #7

Merged
alee merged 16 commits from fix/issue-2-pin-unification into main 2026-04-05 16:59:51 +00:00
2 changed files with 9 additions and 12 deletions
Showing only changes of commit efa3ce4b1b - Show all commits

View File

@@ -1,6 +1,5 @@
"""Tests for the Phase 6 events subsystem: rules, arm state FSM, history."""
import hashlib
import time
import pytest
@@ -19,7 +18,7 @@ from vigilar.storage.queries import insert_event
def _make_config(rules=None, pin_hash=""):
return VigilarConfig(
system={"arm_pin_hash": pin_hash},
security={"pin_hash": pin_hash},
cameras=[],
sensors=[],
rules=rules or [],
@@ -27,7 +26,8 @@ def _make_config(rules=None, pin_hash=""):
def _pin_hash(pin: str) -> str:
return hashlib.sha256(pin.encode()).hexdigest()
from vigilar.alerts.pin import hash_pin
return hash_pin(pin)
# ---------------------------------------------------------------------------

View File

@@ -1,12 +1,11 @@
"""Arm state finite state machine."""
import hashlib
import hmac
import logging
import time
from sqlalchemy.engine import Engine
from vigilar.alerts.pin import verify_pin as _verify_pin_hash
from vigilar.config import VigilarConfig
from vigilar.constants import ArmState, EventType, Severity, Topics
from vigilar.storage.queries import get_current_arm_state, insert_arm_state, insert_event
@@ -19,7 +18,7 @@ class ArmStateFSM:
def __init__(self, engine: Engine, config: VigilarConfig):
self._engine = engine
self._pin_hash = config.system.arm_pin_hash
self._pin_hash = config.security.pin_hash
self._state = ArmState.DISARMED
self._bus = None
self._load_initial_state()
@@ -43,12 +42,11 @@ class ArmStateFSM:
return self._state
def verify_pin(self, pin: str) -> bool:
"""Verify a PIN against the stored hash using HMAC comparison."""
"""Verify a PIN against the stored PBKDF2 hash."""
if not self._pin_hash:
# No PIN configured — allow all transitions
return True
candidate = hashlib.sha256(pin.encode()).hexdigest()
return hmac.compare_digest(candidate, self._pin_hash)
return _verify_pin_hash(pin, self._pin_hash)
def transition(
self,
@@ -68,9 +66,8 @@ class ArmStateFSM:
old_state = self._state
self._state = new_state
# Log to database
pin_hash = hashlib.sha256(pin.encode()).hexdigest() if pin else None
insert_arm_state(self._engine, new_state.value, triggered_by, pin_hash)
# Log to database (pin_hash column is no longer populated — see #2)
insert_arm_state(self._engine, new_state.value, triggered_by, None)
# Log event
insert_event(