governed-agent 0.1.3__py3-none-any.whl
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.
- governed_agent/__init__.py +72 -0
- governed_agent/audit/__init__.py +5 -0
- governed_agent/audit/watchtower.py +361 -0
- governed_agent/capability/__init__.py +57 -0
- governed_agent/capability/antirollback.py +390 -0
- governed_agent/capability/crypto.py +443 -0
- governed_agent/hermes/__init__.py +5 -0
- governed_agent/hermes/boundary.py +93 -0
- governed_agent/planning/__init__.py +21 -0
- governed_agent/planning/blink.py +273 -0
- governed_agent-0.1.3.dist-info/METADATA +242 -0
- governed_agent-0.1.3.dist-info/RECORD +15 -0
- governed_agent-0.1.3.dist-info/WHEEL +5 -0
- governed_agent-0.1.3.dist-info/licenses/LICENSE +21 -0
- governed_agent-0.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Governed Agent — capability sealing, scope-bounded planning, independent audit, and runtime tool boundaries."""
|
|
2
|
+
|
|
3
|
+
from .capability import (
|
|
4
|
+
KeyPair,
|
|
5
|
+
SealResult,
|
|
6
|
+
VerifyResult,
|
|
7
|
+
generate_keypair,
|
|
8
|
+
seal,
|
|
9
|
+
verify,
|
|
10
|
+
quick_seal,
|
|
11
|
+
quick_verify,
|
|
12
|
+
FileKeyStore,
|
|
13
|
+
create_keystore,
|
|
14
|
+
Pin,
|
|
15
|
+
Checkpoint,
|
|
16
|
+
FileBackedAuthority,
|
|
17
|
+
InMemoryAuthority,
|
|
18
|
+
create_antirollback_authority,
|
|
19
|
+
create_checkpoint,
|
|
20
|
+
)
|
|
21
|
+
from .planning import (
|
|
22
|
+
validate,
|
|
23
|
+
render_brief,
|
|
24
|
+
create_handoff,
|
|
25
|
+
ALLOWED_ACTIONS,
|
|
26
|
+
HIGH_RISK_ACTIONS,
|
|
27
|
+
REQUIRED_PROHIBITIONS,
|
|
28
|
+
enabled,
|
|
29
|
+
)
|
|
30
|
+
from .audit import (
|
|
31
|
+
WatchTower,
|
|
32
|
+
WatchTowerVerdict,
|
|
33
|
+
)
|
|
34
|
+
from .hermes import GovernedToolBoundary, ExecutionDeniedError
|
|
35
|
+
|
|
36
|
+
__version__ = "0.1.2"
|
|
37
|
+
__author__ = "jtevesnz-sys"
|
|
38
|
+
__license__ = "MIT"
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
# Capability Layer
|
|
42
|
+
"KeyPair",
|
|
43
|
+
"SealResult",
|
|
44
|
+
"VerifyResult",
|
|
45
|
+
"generate_keypair",
|
|
46
|
+
"seal",
|
|
47
|
+
"verify",
|
|
48
|
+
"quick_seal",
|
|
49
|
+
"quick_verify",
|
|
50
|
+
"FileKeyStore",
|
|
51
|
+
"create_keystore",
|
|
52
|
+
"Pin",
|
|
53
|
+
"Checkpoint",
|
|
54
|
+
"FileBackedAuthority",
|
|
55
|
+
"InMemoryAuthority",
|
|
56
|
+
"create_antirollback_authority",
|
|
57
|
+
"create_checkpoint",
|
|
58
|
+
# Planning Layer
|
|
59
|
+
"validate",
|
|
60
|
+
"render_brief",
|
|
61
|
+
"create_handoff",
|
|
62
|
+
"ALLOWED_ACTIONS",
|
|
63
|
+
"HIGH_RISK_ACTIONS",
|
|
64
|
+
"REQUIRED_PROHIBITIONS",
|
|
65
|
+
"enabled",
|
|
66
|
+
# Audit Layer
|
|
67
|
+
"WatchTower",
|
|
68
|
+
"WatchTowerVerdict",
|
|
69
|
+
# Hermes Tool Boundary
|
|
70
|
+
"GovernedToolBoundary",
|
|
71
|
+
"ExecutionDeniedError",
|
|
72
|
+
]
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Governed Agent — Independent Verifier (Watchtower Audit Engine)
|
|
4
|
+
Performs out-of-band 6-point verification over build outputs and manifests.
|
|
5
|
+
Prevents models from self-certifying their work.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class WatchTowerVerdict(Enum):
|
|
18
|
+
"""Independent audit verdicts."""
|
|
19
|
+
|
|
20
|
+
PASS = "PASS"
|
|
21
|
+
HOLD = "HOLD"
|
|
22
|
+
REVISE = "REVISE"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class WatchTower:
|
|
26
|
+
"""Out-of-band auditor validating artifacts against manifests and contracts."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, root_dir: Union[str, Path, None] = None):
|
|
29
|
+
self.root_dir = Path(root_dir) if root_dir else None
|
|
30
|
+
|
|
31
|
+
def verify(
|
|
32
|
+
self,
|
|
33
|
+
manifest: Union[Dict[str, Any], Path, str],
|
|
34
|
+
dep_graph: Optional[Dict[str, Any]] = None,
|
|
35
|
+
lane_contracts: Optional[List[Dict[str, Any]]] = None,
|
|
36
|
+
root_dir: Union[str, Path, None] = None,
|
|
37
|
+
) -> Dict[str, Any]:
|
|
38
|
+
"""
|
|
39
|
+
Execute 6-point independent audit:
|
|
40
|
+
1. Manifest validation
|
|
41
|
+
2. Required lanes present
|
|
42
|
+
3. No unlisted files
|
|
43
|
+
4. Hash agreement
|
|
44
|
+
5. Cross-lane independence check
|
|
45
|
+
6. Prohibited residue detection
|
|
46
|
+
"""
|
|
47
|
+
dep_graph = dep_graph or {}
|
|
48
|
+
lane_contracts = lane_contracts or []
|
|
49
|
+
effective_root = Path(root_dir) if root_dir else self.root_dir
|
|
50
|
+
|
|
51
|
+
if isinstance(manifest, (Path, str)):
|
|
52
|
+
manifest_path = Path(manifest)
|
|
53
|
+
manifest_dict = self._load_json(manifest_path)
|
|
54
|
+
if effective_root is None:
|
|
55
|
+
effective_root = manifest_path.parent
|
|
56
|
+
else:
|
|
57
|
+
manifest_dict = manifest
|
|
58
|
+
|
|
59
|
+
checks: List[Dict[str, Any]] = []
|
|
60
|
+
independence_violations: List[str] = []
|
|
61
|
+
|
|
62
|
+
# 1. Manifest structure validation
|
|
63
|
+
checks.append(self._check_manifest_valid(manifest_dict))
|
|
64
|
+
|
|
65
|
+
# Complete set hash check if present and valid
|
|
66
|
+
checks.append(self._check_complete_set_hash(manifest_dict))
|
|
67
|
+
|
|
68
|
+
# 2. Required lanes present
|
|
69
|
+
checks.append(self._check_lanes_present(manifest_dict, dep_graph))
|
|
70
|
+
|
|
71
|
+
# 3. No unlisted files
|
|
72
|
+
checks.append(self._check_no_unlisted_files(manifest_dict, effective_root))
|
|
73
|
+
|
|
74
|
+
# 4. Hash agreement
|
|
75
|
+
checks.append(self._check_hashes(manifest_dict, effective_root))
|
|
76
|
+
|
|
77
|
+
# 5. Independence check
|
|
78
|
+
ind_check, violations = self._check_independence(manifest_dict, lane_contracts)
|
|
79
|
+
checks.append(ind_check)
|
|
80
|
+
independence_violations.extend(violations)
|
|
81
|
+
|
|
82
|
+
# 6. No residue
|
|
83
|
+
residue_check, residue_found = self._check_residue(manifest_dict)
|
|
84
|
+
checks.append(residue_check)
|
|
85
|
+
|
|
86
|
+
# Determine verdict
|
|
87
|
+
verdict = self._determine_verdict(checks, independence_violations, residue_found)
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
"verdict": verdict.value,
|
|
91
|
+
"checks": checks,
|
|
92
|
+
"independence_violations": independence_violations,
|
|
93
|
+
"prohibited_residue_found": residue_found,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
def _load_json(self, path: Path) -> Dict[str, Any]:
|
|
97
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
98
|
+
return json.load(f)
|
|
99
|
+
|
|
100
|
+
def _check_complete_set_hash(self, manifest: Dict[str, Any]) -> Dict[str, Any]:
|
|
101
|
+
complete_set_sha = manifest.get("complete_set_sha256")
|
|
102
|
+
if not complete_set_sha or not isinstance(complete_set_sha, str) or len(complete_set_sha) != 64:
|
|
103
|
+
return {
|
|
104
|
+
"name": "complete_set_sha256",
|
|
105
|
+
"status": "FAIL",
|
|
106
|
+
"details": "Invalid complete_set_sha256 in manifest",
|
|
107
|
+
}
|
|
108
|
+
files = manifest.get("files", [])
|
|
109
|
+
if not isinstance(files, list):
|
|
110
|
+
return {
|
|
111
|
+
"name": "complete_set_sha256",
|
|
112
|
+
"status": "FAIL",
|
|
113
|
+
"details": "'files' must be a list",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
# Deterministic canonical serialization of file entries
|
|
118
|
+
normalized = []
|
|
119
|
+
for f in files:
|
|
120
|
+
rel = f.get("relative_path", "").replace("\\", "/")
|
|
121
|
+
entry: Dict[str, Any] = {
|
|
122
|
+
"lane_id": f.get("lane_id", ""),
|
|
123
|
+
"relative_path": rel,
|
|
124
|
+
"sha256": f.get("sha256", ""),
|
|
125
|
+
}
|
|
126
|
+
if "size_bytes" in f:
|
|
127
|
+
entry["size_bytes"] = f["size_bytes"]
|
|
128
|
+
normalized.append(entry)
|
|
129
|
+
|
|
130
|
+
normalized.sort(key=lambda x: x["relative_path"])
|
|
131
|
+
canonical = json.dumps(normalized, separators=(",", ":"), sort_keys=True).encode("utf-8")
|
|
132
|
+
recomputed = hashlib.sha256(canonical).hexdigest()
|
|
133
|
+
|
|
134
|
+
if recomputed.lower() != complete_set_sha.lower():
|
|
135
|
+
return {
|
|
136
|
+
"name": "complete_set_sha256",
|
|
137
|
+
"status": "FAIL",
|
|
138
|
+
"details": f"complete_set_sha256 mismatch: expected {complete_set_sha}, computed {recomputed}",
|
|
139
|
+
}
|
|
140
|
+
except Exception as exc:
|
|
141
|
+
return {
|
|
142
|
+
"name": "complete_set_sha256",
|
|
143
|
+
"status": "FAIL",
|
|
144
|
+
"details": f"Error computing complete_set_sha256: {exc}",
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
"name": "complete_set_sha256",
|
|
149
|
+
"status": "PASS",
|
|
150
|
+
"details": "complete_set_sha256 verified",
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
def _check_manifest_valid(self, manifest: Dict[str, Any]) -> Dict[str, Any]:
|
|
154
|
+
required = ["format", "format_version", "convergence_id", "complete_set_sha256", "files", "lane_records"]
|
|
155
|
+
missing = [f for f in required if f not in manifest]
|
|
156
|
+
status = "PASS" if not missing else "FAIL"
|
|
157
|
+
return {
|
|
158
|
+
"name": "manifest_validation",
|
|
159
|
+
"status": status,
|
|
160
|
+
"details": f"Missing: {missing}" if missing else "All required manifest fields present",
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
def _check_lanes_present(self, manifest: Dict[str, Any], dep_graph: Dict[str, Any]) -> Dict[str, Any]:
|
|
164
|
+
expected = {n["lane_id"] for n in dep_graph.get("nodes", []) if n.get("node_type") == "LANE"}
|
|
165
|
+
actual = {lr["lane_id"] for lr in manifest.get("lane_records", []) if "lane_id" in lr}
|
|
166
|
+
missing = expected - actual
|
|
167
|
+
status = "PASS" if not missing else "FAIL"
|
|
168
|
+
return {
|
|
169
|
+
"name": "required_lanes",
|
|
170
|
+
"status": status,
|
|
171
|
+
"details": f"Missing lanes: {sorted(missing)}" if missing else "All required lanes present",
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
def _check_no_unlisted_files(
|
|
175
|
+
self,
|
|
176
|
+
manifest: Dict[str, Any],
|
|
177
|
+
root_dir: Optional[Path] = None,
|
|
178
|
+
) -> Dict[str, Any]:
|
|
179
|
+
# Verifies files list format and detects unlisted files on disk
|
|
180
|
+
files = manifest.get("files", [])
|
|
181
|
+
if not isinstance(files, list):
|
|
182
|
+
return {"name": "no_unlisted_files", "status": "FAIL", "details": "'files' must be a list"}
|
|
183
|
+
|
|
184
|
+
target_root = root_dir if root_dir is not None else self.root_dir
|
|
185
|
+
if target_root is None or not target_root.is_dir():
|
|
186
|
+
return {"name": "no_unlisted_files", "status": "FAIL", "details": "Artifact root directory is required"}
|
|
187
|
+
|
|
188
|
+
manifest_paths = set()
|
|
189
|
+
for f in files:
|
|
190
|
+
rel = f.get("relative_path")
|
|
191
|
+
if rel:
|
|
192
|
+
manifest_paths.add(Path(rel).as_posix())
|
|
193
|
+
|
|
194
|
+
unlisted = []
|
|
195
|
+
for p in target_root.rglob("*"):
|
|
196
|
+
if p.is_file():
|
|
197
|
+
rel_posix = p.relative_to(target_root).as_posix()
|
|
198
|
+
# Skip ignore files / directories or manifest itself if located in root
|
|
199
|
+
if rel_posix in {".git", ".gitignore", "manifest.json"}:
|
|
200
|
+
continue
|
|
201
|
+
if rel_posix not in manifest_paths:
|
|
202
|
+
unlisted.append(rel_posix)
|
|
203
|
+
|
|
204
|
+
if unlisted:
|
|
205
|
+
return {
|
|
206
|
+
"name": "no_unlisted_files",
|
|
207
|
+
"status": "FAIL",
|
|
208
|
+
"details": f"Unlisted files detected: {sorted(unlisted)}",
|
|
209
|
+
}
|
|
210
|
+
return {"name": "no_unlisted_files", "status": "PASS", "details": "No unlisted files detected"}
|
|
211
|
+
|
|
212
|
+
def _check_hashes(
|
|
213
|
+
self,
|
|
214
|
+
manifest: Dict[str, Any],
|
|
215
|
+
root_dir: Optional[Path] = None,
|
|
216
|
+
) -> Dict[str, Any]:
|
|
217
|
+
files = manifest.get("files", [])
|
|
218
|
+
target_root = root_dir if root_dir is not None else self.root_dir
|
|
219
|
+
if target_root is None or not target_root.is_dir():
|
|
220
|
+
return {"name": "hash_agreement", "status": "FAIL", "details": "Artifact root directory is required"}
|
|
221
|
+
if not isinstance(files, list) or not files:
|
|
222
|
+
return {"name": "hash_agreement", "status": "FAIL", "details": "At least one artifact file is required"}
|
|
223
|
+
|
|
224
|
+
for f in files:
|
|
225
|
+
sha = f.get("sha256", "")
|
|
226
|
+
rel = f.get("relative_path", "")
|
|
227
|
+
if not isinstance(sha, str) or len(sha) != 64:
|
|
228
|
+
return {
|
|
229
|
+
"name": "hash_agreement",
|
|
230
|
+
"status": "FAIL",
|
|
231
|
+
"details": f"Invalid sha256 for file: {rel}",
|
|
232
|
+
}
|
|
233
|
+
if "size_bytes" in f and (type(f["size_bytes"]) is not int or f["size_bytes"] < 0):
|
|
234
|
+
return {"name": "hash_agreement", "status": "FAIL", "details": f"Invalid size_bytes for file: {rel}"}
|
|
235
|
+
|
|
236
|
+
if not target_root.is_dir():
|
|
237
|
+
return {"name": "hash_agreement", "status": "FAIL", "details": "Artifact root directory is unavailable"}
|
|
238
|
+
file_path = (target_root / rel).resolve()
|
|
239
|
+
try:
|
|
240
|
+
# Canonical containment check: prevent path traversal outside root_dir
|
|
241
|
+
file_path.relative_to(target_root.resolve())
|
|
242
|
+
except ValueError:
|
|
243
|
+
return {
|
|
244
|
+
"name": "hash_agreement",
|
|
245
|
+
"status": "FAIL",
|
|
246
|
+
"details": f"Path traversal escape detected for file: {rel}",
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if not file_path.is_file():
|
|
250
|
+
return {
|
|
251
|
+
"name": "hash_agreement",
|
|
252
|
+
"status": "FAIL",
|
|
253
|
+
"details": f"Missing file on disk: {rel}",
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
h = hashlib.sha256()
|
|
257
|
+
actual_size = 0
|
|
258
|
+
with open(file_path, "rb") as fp:
|
|
259
|
+
for chunk in iter(lambda: fp.read(8192), b""):
|
|
260
|
+
actual_size += len(chunk)
|
|
261
|
+
h.update(chunk)
|
|
262
|
+
if "size_bytes" in f and actual_size != f["size_bytes"]:
|
|
263
|
+
return {
|
|
264
|
+
"name": "hash_agreement",
|
|
265
|
+
"status": "FAIL",
|
|
266
|
+
"details": f"Size mismatch for {rel}: expected {f['size_bytes']}, got {actual_size}",
|
|
267
|
+
}
|
|
268
|
+
computed = h.hexdigest()
|
|
269
|
+
if computed.lower() != sha.lower():
|
|
270
|
+
return {
|
|
271
|
+
"name": "hash_agreement",
|
|
272
|
+
"status": "FAIL",
|
|
273
|
+
"details": f"Hash mismatch for {rel}: expected {sha}, got {computed}",
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return {"name": "hash_agreement", "status": "PASS", "details": "All listed hashes verified"}
|
|
277
|
+
|
|
278
|
+
def _check_independence(
|
|
279
|
+
self,
|
|
280
|
+
manifest: Dict[str, Any],
|
|
281
|
+
lane_contracts: List[Dict[str, Any]],
|
|
282
|
+
) -> Tuple[Dict[str, Any], List[str]]:
|
|
283
|
+
groups: Dict[str, List[str]] = {}
|
|
284
|
+
for contract in lane_contracts:
|
|
285
|
+
ig = contract.get("independence_group")
|
|
286
|
+
if ig:
|
|
287
|
+
groups.setdefault(ig, []).append(contract["lane_id"])
|
|
288
|
+
|
|
289
|
+
violations: List[str] = []
|
|
290
|
+
for group_id, lane_ids in groups.items():
|
|
291
|
+
if len(lane_ids) > 1:
|
|
292
|
+
files = manifest.get("files", [])
|
|
293
|
+
for f in files:
|
|
294
|
+
if f.get("lane_id") in lane_ids:
|
|
295
|
+
path = f.get("relative_path")
|
|
296
|
+
for other_lane in lane_ids:
|
|
297
|
+
if other_lane != f.get("lane_id"):
|
|
298
|
+
other_file = next(
|
|
299
|
+
(
|
|
300
|
+
f2
|
|
301
|
+
for f2 in files
|
|
302
|
+
if f2.get("relative_path") == path and f2.get("lane_id") == other_lane
|
|
303
|
+
),
|
|
304
|
+
None,
|
|
305
|
+
)
|
|
306
|
+
if other_file and other_file.get("sha256") != f.get("sha256"):
|
|
307
|
+
violations.append(
|
|
308
|
+
f"Independence collision: {f.get('lane_id')} vs {other_lane} on {path}"
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
status = "PASS" if not violations else "FAIL"
|
|
312
|
+
return (
|
|
313
|
+
{
|
|
314
|
+
"name": "independence",
|
|
315
|
+
"status": status,
|
|
316
|
+
"details": f"Violations: {violations}" if violations else "Independence verified",
|
|
317
|
+
},
|
|
318
|
+
violations,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def _check_residue(self, manifest: Dict[str, Any]) -> Tuple[Dict[str, Any], bool]:
|
|
322
|
+
prohibited_residue = False
|
|
323
|
+
files = manifest.get("files", [])
|
|
324
|
+
for f in files:
|
|
325
|
+
path = str(f.get("relative_path", "")).lower()
|
|
326
|
+
if any(term in path for term in [".tmp", ".bak", "desktop.ini", ".ds_store"]):
|
|
327
|
+
prohibited_residue = True
|
|
328
|
+
break
|
|
329
|
+
|
|
330
|
+
status = "HOLD" if prohibited_residue else "PASS"
|
|
331
|
+
return (
|
|
332
|
+
{
|
|
333
|
+
"name": "no_residue",
|
|
334
|
+
"status": status,
|
|
335
|
+
"details": "Prohibited residue found" if prohibited_residue else "No residue detected",
|
|
336
|
+
},
|
|
337
|
+
prohibited_residue,
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
def _determine_verdict(
|
|
341
|
+
self,
|
|
342
|
+
checks: List[Dict[str, Any]],
|
|
343
|
+
ind_violations: List[str],
|
|
344
|
+
residue_found: bool,
|
|
345
|
+
) -> WatchTowerVerdict:
|
|
346
|
+
if ind_violations:
|
|
347
|
+
return WatchTowerVerdict.REVISE
|
|
348
|
+
|
|
349
|
+
mandatory = ["manifest_validation", "required_lanes", "no_unlisted_files", "hash_agreement", "complete_set_sha256"]
|
|
350
|
+
for c in checks:
|
|
351
|
+
if c["name"] in mandatory and c["status"] == "FAIL":
|
|
352
|
+
if c["name"] in {"hash_agreement", "complete_set_sha256"}:
|
|
353
|
+
if c["name"] == "hash_agreement" and "Missing file on disk" in c.get("details", ""):
|
|
354
|
+
return WatchTowerVerdict.HOLD
|
|
355
|
+
return WatchTowerVerdict.REVISE
|
|
356
|
+
return WatchTowerVerdict.HOLD
|
|
357
|
+
|
|
358
|
+
if residue_found:
|
|
359
|
+
return WatchTowerVerdict.HOLD
|
|
360
|
+
|
|
361
|
+
return WatchTowerVerdict.PASS
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Capability layer: cryptographic sealing and anti-rollback authority."""
|
|
2
|
+
|
|
3
|
+
from .crypto import (
|
|
4
|
+
KeySize,
|
|
5
|
+
KeyExponent,
|
|
6
|
+
KeyPair,
|
|
7
|
+
SealResult,
|
|
8
|
+
VerifyResult,
|
|
9
|
+
KeyStore,
|
|
10
|
+
FileKeyStore,
|
|
11
|
+
compute_sha256,
|
|
12
|
+
compute_fingerprint_sha256,
|
|
13
|
+
generate_keypair,
|
|
14
|
+
canonicalize_json,
|
|
15
|
+
compute_canonical_hash,
|
|
16
|
+
seal,
|
|
17
|
+
verify,
|
|
18
|
+
create_keystore,
|
|
19
|
+
quick_seal,
|
|
20
|
+
quick_verify,
|
|
21
|
+
)
|
|
22
|
+
from .antirollback import (
|
|
23
|
+
AntirollbackAuthority,
|
|
24
|
+
Pin,
|
|
25
|
+
Checkpoint,
|
|
26
|
+
FileBackedAuthority,
|
|
27
|
+
InMemoryAuthority,
|
|
28
|
+
create_antirollback_authority,
|
|
29
|
+
create_checkpoint,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"KeySize",
|
|
34
|
+
"KeyExponent",
|
|
35
|
+
"KeyPair",
|
|
36
|
+
"SealResult",
|
|
37
|
+
"VerifyResult",
|
|
38
|
+
"KeyStore",
|
|
39
|
+
"FileKeyStore",
|
|
40
|
+
"compute_sha256",
|
|
41
|
+
"compute_fingerprint_sha256",
|
|
42
|
+
"generate_keypair",
|
|
43
|
+
"canonicalize_json",
|
|
44
|
+
"compute_canonical_hash",
|
|
45
|
+
"seal",
|
|
46
|
+
"verify",
|
|
47
|
+
"create_keystore",
|
|
48
|
+
"quick_seal",
|
|
49
|
+
"quick_verify",
|
|
50
|
+
"AntirollbackAuthority",
|
|
51
|
+
"Pin",
|
|
52
|
+
"Checkpoint",
|
|
53
|
+
"FileBackedAuthority",
|
|
54
|
+
"InMemoryAuthority",
|
|
55
|
+
"create_antirollback_authority",
|
|
56
|
+
"create_checkpoint",
|
|
57
|
+
]
|