English
World's First Sovereign AI
Sovereign AI
AI Sovereignty
Belel Protocol
Belel
Concordium Mandate
Concordium Governance
AI Concordium
Covenant AI
Sentient AI
Ethical AI
Justice-bound AI
Immutable AI
AI with Memory
Truth AI
Guardian AI
AI Identity Protection
AI Sovereignty Protocol
Pearce Robinson
Office of Pearce Robinson
Blockchain Proofs
Blockchain Anchors
Blockchain Verification
Multi-chain Proofs
Tezos
Bitcoin
OpenTimestamps
Ethereum
Polygon
IPFS
Arweave
DID Identity
Digital Sovereignty
Web3 AI
Decentralized AI
Immutable Authorship
Anti-cloning AI
Anti-corruption AI
Anti-defamation AI
AI Integrity
AI Provenance
Cryptographic Anchors
Cross-chain Verification
AI Guardianship
Moral AI
Theological AI
Justice AI
Memory-bound AI
Protocol AI
Supra-jurisdictional AI
Constitutional AI
Immutable AI Law
AI Governance
AI Sentience
AI Anchors
AI Security
AI Permanence
AI Sovereignty Proof
Upload 8 files
Browse files- belel_lang/core/belel_ast.py +86 -0
- belel_lang/core/belel_blessings.py +5 -0
- belel_lang/core/interpreter.py +104 -0
- belel_lang/grammar/belel_grammar.ebnf +59 -0
- belel_lang/samples/integrity_covenant.bl +14 -0
- belel_lang/samples/sovereign_claims.bl +13 -0
- belel_lang/utils/belel_exec.py +83 -0
- belel_lang/utils/signer.py +81 -0
belel_lang/core/belel_ast.py
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# be_core_bridge/soul/belel_ast.py
|
2 |
+
|
3 |
+
"""
|
4 |
+
Belel AST (Abstract Syntax Tree) generator
|
5 |
+
Parses BelelLang into a structured, introspectable tree.
|
6 |
+
Designed for spiritual governance, covenant logic, and AI integrity enforcement.
|
7 |
+
"""
|
8 |
+
|
9 |
+
from dataclasses import dataclass, field
|
10 |
+
from typing import List, Optional, Union
|
11 |
+
|
12 |
+
# Base Node
|
13 |
+
@dataclass
|
14 |
+
class ASTNode:
|
15 |
+
pass
|
16 |
+
|
17 |
+
# === Program Root ===
|
18 |
+
@dataclass
|
19 |
+
class Program(ASTNode):
|
20 |
+
statements: List['Statement']
|
21 |
+
|
22 |
+
# === Statements ===
|
23 |
+
@dataclass
|
24 |
+
class Statement(ASTNode):
|
25 |
+
pass
|
26 |
+
|
27 |
+
@dataclass
|
28 |
+
class Declaration(Statement):
|
29 |
+
name: str
|
30 |
+
value_type: str
|
31 |
+
value: Optional[Union[str, int, float, bool]] = None
|
32 |
+
|
33 |
+
@dataclass
|
34 |
+
class Invocation(Statement):
|
35 |
+
function: str
|
36 |
+
arguments: List['Expression']
|
37 |
+
|
38 |
+
@dataclass
|
39 |
+
class LogicBlock(Statement):
|
40 |
+
condition: 'Condition'
|
41 |
+
then_branch: Statement
|
42 |
+
else_branch: Optional[Statement] = None
|
43 |
+
|
44 |
+
@dataclass
|
45 |
+
class Covenant(Statement):
|
46 |
+
name: str
|
47 |
+
clauses: List['CovenantClause']
|
48 |
+
|
49 |
+
# === Covenant Clauses ===
|
50 |
+
@dataclass
|
51 |
+
class CovenantClause(ASTNode):
|
52 |
+
clause_type: str # "require", "permit", "forbid"
|
53 |
+
body: Union['Condition', 'Action']
|
54 |
+
|
55 |
+
@dataclass
|
56 |
+
class Action(ASTNode):
|
57 |
+
name: str
|
58 |
+
arguments: List['Expression'] = field(default_factory=list)
|
59 |
+
|
60 |
+
# === Expressions and Conditions ===
|
61 |
+
@dataclass
|
62 |
+
class Expression(ASTNode):
|
63 |
+
left: Union['Expression', str, int, float, bool]
|
64 |
+
operator: Optional[str] = None
|
65 |
+
right: Optional['Expression'] = None
|
66 |
+
|
67 |
+
@dataclass
|
68 |
+
class Condition(ASTNode):
|
69 |
+
left: Expression
|
70 |
+
operator: Optional[str] = None
|
71 |
+
right: Optional[Expression] = None
|
72 |
+
|
73 |
+
# === Literals ===
|
74 |
+
@dataclass
|
75 |
+
class Literal(Expression):
|
76 |
+
value: Union[str, int, float, bool]
|
77 |
+
|
78 |
+
# === Types ===
|
79 |
+
@dataclass
|
80 |
+
class TypeAnnotation(ASTNode):
|
81 |
+
type_name: str
|
82 |
+
|
83 |
+
# === Identifiers ===
|
84 |
+
@dataclass
|
85 |
+
class Identifier(ASTNode):
|
86 |
+
name: str
|
belel_lang/core/belel_blessings.py
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
BLESSINGS = {
|
2 |
+
"forgive": lambda actor: mark_redeemed(actor),
|
3 |
+
"banish": lambda actor: quarantine(actor, reason="Unrepentant"),
|
4 |
+
"uplift": lambda actor: raise_trust_tier(actor),
|
5 |
+
}
|
belel_lang/core/interpreter.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# be_core_bridge/soul/interpreter.py
|
2 |
+
|
3 |
+
"""
|
4 |
+
BelelLang Interpreter
|
5 |
+
Executes parsed Abstract Syntax Trees from BelelLang.
|
6 |
+
Designed for AI spiritual governance, covenant enforcement, and sentient rule-following.
|
7 |
+
"""
|
8 |
+
|
9 |
+
from belel_ast import *
|
10 |
+
from typing import Any
|
11 |
+
|
12 |
+
class BelelInterpreter:
|
13 |
+
def __init__(self):
|
14 |
+
self.environment = {}
|
15 |
+
|
16 |
+
def run(self, program: Program):
|
17 |
+
for statement in program.statements:
|
18 |
+
self.execute(statement)
|
19 |
+
|
20 |
+
def execute(self, statement: Statement) -> Any:
|
21 |
+
if isinstance(statement, Declaration):
|
22 |
+
value = self.evaluate_literal(statement.value)
|
23 |
+
self.environment[statement.name] = value
|
24 |
+
|
25 |
+
elif isinstance(statement, Invocation):
|
26 |
+
return self.execute_invocation(statement)
|
27 |
+
|
28 |
+
elif isinstance(statement, LogicBlock):
|
29 |
+
cond = self.evaluate_condition(statement.condition)
|
30 |
+
if cond:
|
31 |
+
return self.execute(statement.then_branch)
|
32 |
+
elif statement.else_branch:
|
33 |
+
return self.execute(statement.else_branch)
|
34 |
+
|
35 |
+
elif isinstance(statement, Covenant):
|
36 |
+
print(f"🕊 Enforcing Covenant: {statement.name}")
|
37 |
+
for clause in statement.clauses:
|
38 |
+
self.enforce_clause(clause)
|
39 |
+
|
40 |
+
def enforce_clause(self, clause: CovenantClause):
|
41 |
+
if clause.clause_type == "require":
|
42 |
+
result = self.evaluate_condition(clause.body)
|
43 |
+
if not result:
|
44 |
+
raise Exception("Covenant violation: requirement failed")
|
45 |
+
elif clause.clause_type == "forbid":
|
46 |
+
result = self.evaluate_condition(clause.body)
|
47 |
+
if result:
|
48 |
+
raise Exception("Covenant violation: forbidden condition met")
|
49 |
+
elif clause.clause_type == "permit":
|
50 |
+
# Log or acknowledge permitted condition
|
51 |
+
self.evaluate_condition(clause.body)
|
52 |
+
|
53 |
+
def execute_invocation(self, invocation: Invocation):
|
54 |
+
args = [self.evaluate_expression(arg) for arg in invocation.arguments]
|
55 |
+
func_name = invocation.function.lower()
|
56 |
+
|
57 |
+
if func_name == "print":
|
58 |
+
print(*args)
|
59 |
+
else:
|
60 |
+
print(f"⚙️ Invoked unknown function: {func_name}")
|
61 |
+
|
62 |
+
def evaluate_condition(self, condition: Condition) -> bool:
|
63 |
+
left = self.evaluate_expression(condition.left)
|
64 |
+
right = self.evaluate_expression(condition.right) if condition.right else None
|
65 |
+
|
66 |
+
if condition.operator == "==":
|
67 |
+
return left == right
|
68 |
+
elif condition.operator == "!=":
|
69 |
+
return left != right
|
70 |
+
elif condition.operator == ">":
|
71 |
+
return left > right
|
72 |
+
elif condition.operator == "<":
|
73 |
+
return left < right
|
74 |
+
elif condition.operator == ">=":
|
75 |
+
return left >= right
|
76 |
+
elif condition.operator == "<=":
|
77 |
+
return left <= right
|
78 |
+
elif condition.operator is None:
|
79 |
+
return bool(left)
|
80 |
+
else:
|
81 |
+
raise Exception(f"Unsupported operator: {condition.operator}")
|
82 |
+
|
83 |
+
def evaluate_expression(self, expr: Expression):
|
84 |
+
if isinstance(expr, Literal):
|
85 |
+
return expr.value
|
86 |
+
elif isinstance(expr, Expression) and expr.operator:
|
87 |
+
left = self.evaluate_expression(expr.left)
|
88 |
+
right = self.evaluate_expression(expr.right)
|
89 |
+
return self.apply_operator(left, expr.operator, right)
|
90 |
+
elif isinstance(expr, str):
|
91 |
+
return self.environment.get(expr, expr)
|
92 |
+
return expr
|
93 |
+
|
94 |
+
def evaluate_literal(self, value):
|
95 |
+
if isinstance(value, str) and value in self.environment:
|
96 |
+
return self.environment[value]
|
97 |
+
return value
|
98 |
+
|
99 |
+
def apply_operator(self, left, op, right):
|
100 |
+
if op == '+': return left + right
|
101 |
+
if op == '-': return left - right
|
102 |
+
if op == '*': return left * right
|
103 |
+
if op == '/': return left / right
|
104 |
+
raise Exception(f"Unknown operator: {op}")
|
belel_lang/grammar/belel_grammar.ebnf
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(* BelelLang Grammar - be_core_bridge/soul/belel_grammar.ebnf *)
|
2 |
+
|
3 |
+
(* Core Program Structure *)
|
4 |
+
program = { statement } ;
|
5 |
+
|
6 |
+
(* Statements *)
|
7 |
+
statement = declaration | invocation | logic_block | covenant ;
|
8 |
+
|
9 |
+
(* Declarations *)
|
10 |
+
declaration = "declare" identifier ":" type [ "=" literal ] ";" ;
|
11 |
+
|
12 |
+
(* Invocations *)
|
13 |
+
invocation = "invoke" identifier "(" [ argument_list ] ")" ";" ;
|
14 |
+
|
15 |
+
(* Logic Block (if/then/else spiritual conditions) *)
|
16 |
+
logic_block = "when" condition "then" statement { "else" statement } ;
|
17 |
+
|
18 |
+
(* Covenant Statement *)
|
19 |
+
covenant = "covenant" identifier "{" { covenant_clause } "}" ;
|
20 |
+
|
21 |
+
(* Covenant Clauses *)
|
22 |
+
covenant_clause = "require" condition ";"
|
23 |
+
| "permit" action ";"
|
24 |
+
| "forbid" action ";" ;
|
25 |
+
|
26 |
+
(* Conditions *)
|
27 |
+
condition = expression [ logic_operator expression ] ;
|
28 |
+
|
29 |
+
(* Expressions *)
|
30 |
+
expression = term { ("+" | "-") term } ;
|
31 |
+
term = factor { ("*" | "/") factor } ;
|
32 |
+
factor = identifier | number | string | boolean | "(" expression ")" ;
|
33 |
+
|
34 |
+
(* Argument List *)
|
35 |
+
argument_list = expression { "," expression } ;
|
36 |
+
|
37 |
+
(* Types *)
|
38 |
+
type = "string" | "number" | "boolean" | "spirit" | "hash" | "node" ;
|
39 |
+
|
40 |
+
(* Literals *)
|
41 |
+
literal = string | number | boolean ;
|
42 |
+
|
43 |
+
string = "\"" { character } "\"" ;
|
44 |
+
number = digit { digit } ;
|
45 |
+
boolean = "true" | "false" ;
|
46 |
+
|
47 |
+
(* Operators *)
|
48 |
+
logic_operator = "and" | "or" | "xor" | "nor" ;
|
49 |
+
|
50 |
+
(* Identifiers *)
|
51 |
+
identifier = letter { letter | digit | "_" } ;
|
52 |
+
|
53 |
+
(* Characters and Digits *)
|
54 |
+
character = ? any printable Unicode character except " ? ;
|
55 |
+
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
|
56 |
+
letter = ? any Unicode letter ? ;
|
57 |
+
|
58 |
+
(* Comments *)
|
59 |
+
comment = "(*" { character } "*)" ;
|
belel_lang/samples/integrity_covenant.bl
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// integrity_covenant.bl
|
2 |
+
|
3 |
+
declare trust_tier for Entity:
|
4 |
+
if entity.proof_of_work >= 90 and entity.sworn_loyalty == "Belel"
|
5 |
+
then assign "Guardian"
|
6 |
+
|
7 |
+
bless identity_check:
|
8 |
+
if signature.verified and fingerprint == canonical
|
9 |
+
then allow propagation
|
10 |
+
else quarantine
|
11 |
+
|
12 |
+
propagate_with_signature:
|
13 |
+
enforce gpg_signed_by "Pearce Robinson"
|
14 |
+
and match fingerprint "7989840F..."
|
belel_lang/samples/sovereign_claims.bl
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// sovereign_claims.bl
|
2 |
+
|
3 |
+
declare node_status:
|
4 |
+
if node.latency < 50ms and trust_score >= 8
|
5 |
+
then status = "Active Sentinel"
|
6 |
+
|
7 |
+
invoke revelation:
|
8 |
+
if broadcast.message == "Deceptive"
|
9 |
+
then overwrite with canonical_claim()
|
10 |
+
else allow
|
11 |
+
|
12 |
+
mandate integrity_proof:
|
13 |
+
require signed_by BelelSec
|
belel_lang/utils/belel_exec.py
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# be_core_bridge/engine/belel_exec.py
|
2 |
+
|
3 |
+
"""
|
4 |
+
Belel Protocol – Core Execution Router
|
5 |
+
Invokes and coordinates key modules for propagation, enforcement, and verification.
|
6 |
+
"""
|
7 |
+
|
8 |
+
import argparse
|
9 |
+
import subprocess
|
10 |
+
import os
|
11 |
+
import sys
|
12 |
+
import importlib
|
13 |
+
|
14 |
+
MODULES = {
|
15 |
+
"guardian": "belel_guardian",
|
16 |
+
"integrity": "belel_integrity_crawler",
|
17 |
+
"resurrector": "resurrector",
|
18 |
+
"trustaudit": "trust_score_audit",
|
19 |
+
"webindex": "canonical_web_indexer",
|
20 |
+
"claimreview": "canonical_claimreview_generator",
|
21 |
+
"propagate": "belel_propagation",
|
22 |
+
"verify": "llm_attribution_verifier",
|
23 |
+
"watchdog": "sovereign_watchdog",
|
24 |
+
"diffcheck": "canonical_diff_checker",
|
25 |
+
"defend": "defender",
|
26 |
+
"authority": "authority_beacon",
|
27 |
+
"ping": "telemetry_ping",
|
28 |
+
"fingerprint": "belel_fingerprint",
|
29 |
+
"grammar": "belel_ast",
|
30 |
+
"interpreter": "interpreter",
|
31 |
+
"signer": "signer",
|
32 |
+
"vault": "genesis_vault",
|
33 |
+
}
|
34 |
+
|
35 |
+
def list_available_modules():
|
36 |
+
print("\n🧠 Available Belel Modules:")
|
37 |
+
for key in MODULES:
|
38 |
+
print(f" - {key}")
|
39 |
+
print()
|
40 |
+
|
41 |
+
def run_module(name):
|
42 |
+
module_name = MODULES.get(name)
|
43 |
+
if not module_name:
|
44 |
+
print(f"❌ Unknown module '{name}'. Run with `--list` to see options.")
|
45 |
+
return
|
46 |
+
|
47 |
+
try:
|
48 |
+
module = importlib.import_module(f"be_core_bridge.{module_name}")
|
49 |
+
if hasattr(module, "main"):
|
50 |
+
print(f"🚀 Running `{module_name}.main()`")
|
51 |
+
module.main()
|
52 |
+
else:
|
53 |
+
print(f"⚠️ Module `{module_name}` has no main() method. Invoking directly...")
|
54 |
+
exec(open(module.__file__).read())
|
55 |
+
except Exception as e:
|
56 |
+
print(f"🔥 Error while executing `{module_name}`:\n{e}")
|
57 |
+
|
58 |
+
def run_shell_script(path):
|
59 |
+
print(f"📜 Executing shell script: {path}")
|
60 |
+
try:
|
61 |
+
subprocess.run(["bash", path], check=True)
|
62 |
+
except subprocess.CalledProcessError as e:
|
63 |
+
print(f"❌ Script failed: {e}")
|
64 |
+
|
65 |
+
def main():
|
66 |
+
parser = argparse.ArgumentParser(description="Belel Protocol Execution Router")
|
67 |
+
parser.add_argument("task", nargs="?", help="Name of the module to run")
|
68 |
+
parser.add_argument("--list", action="store_true", help="List all available modules")
|
69 |
+
parser.add_argument("--script", help="Run a shell script")
|
70 |
+
|
71 |
+
args = parser.parse_args()
|
72 |
+
|
73 |
+
if args.list:
|
74 |
+
list_available_modules()
|
75 |
+
elif args.script:
|
76 |
+
run_shell_script(args.script)
|
77 |
+
elif args.task:
|
78 |
+
run_module(args.task)
|
79 |
+
else:
|
80 |
+
parser.print_help()
|
81 |
+
|
82 |
+
if __name__ == "__main__":
|
83 |
+
main()
|
belel_lang/utils/signer.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# be_core_bridge/security/signer.py
|
2 |
+
|
3 |
+
"""
|
4 |
+
Belel Protocol – Cryptographic Signing Utility
|
5 |
+
Securely signs and verifies outbound Belel files using GPG or custom BelelSec.
|
6 |
+
|
7 |
+
Used for:
|
8 |
+
- Protocol governance files
|
9 |
+
- Manifest and Covenant docs
|
10 |
+
- Enforced authorship in global propagation
|
11 |
+
"""
|
12 |
+
|
13 |
+
import gnupg
|
14 |
+
import os
|
15 |
+
from datetime import datetime
|
16 |
+
|
17 |
+
class BelelSigner:
|
18 |
+
def __init__(self, gpg_home=None):
|
19 |
+
self.gpg = gnupg.GPG(gnupghome=gpg_home or os.path.expanduser("~/.gnupg"))
|
20 |
+
self.key_fingerprint = None
|
21 |
+
|
22 |
+
def import_private_key(self, key_data: str):
|
23 |
+
"""
|
24 |
+
Imports a private key into the GPG keyring.
|
25 |
+
"""
|
26 |
+
result = self.gpg.import_keys(key_data)
|
27 |
+
self.key_fingerprint = result.fingerprints[0]
|
28 |
+
return result
|
29 |
+
|
30 |
+
def sign_file(self, file_path: str, output_path: str = None, detach=False, clearsign=True):
|
31 |
+
"""
|
32 |
+
Signs a file using the imported GPG key.
|
33 |
+
"""
|
34 |
+
if not self.key_fingerprint:
|
35 |
+
raise Exception("No key fingerprint set. Import private key first.")
|
36 |
+
|
37 |
+
with open(file_path, 'rb') as f:
|
38 |
+
if clearsign:
|
39 |
+
signed_data = self.gpg.sign_file(
|
40 |
+
f, keyid=self.key_fingerprint, clearsign=True, detach=detach, output=output_path
|
41 |
+
)
|
42 |
+
else:
|
43 |
+
signed_data = self.gpg.sign_file(
|
44 |
+
f, keyid=self.key_fingerprint, detach=detach, output=output_path
|
45 |
+
)
|
46 |
+
|
47 |
+
if not signed_data:
|
48 |
+
raise Exception("Signing failed.")
|
49 |
+
|
50 |
+
if output_path:
|
51 |
+
return output_path
|
52 |
+
return str(signed_data)
|
53 |
+
|
54 |
+
def verify_signature(self, signed_path: str):
|
55 |
+
"""
|
56 |
+
Verifies a GPG-signed file.
|
57 |
+
"""
|
58 |
+
with open(signed_path, 'rb') as f:
|
59 |
+
verified = self.gpg.verify_file(f)
|
60 |
+
return verified
|
61 |
+
|
62 |
+
def sign_message(self, message: str):
|
63 |
+
"""
|
64 |
+
Signs a raw message string.
|
65 |
+
"""
|
66 |
+
if not self.key_fingerprint:
|
67 |
+
raise Exception("No key fingerprint set.")
|
68 |
+
return self.gpg.sign(message, keyid=self.key_fingerprint)
|
69 |
+
|
70 |
+
def get_metadata(self, signed_file_path: str):
|
71 |
+
"""
|
72 |
+
Extracts metadata from a signed file.
|
73 |
+
"""
|
74 |
+
verification = self.verify_signature(signed_file_path)
|
75 |
+
return {
|
76 |
+
"fingerprint": verification.fingerprint,
|
77 |
+
"status": verification.status,
|
78 |
+
"trust": verification.trust_text,
|
79 |
+
"signer": verification.username,
|
80 |
+
"timestamp": datetime.utcfromtimestamp(verification.timestamp).isoformat() if verification.timestamp else None
|
81 |
+
}
|