ciris-verify 7.2.0__tar.gz → 7.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/PKG-INFO +1 -1
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/__init__.py +3 -1
- ciris_verify-7.3.0/ciris_verify/_rns_dest_hash.py +150 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/PKG-INFO +1 -1
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/SOURCES.txt +1 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/pyproject.toml +1 -1
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/README.md +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_accord_custody.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_bin_sign.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_bin_verify.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_federation_identity.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_jcs.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_manifest_contribution.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_operational_admit.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_wheel_hybrid_kex.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_wheel_key_grant.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_wheel_locale_merkle.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_wheel_reconsider_dos.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/_wheel_skill_import.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/client.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/exceptions.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/py.typed +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify/types.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/dependency_links.txt +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/entry_points.txt +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/requires.txt +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/ciris_verify.egg-info/top_level.txt +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/setup.cfg +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/tests/test_client.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/tests/test_memory_baseline.py +0 -0
- {ciris_verify-7.2.0 → ciris_verify-7.3.0}/tests/test_types.py +0 -0
|
@@ -30,6 +30,7 @@ import logging as _logging
|
|
|
30
30
|
|
|
31
31
|
from .client import CIRISVerify, MockCIRISVerify, verify_tree, DEFAULT_REGISTRY_URL
|
|
32
32
|
from ._jcs import jcs_canonicalize
|
|
33
|
+
from ._rns_dest_hash import rns_destination_hash
|
|
33
34
|
from ._federation_identity import create_federation_identity
|
|
34
35
|
from ._manifest_contribution import verify_build_manifest_contribution
|
|
35
36
|
from ._accord_custody import verify_accord_custody_attestation
|
|
@@ -127,12 +128,13 @@ def get_library_version() -> str:
|
|
|
127
128
|
return __version__
|
|
128
129
|
|
|
129
130
|
|
|
130
|
-
__version__ = "7.
|
|
131
|
+
__version__ = "7.3.0"
|
|
131
132
|
__all__ = [
|
|
132
133
|
"CIRISVerify",
|
|
133
134
|
"MockCIRISVerify",
|
|
134
135
|
"verify_tree",
|
|
135
136
|
"jcs_canonicalize",
|
|
137
|
+
"rns_destination_hash",
|
|
136
138
|
"create_federation_identity",
|
|
137
139
|
"verify_build_manifest_contribution",
|
|
138
140
|
"verify_accord_custody_attestation",
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""RNS ``destination_hash`` recompute — Python binding (CIRISVerify#28).
|
|
2
|
+
|
|
3
|
+
Exposes :func:`rns_destination_hash`, a thin wrapper over the FFI symbol
|
|
4
|
+
``ciris_verify_rns_destination_hash`` which calls
|
|
5
|
+
``ciris_verify_core::transport_binding::compute_destination_hash`` — the one
|
|
6
|
+
blessed two-stage RNS destination-hash construction (CEG 1.0-RC6 §5.6.8.8.1.1).
|
|
7
|
+
|
|
8
|
+
This lifts the last verify-side remainder of the #28 transport-binding
|
|
9
|
+
waterfall: the recompute shipped Rust-side in v5.6.0 (``DestinationHashCheck``
|
|
10
|
+
lifted off ``Unsupported``) but was never on the wheel, so a Python consumer —
|
|
11
|
+
and CIRISConformance's ``test_150_rns_dest_hash.py`` cross-check — could not
|
|
12
|
+
verify a peer's ``destination_hash`` against the pinned algorithm. With this it
|
|
13
|
+
can, byte-for-byte, with **no** Reticulum vendoring and no second
|
|
14
|
+
implementation: the canonical bytes come from the same Rust path the verifiers
|
|
15
|
+
use.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import ctypes
|
|
21
|
+
import json as _json
|
|
22
|
+
import platform as _platform
|
|
23
|
+
import threading as _threading
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Optional, Sequence
|
|
26
|
+
|
|
27
|
+
__all__ = ["rns_destination_hash"]
|
|
28
|
+
|
|
29
|
+
_lib: Optional[ctypes.CDLL] = None
|
|
30
|
+
_lib_lock = _threading.Lock()
|
|
31
|
+
_SUCCESS = 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _candidate_paths() -> list[str]:
|
|
35
|
+
here = Path(__file__).resolve().parent
|
|
36
|
+
system = _platform.system()
|
|
37
|
+
names = {
|
|
38
|
+
"Linux": ["libciris_verify_ffi.so", "libciris_verify.so"],
|
|
39
|
+
"Darwin": ["libciris_verify_ffi.dylib", "libciris_verify.dylib"],
|
|
40
|
+
"Windows": ["ciris_verify_ffi.dll", "ciris_verify.dll"],
|
|
41
|
+
}.get(system, ["libciris_verify_ffi.so"])
|
|
42
|
+
|
|
43
|
+
paths: list[str] = []
|
|
44
|
+
for n in names:
|
|
45
|
+
paths.append(str(here / n))
|
|
46
|
+
try:
|
|
47
|
+
from .client import DEFAULT_BINARY_PATHS # type: ignore
|
|
48
|
+
|
|
49
|
+
paths.extend(DEFAULT_BINARY_PATHS.get(system, []))
|
|
50
|
+
except Exception: # pragma: no cover - defensive
|
|
51
|
+
pass
|
|
52
|
+
return paths
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_lib() -> ctypes.CDLL:
|
|
56
|
+
global _lib
|
|
57
|
+
if _lib is not None:
|
|
58
|
+
return _lib
|
|
59
|
+
with _lib_lock:
|
|
60
|
+
if _lib is not None:
|
|
61
|
+
return _lib
|
|
62
|
+
last_err: Optional[Exception] = None
|
|
63
|
+
for path in _candidate_paths():
|
|
64
|
+
if not Path(path).exists():
|
|
65
|
+
continue
|
|
66
|
+
try:
|
|
67
|
+
lib = ctypes.CDLL(path)
|
|
68
|
+
fn = lib.ciris_verify_rns_destination_hash
|
|
69
|
+
except (OSError, AttributeError) as exc:
|
|
70
|
+
last_err = exc
|
|
71
|
+
continue
|
|
72
|
+
fn.argtypes = [
|
|
73
|
+
ctypes.c_char_p, # input_json (UTF-8 bytes)
|
|
74
|
+
ctypes.c_size_t, # input_len
|
|
75
|
+
ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)), # result_out
|
|
76
|
+
ctypes.POINTER(ctypes.c_size_t), # result_len_out
|
|
77
|
+
]
|
|
78
|
+
fn.restype = ctypes.c_int
|
|
79
|
+
lib.ciris_verify_free.argtypes = [ctypes.c_void_p]
|
|
80
|
+
lib.ciris_verify_free.restype = None
|
|
81
|
+
_lib = lib
|
|
82
|
+
return _lib
|
|
83
|
+
raise RuntimeError(
|
|
84
|
+
"ciris_verify_rns_destination_hash not available — could not load "
|
|
85
|
+
f"the CIRISVerify shared library (last error: {last_err}). "
|
|
86
|
+
"The library must be built with the wheel (>= v7.3.0)."
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def rns_destination_hash(
|
|
91
|
+
app_name: str,
|
|
92
|
+
aspects: Sequence[str],
|
|
93
|
+
x25519_pub: bytes,
|
|
94
|
+
ed25519_pub: bytes,
|
|
95
|
+
) -> bytes:
|
|
96
|
+
"""Recompute the RNS ``destination_hash`` per CEG §5.6.8.8.1.1.
|
|
97
|
+
|
|
98
|
+
The two-stage construction (NOT a flat single SHA-256):
|
|
99
|
+
|
|
100
|
+
name_hash = SHA256(app_name + "." + ".".join(aspects))[:10]
|
|
101
|
+
identity_hash = SHA256(x25519_pub ‖ ed25519_pub)[:16]
|
|
102
|
+
destination_hash = SHA256(name_hash ‖ identity_hash)[:16]
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
app_name: the RNS app name (e.g. ``"ciris.federation"``).
|
|
106
|
+
aspects: the dot-joined aspects (each MUST NOT contain ``"."``).
|
|
107
|
+
x25519_pub: the peer's X25519 public key bytes.
|
|
108
|
+
ed25519_pub: the peer's Ed25519 public key bytes (key order is
|
|
109
|
+
x25519 THEN ed25519, per RNS ``get_public_key``).
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
The 16-byte destination hash — byte-identical to
|
|
113
|
+
``ciris_verify_core::transport_binding::compute_destination_hash`` and
|
|
114
|
+
therefore to the pinned §5.6.8.8.1.1 algorithm.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValueError: an aspect contains ``"."`` (illegal — it would alter the
|
|
118
|
+
name preimage split), or the inputs cannot be encoded.
|
|
119
|
+
RuntimeError: the shared library / FFI symbol is unavailable.
|
|
120
|
+
"""
|
|
121
|
+
req = {
|
|
122
|
+
"app_name": app_name,
|
|
123
|
+
"aspects": list(aspects),
|
|
124
|
+
"x25519_pubkey": list(x25519_pub),
|
|
125
|
+
"ed25519_pubkey": list(ed25519_pub),
|
|
126
|
+
}
|
|
127
|
+
input_bytes = _json.dumps(req).encode("utf-8")
|
|
128
|
+
|
|
129
|
+
lib = _load_lib()
|
|
130
|
+
out_ptr = ctypes.POINTER(ctypes.c_ubyte)()
|
|
131
|
+
out_len = ctypes.c_size_t(0)
|
|
132
|
+
rc = lib.ciris_verify_rns_destination_hash(
|
|
133
|
+
input_bytes,
|
|
134
|
+
len(input_bytes),
|
|
135
|
+
ctypes.byref(out_ptr),
|
|
136
|
+
ctypes.byref(out_len),
|
|
137
|
+
)
|
|
138
|
+
if rc != _SUCCESS:
|
|
139
|
+
# rc 2 == SerializationError (bad request / dotted aspect).
|
|
140
|
+
raise ValueError(
|
|
141
|
+
f"rns_destination_hash: invalid request (e.g. an aspect containing "
|
|
142
|
+
f"'.', or non-encodable input) (FFI code {rc})"
|
|
143
|
+
)
|
|
144
|
+
n = out_len.value
|
|
145
|
+
try:
|
|
146
|
+
result = ctypes.string_at(out_ptr, n)
|
|
147
|
+
finally:
|
|
148
|
+
if n != 0:
|
|
149
|
+
lib.ciris_verify_free(ctypes.cast(out_ptr, ctypes.c_void_p))
|
|
150
|
+
return result
|
|
@@ -8,6 +8,7 @@ ciris_verify/_federation_identity.py
|
|
|
8
8
|
ciris_verify/_jcs.py
|
|
9
9
|
ciris_verify/_manifest_contribution.py
|
|
10
10
|
ciris_verify/_operational_admit.py
|
|
11
|
+
ciris_verify/_rns_dest_hash.py
|
|
11
12
|
ciris_verify/_wheel_hybrid_kex.py
|
|
12
13
|
ciris_verify/_wheel_key_grant.py
|
|
13
14
|
ciris_verify/_wheel_locale_merkle.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|