146 lines
4.3 KiB
Python
146 lines
4.3 KiB
Python
"""Tests for act.crypto module."""
|
|
|
|
import pytest
|
|
|
|
from act.crypto import (
|
|
ACTKeyResolver,
|
|
KeyRegistry,
|
|
X509TrustStore,
|
|
b64url_sha256,
|
|
compute_sha256,
|
|
did_key_from_ed25519,
|
|
generate_ed25519_keypair,
|
|
generate_p256_keypair,
|
|
resolve_did_key,
|
|
sign,
|
|
verify,
|
|
)
|
|
from act.errors import ACTKeyResolutionError, ACTSignatureError
|
|
|
|
|
|
class TestEd25519:
|
|
def test_generate_keypair(self):
|
|
priv, pub = generate_ed25519_keypair()
|
|
assert priv is not None
|
|
assert pub is not None
|
|
|
|
def test_sign_verify(self):
|
|
priv, pub = generate_ed25519_keypair()
|
|
data = b"test data"
|
|
sig = sign(priv, data)
|
|
verify(pub, sig, data)
|
|
|
|
def test_verify_wrong_data(self):
|
|
priv, pub = generate_ed25519_keypair()
|
|
sig = sign(priv, b"correct data")
|
|
with pytest.raises(ACTSignatureError):
|
|
verify(pub, sig, b"wrong data")
|
|
|
|
def test_verify_wrong_key(self):
|
|
priv1, pub1 = generate_ed25519_keypair()
|
|
_, pub2 = generate_ed25519_keypair()
|
|
sig = sign(priv1, b"data")
|
|
with pytest.raises(ACTSignatureError):
|
|
verify(pub2, sig, b"data")
|
|
|
|
|
|
class TestP256:
|
|
def test_generate_keypair(self):
|
|
priv, pub = generate_p256_keypair()
|
|
assert priv is not None
|
|
assert pub is not None
|
|
|
|
def test_sign_verify(self):
|
|
priv, pub = generate_p256_keypair()
|
|
data = b"test data for p256"
|
|
sig = sign(priv, data)
|
|
assert len(sig) == 64 # r||s, 32 bytes each
|
|
verify(pub, sig, data)
|
|
|
|
def test_verify_wrong_data(self):
|
|
priv, pub = generate_p256_keypair()
|
|
sig = sign(priv, b"correct")
|
|
with pytest.raises(ACTSignatureError):
|
|
verify(pub, sig, b"wrong")
|
|
|
|
|
|
class TestSHA256:
|
|
def test_compute(self):
|
|
h = compute_sha256(b"hello")
|
|
assert len(h) == 32
|
|
|
|
def test_b64url(self):
|
|
result = b64url_sha256(b"hello world")
|
|
assert "=" not in result
|
|
assert isinstance(result, str)
|
|
|
|
|
|
class TestKeyRegistry:
|
|
def test_register_and_get(self):
|
|
reg = KeyRegistry()
|
|
_, pub = generate_ed25519_keypair()
|
|
reg.register("key-1", pub)
|
|
assert reg.get("key-1") is pub
|
|
assert "key-1" in reg
|
|
assert len(reg) == 1
|
|
|
|
def test_missing_key(self):
|
|
reg = KeyRegistry()
|
|
assert reg.get("missing") is None
|
|
assert "missing" not in reg
|
|
|
|
|
|
class TestDIDKey:
|
|
def test_ed25519_roundtrip(self):
|
|
_, pub = generate_ed25519_keypair()
|
|
did = did_key_from_ed25519(pub)
|
|
assert did.startswith("did:key:z6Mk")
|
|
resolved = resolve_did_key(did)
|
|
# Verify same key by signing/verifying
|
|
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
|
|
original_bytes = pub.public_bytes(Encoding.Raw, PublicFormat.Raw)
|
|
resolved_bytes = resolved.public_bytes(Encoding.Raw, PublicFormat.Raw)
|
|
assert original_bytes == resolved_bytes
|
|
|
|
def test_invalid_prefix(self):
|
|
with pytest.raises(ACTKeyResolutionError):
|
|
resolve_did_key("did:web:example.com")
|
|
|
|
def test_with_fragment(self):
|
|
_, pub = generate_ed25519_keypair()
|
|
did = did_key_from_ed25519(pub)
|
|
did_with_fragment = f"{did}#{did.split(':')[2]}"
|
|
resolved = resolve_did_key(did_with_fragment)
|
|
assert resolved is not None
|
|
|
|
|
|
class TestACTKeyResolver:
|
|
def test_tier1_resolution(self):
|
|
reg = KeyRegistry()
|
|
_, pub = generate_ed25519_keypair()
|
|
reg.register("my-key", pub)
|
|
resolver = ACTKeyResolver(registry=reg)
|
|
assert resolver.resolve("my-key") is pub
|
|
|
|
def test_tier3_did_key(self):
|
|
_, pub = generate_ed25519_keypair()
|
|
did = did_key_from_ed25519(pub)
|
|
resolver = ACTKeyResolver()
|
|
resolved = resolver.resolve(did)
|
|
assert resolved is not None
|
|
|
|
def test_unresolvable(self):
|
|
resolver = ACTKeyResolver()
|
|
with pytest.raises(ACTKeyResolutionError):
|
|
resolver.resolve("unknown-kid")
|
|
|
|
def test_did_web_resolver_callback(self):
|
|
_, pub = generate_ed25519_keypair()
|
|
def resolver_cb(did: str):
|
|
if did == "did:web:example.com":
|
|
return pub
|
|
return None
|
|
resolver = ACTKeyResolver(did_web_resolver=resolver_cb)
|
|
result = resolver.resolve("did:web:example.com")
|
|
assert result is pub
|