Merge pull request #260 from PR0M3TH3AN/beta

Beta
This commit is contained in:
thePR0M3TH3AN
2025-07-04 22:24:39 -04:00
committed by GitHub
8 changed files with 102 additions and 3 deletions

View File

@@ -78,6 +78,7 @@ bash -c "$(curl -sSL https://raw.githubusercontent.com/PR0M3TH3AN/SeedPass/main/
```powershell ```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; $scriptContent = (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/PR0M3TH3AN/SeedPass/main/scripts/install.ps1'); & ([scriptblock]::create($scriptContent)) Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; $scriptContent = (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/PR0M3TH3AN/SeedPass/main/scripts/install.ps1'); & ([scriptblock]::create($scriptContent))
``` ```
The Windows installer will attempt to install Git automatically if it is not already available.
*Install the beta branch:* *Install the beta branch:*
```powershell ```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; $scriptContent = (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/PR0M3TH3AN/SeedPass/main/scripts/install.ps1'); & ([scriptblock]::create($scriptContent)) -Branch beta Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; $scriptContent = (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/PR0M3TH3AN/SeedPass/main/scripts/install.ps1'); & ([scriptblock]::create($scriptContent)) -Branch beta

View File

@@ -32,7 +32,19 @@ function Write-Error {
# 1. Check for prerequisites # 1. Check for prerequisites
Write-Info "Installing SeedPass from branch: '$Branch'" Write-Info "Installing SeedPass from branch: '$Branch'"
Write-Info "Checking for prerequisites..." Write-Info "Checking for prerequisites..."
if (-not (Get-Command git -ErrorAction SilentlyContinue)) { Write-Error "Git is not installed. Please install it from https://git-scm.com/ and ensure it's in your PATH." } if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
Write-Warning "Git is not installed. Attempting to install..."
if (Get-Command winget -ErrorAction SilentlyContinue) {
try { winget install --id Git.Git -e --source winget -h } catch { Write-Error "Failed to install Git via winget. Error: $_" }
} elseif (Get-Command choco -ErrorAction SilentlyContinue) {
try { choco install git -y } catch { Write-Error "Failed to install Git via Chocolatey. Error: $_" }
} elseif (Get-Command scoop -ErrorAction SilentlyContinue) {
try { scoop install git } catch { Write-Error "Failed to install Git via Scoop. Error: $_" }
} else {
Write-Error "Git is not installed. Please install it from https://git-scm.com/ and ensure it's in your PATH."
}
if (-not (Get-Command git -ErrorAction SilentlyContinue)) { Write-Error "Git installation failed or git not found in PATH after installation." }
}
$pythonExe = Get-Command python -ErrorAction SilentlyContinue $pythonExe = Get-Command python -ErrorAction SilentlyContinue
if (-not $pythonExe) { Write-Error "Python 3 is not installed or not in your PATH. Please install it from https://www.python.org/" } if (-not $pythonExe) { Write-Error "Python 3 is not installed or not in your PATH. Please install it from https://www.python.org/" }

View File

