Skip to content

Commit ffa2f56

Browse files
MHHukiewitzPsycojokerhoh
committed
feat: add aleph.sdk.security module
Co-authored-by: Laurent Peuch <[email protected]> Co-authored-by: Hugo Herter <[email protected]>
1 parent 9c5ec6e commit ffa2f56

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/aleph/sdk/security.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from importlib import import_module
2+
from typing import Callable, Dict, Optional, Union
3+
4+
from aleph_message.models import AlephMessage, Chain
5+
6+
from aleph.sdk.chains.common import get_verification_buffer
7+
from aleph.sdk.query.responses import Post
8+
9+
10+
def _try_import_verify_signature(
11+
chain: str,
12+
) -> Optional[
13+
Callable[[Union[bytes, str], Union[bytes, str], Union[bytes, str]], None]
14+
]:
15+
"""Try to import a chain signature validator."""
16+
try:
17+
return import_module(f"aleph.sdk.chains.{chain}").verify_signature
18+
except (ImportError, AttributeError):
19+
return None
20+
21+
22+
# This is a dict containing all currently available signature validators,
23+
# indexed by their Chain abbreviation.
24+
#
25+
# Ex.: validators["SOL"] -> aleph.sdk.chains.solana.verify_signature()
26+
VALIDATORS: Dict[
27+
Chain,
28+
Optional[Callable[[Union[bytes, str], Union[bytes, str], Union[bytes, str]], None]],
29+
] = {
30+
key: _try_import_verify_signature(value)
31+
for key, value in {
32+
# TODO: Add AVAX
33+
Chain.ETH: "ethereum",
34+
Chain.SOL: "sol",
35+
Chain.CSDK: "cosmos",
36+
Chain.DOT: "substrate",
37+
Chain.NULS2: "nuls2",
38+
Chain.TEZOS: "tezos",
39+
}.items()
40+
}
41+
42+
43+
def verify_message_signature(message: Union[AlephMessage, Post]) -> None:
44+
"""Verify the signature of a message, raise an error if invalid or unsupported.
45+
A BadSignatureError is raised when the signature is incorrect.
46+
A ValueError is raised when the chain is not supported or required dependencies are missing.
47+
"""
48+
if message.chain not in VALIDATORS:
49+
raise ValueError(f"Chain {message.chain} is not supported.")
50+
51+
validator = VALIDATORS[message.chain]
52+
if validator is None:
53+
raise ValueError(
54+
f"Chain {message.chain} is not installed. Install it with `aleph-sdk-python[{message.chain}]`."
55+
)
56+
57+
signature = message.signature
58+
public_key = message.sender
59+
message = get_verification_buffer(message.dict())
60+
61+
# to please mypy
62+
assert isinstance(signature, (str, bytes))
63+
64+
validator(signature, public_key, message)

tests/unit/test_security.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
def test_validators_loaded():
2+
import aleph.sdk.security as security
3+
4+
assert any([validator is not None for validator in security.validators.values()])

0 commit comments

Comments
 (0)