Harden M9: Ed25519 attestation, full SHA-256 integrity, locked-by-default, prompt improvements, registry verification
This commit is contained in:
+41
-15
@@ -2,44 +2,70 @@
|
||||
|
||||
from cmdforge.attestation import (
|
||||
Attestation,
|
||||
generate_keypair,
|
||||
sign_tool,
|
||||
verify_attestation,
|
||||
verify_content_hash,
|
||||
verify_trusted_attestation,
|
||||
)
|
||||
from cmdforge.tool import Tool
|
||||
|
||||
|
||||
class TestSignTool:
|
||||
def test_creates_attestation(self):
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", "secret-key")
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", private)
|
||||
assert att.tool_name == "mytool"
|
||||
assert att.version == "1.0.0"
|
||||
assert att.content_hash == "abc123"
|
||||
assert att.signer == "alice"
|
||||
assert len(att.signature) == 64 # SHA256 hex
|
||||
assert att.algorithm == "hmac-sha256"
|
||||
assert len(att.signature) == 88
|
||||
assert att.algorithm == "ed25519"
|
||||
assert verify_attestation(att, public)
|
||||
|
||||
def test_different_keys_different_signatures(self):
|
||||
att1 = sign_tool("tool", "1.0.0", "hash", "alice", "key1")
|
||||
att2 = sign_tool("tool", "1.0.0", "hash", "alice", "key2")
|
||||
key1, _ = generate_keypair()
|
||||
key2, _ = generate_keypair()
|
||||
att1 = sign_tool("tool", "1.0.0", "hash", "alice", key1)
|
||||
att2 = sign_tool("tool", "1.0.0", "hash", "alice", key2)
|
||||
assert att1.signature != att2.signature
|
||||
|
||||
|
||||
class TestVerifyAttestation:
|
||||
def test_valid_signature(self):
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", "secret-key")
|
||||
assert verify_attestation(att, "secret-key")
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", private)
|
||||
assert verify_attestation(att, public)
|
||||
|
||||
def test_wrong_key_fails(self):
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", "secret-key")
|
||||
assert not verify_attestation(att, "wrong-key")
|
||||
private, _ = generate_keypair()
|
||||
_, wrong_public = generate_keypair()
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", private)
|
||||
assert not verify_attestation(att, wrong_public)
|
||||
|
||||
def test_tampered_content_fails(self):
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", "secret-key")
|
||||
att.content_hash = "tampered"
|
||||
assert not verify_attestation(att, "secret-key")
|
||||
from dataclasses import replace
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", private)
|
||||
att = replace(att, content_hash="tampered")
|
||||
assert not verify_attestation(att, public)
|
||||
|
||||
def test_tampered_signer_fails(self):
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", "secret-key")
|
||||
att.signer = "eve"
|
||||
assert not verify_attestation(att, "secret-key")
|
||||
from dataclasses import replace
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("mytool", "1.0.0", "abc123", "alice", private)
|
||||
att = replace(att, signer="eve")
|
||||
assert not verify_attestation(att, public)
|
||||
|
||||
def test_timestamp_and_algorithm_are_signed(self):
|
||||
from dataclasses import replace
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("tool", "1.0.0", "hash", "alice", private)
|
||||
assert not verify_attestation(replace(att, signed_at="tomorrow"), public)
|
||||
assert not verify_attestation(replace(att, algorithm="hmac-sha256"), public)
|
||||
|
||||
def test_requires_trusted_publisher_mapping(self):
|
||||
private, public = generate_keypair()
|
||||
att = sign_tool("tool", "1.0.0", "hash", "alice", private)
|
||||
assert verify_trusted_attestation(att, {"alice": public})
|
||||
assert not verify_trusted_attestation(att, {"mallory": public})
|
||||
|
||||
Reference in New Issue
Block a user