@@ -57,7 +57,21 @@ main() {
# 2. Check for prerequisites # 2. Check for prerequisites
print_info "Checking for prerequisites (git, python3, pip)..." print_info "Checking for prerequisites (git, python3, pip)..."
if ! command -v git &> /dev/null; then print_error "Git is not installed. Please install it."; fi if ! command -v git &> /dev/null; then
print_warning "Git is not installed. Attempting to install..."
if [ "$OS_NAME" = "Linux" ]; then
if command -v apt-get &> /dev/null; then sudo apt-get update && sudo apt-get install -y git;
elif command -v dnf &> /dev/null; then sudo dnf install -y git;
elif command -v pacman &> /dev/null; then sudo pacman -Syu --noconfirm git;
else print_error "Git is not installed and automatic installation is not supported on this system."; fi
elif [ "$OS_NAME" = "Darwin" ]; then
if command -v brew &> /dev/null; then brew install git;
else print_error "Git is not installed and Homebrew was not found. Please install Git manually."; fi
else
print_error "Git is not installed. Please install it."
fi
if ! command -v git &> /dev/null; then print_error "Git installation failed or git not found in PATH."; fi
fi
if ! command -v python3 &> /dev/null; then print_error "Python 3 is not installed. Please install it."; fi if ! command -v python3 &> /dev/null; then print_error "Python 3 is not installed. Please install it."; fi
if ! python3 -m ensurepip --default-pip &> /dev/null && ! command -v pip3 &> /dev/null; then print_error "pip for Python 3 is not available. Please install it."; fi if ! python3 -m ensurepip --default-pip &> /dev/null && ! command -v pip3 &> /dev/null; then print_error "pip for Python 3 is not available. Please install it."; fi
if ! python3 -c "import venv" &> /dev/null; then if ! python3 -c "import venv" &> /dev/null; then

View File

@@ -14,6 +14,7 @@ import json
import logging import logging
import getpass import getpass
import os import os
import hashlib
from typing import Optional from typing import Optional
import shutil import shutil
import time import time
@@ -2267,7 +2268,8 @@ class PasswordManager:
# Schema version and checksum status # Schema version and checksum status
stats["schema_version"] = data.get("schema_version") stats["schema_version"] = data.get("schema_version")
current_checksum = json_checksum(data) json_content = json.dumps(data, indent=4)
current_checksum = hashlib.sha256(json_content.encode("utf-8")).hexdigest()
chk_path = self.entry_manager.checksum_file chk_path = self.entry_manager.checksum_file
if chk_path.exists(): if chk_path.exists():
stored = chk_path.read_text().strip() stored = chk_path.read_text().strip()

View File

@@ -4,6 +4,8 @@ from tempfile import TemporaryDirectory
from helpers import create_vault, TEST_SEED, TEST_PASSWORD from helpers import create_vault, TEST_SEED, TEST_PASSWORD
from nostr.coincurve_keys import Keys
sys.path.append(str(Path(__file__).resolve().parents[1])) sys.path.append(str(Path(__file__).resolve().parents[1]))
from password_manager.entry_management import EntryManager from password_manager.entry_management import EntryManager
@@ -36,3 +38,11 @@ def test_nostr_key_determinism():
assert nsec1 == nsec2 assert nsec1 == nsec2
assert npub1.startswith("npub") assert npub1.startswith("npub")
assert nsec1.startswith("nsec") assert nsec1.startswith("nsec")
priv_hex = Keys.bech32_to_hex(nsec1)
derived = Keys(priv_k=priv_hex)
encoded_npub = Keys.hex_to_bech32(derived.public_key_hex(), "npub")
assert encoded_npub == npub1
data = enc_mgr.load_json_data(entry_mgr.index_file)
assert data["entries"][str(idx)]["label"] == "main"

View File

@@ -25,3 +25,15 @@ def test_pgp_key_determinism():
assert fp1 == fp2 assert fp1 == fp2
assert key1 == key2 assert key1 == key2
# parse returned armored key and verify fingerprint
from pgpy import PGPKey
parsed_key, _ = PGPKey.from_blob(key1)
assert parsed_key.fingerprint == fp1
# ensure the index file stores key_type and user_id
data = enc_mgr.load_json_data(entry_mgr.index_file)
entry = data["entries"][str(idx)]
assert entry["key_type"] == "ed25519"
assert entry["user_id"] == "Test"

View File

@@ -3,6 +3,7 @@ from pathlib import Path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from helpers import create_vault, TEST_SEED, TEST_PASSWORD from helpers import create_vault, TEST_SEED, TEST_PASSWORD
from mnemonic import Mnemonic
sys.path.append(str(Path(__file__).resolve().parents[1])) sys.path.append(str(Path(__file__).resolve().parents[1]))
@@ -30,6 +31,9 @@ def test_seed_phrase_determinism():
phrase24_a = entry_mgr.get_seed_phrase(idx_24, TEST_SEED) phrase24_a = entry_mgr.get_seed_phrase(idx_24, TEST_SEED)
phrase24_b = entry_mgr.get_seed_phrase(idx_24, TEST_SEED) phrase24_b = entry_mgr.get_seed_phrase(idx_24, TEST_SEED)
entry12 = entry_mgr.retrieve_entry(idx_12)
entry24 = entry_mgr.retrieve_entry(idx_24)
seed_bytes = Bip39SeedGenerator(TEST_SEED).Generate() seed_bytes = Bip39SeedGenerator(TEST_SEED).Generate()
bip85 = BIP85(seed_bytes) bip85 = BIP85(seed_bytes)
expected12 = derive_seed_phrase(bip85, idx_12, 12) expected12 = derive_seed_phrase(bip85, idx_12, 12)
@@ -39,3 +43,7 @@ def test_seed_phrase_determinism():
assert phrase24_a == phrase24_b == expected24 assert phrase24_a == phrase24_b == expected24
assert len(phrase12_a.split()) == 12 assert len(phrase12_a.split()) == 12
assert len(phrase24_a.split()) == 24 assert len(phrase24_a.split()) == 24
assert Mnemonic("english").check(phrase12_a)
assert Mnemonic("english").check(phrase24_a)
assert entry12.get("words") == 12
assert entry24.get("words") == 24

View File

@@ -0,0 +1,40 @@
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
sys.path.append(str(Path(__file__).resolve().parents[1]))
from password_manager.entry_management import EntryManager
from password_manager.backup import BackupManager
from password_manager.vault import Vault
from password_manager.config_manager import ConfigManager
from cryptography.hazmat.primitives import serialization
def test_ssh_private_key_corresponds_to_public():
with TemporaryDirectory() as tmpdir:
tmp_path = Path(tmpdir)
vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
entry_mgr = EntryManager(vault, backup_mgr)
idx = entry_mgr.add_ssh_key(TEST_SEED)
priv_pem, pub_pem = entry_mgr.get_ssh_key_pair(idx, TEST_SEED)
priv_key = serialization.load_pem_private_key(
priv_pem.encode(),
password=None,
)
derived_pub_pem = (
priv_key.public_key()
.public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo,
)
.decode()
)
assert derived_pub_pem == pub_pem