secubox-openwrt/package/secubox/luci-app-zkp/root/usr/libexec/rpcd/luci.zkp
CyberMind-FR 4a972ab0ae fix(zkp-hamiltonian): ARM64 build fixes and RPCD CLI flag corrections
- Add #ifndef guard for ZKP_MAX_N in zkp_types.h to allow command-line override
- Copy OpenWrt Makefile to package root for proper feed detection
- Fix RPCD luci.zkp CLI flags: -r for ratio, -o for output prefix
- Add temp directory handling for keygen file generation

Tested on MochaBin router:
- zkp_keygen: generates graph + key pair
- zkp_prover: creates NIZK proof
- zkp_verifier: validates proof → ACCEPT

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-24 10:50:25 +01:00

410 lines
9.0 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 CyberMind.FR / SecuBox
#
# RPCD backend for ZKP Hamiltonian Dashboard
# Wraps zkp_keygen, zkp_prover, zkp_verifier CLI tools
. /usr/share/libubox/jshn.sh
readonly ZKP_DIR="/var/lib/zkp"
readonly GRAPHS_DIR="$ZKP_DIR/graphs"
readonly KEYS_DIR="$ZKP_DIR/keys"
readonly PROOFS_DIR="$ZKP_DIR/proofs"
# Ensure directories exist
init_dirs() {
mkdir -p "$GRAPHS_DIR" "$KEYS_DIR" "$PROOFS_DIR" 2>/dev/null
}
# Check if ZKP tools are available
check_tools() {
command -v zkp_keygen >/dev/null 2>&1 && \
command -v zkp_prover >/dev/null 2>&1 && \
command -v zkp_verifier >/dev/null 2>&1
}
# Get library version
get_version() {
if check_tools; then
zkp_keygen --version 2>/dev/null | head -1 || echo "1.0.0"
else
echo "not installed"
fi
}
# Count saved keys
count_keys() {
init_dirs
ls -1 "$KEYS_DIR"/*.key 2>/dev/null | wc -l
}
# ============== RPC Methods ==============
method_status() {
local tools_ok="false"
local version="not installed"
local key_count=0
if check_tools; then
tools_ok="true"
version=$(get_version)
fi
init_dirs
key_count=$(ls -1 "$KEYS_DIR"/*.key 2>/dev/null | wc -l)
cat <<EOF
{"tools_available":$tools_ok,"version":"$version","key_count":$key_count,"graphs_dir":"$GRAPHS_DIR","keys_dir":"$KEYS_DIR","proofs_dir":"$PROOFS_DIR"}
EOF
}
method_list_keys() {
init_dirs
local first=1
echo -n '{"keys":['
for keyfile in "$KEYS_DIR"/*.key; do
[ -f "$keyfile" ] || continue
local name=$(basename "$keyfile" .key)
local graphfile="$GRAPHS_DIR/${name}.graph"
local nodes=0
local graph_size=0
local key_size=0
local created=0
if [ -f "$graphfile" ]; then
graph_size=$(stat -c %s "$graphfile" 2>/dev/null || echo 0)
nodes=$(od -A n -t u1 -j 4 -N 1 "$graphfile" 2>/dev/null | tr -d ' ' || echo 0)
fi
key_size=$(stat -c %s "$keyfile" 2>/dev/null || echo 0)
created=$(stat -c %Y "$keyfile" 2>/dev/null || echo 0)
[ "$first" = "1" ] || echo -n ','
first=0
echo -n "{\"name\":\"$name\",\"nodes\":${nodes:-0},\"graph_size\":$graph_size,\"key_size\":$key_size,\"created\":$created}"
done
echo ']}'
}
method_keygen() {
local nodes density name
read -r input
json_load "$input"
json_get_var nodes nodes
json_get_var density density
json_get_var name name
# Defaults
[ -z "$nodes" ] && nodes=20
[ -z "$density" ] && density="0.8"
[ -z "$name" ] && name="key_$(date +%s)"
# Validate
if [ "$nodes" -lt 4 ] || [ "$nodes" -gt 50 ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Nodes must be between 4 and 50"
json_dump
return
fi
# Sanitize name
name=$(echo "$name" | sed 's/[^a-zA-Z0-9_-]/_/g')
init_dirs
local graphfile="$GRAPHS_DIR/${name}.graph"
local keyfile="$KEYS_DIR/${name}.key"
# Check if already exists
if [ -f "$keyfile" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Key '$name' already exists"
json_dump
return
fi
# Generate
if ! check_tools; then
json_init
json_add_boolean "success" 0
json_add_string "error" "ZKP tools not installed"
json_dump
return
fi
# Create temp directory for generation
local tmpdir="/tmp/zkp_gen_$$"
mkdir -p "$tmpdir"
local prefix="$tmpdir/$name"
local output
output=$(zkp_keygen -n "$nodes" -r "$density" -o "$prefix" 2>&1)
local rc=$?
# Move generated files to proper locations
if [ $rc -eq 0 ] && [ -f "${prefix}.graph" ] && [ -f "${prefix}.key" ]; then
mv "${prefix}.graph" "$graphfile"
mv "${prefix}.key" "$keyfile"
fi
rm -rf "$tmpdir"
if [ $rc -eq 0 ] && [ -f "$graphfile" ] && [ -f "$keyfile" ]; then
local graph_size=$(stat -c %s "$graphfile")
local key_size=$(stat -c %s "$keyfile")
json_init
json_add_boolean "success" 1
json_add_string "name" "$name"
json_add_int "nodes" "$nodes"
json_add_string "density" "$density"
json_add_int "graph_size" "$graph_size"
json_add_int "key_size" "$key_size"
json_add_string "output" "$output"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "error" "Keygen failed: $output"
json_dump
fi
}
method_prove() {
local name
read -r input
json_load "$input"
json_get_var name name
if [ -z "$name" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Missing key name"
json_dump
return
fi
local graphfile="$GRAPHS_DIR/${name}.graph"
local keyfile="$KEYS_DIR/${name}.key"
local prooffile="$PROOFS_DIR/${name}.proof"
if [ ! -f "$graphfile" ] || [ ! -f "$keyfile" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Key '$name' not found"
json_dump
return
fi
if ! check_tools; then
json_init
json_add_boolean "success" 0
json_add_string "error" "ZKP tools not installed"
json_dump
return
fi
local output
output=$(zkp_prover -g "$graphfile" -k "$keyfile" -o "$prooffile" 2>&1)
local rc=$?
if [ $rc -eq 0 ] && [ -f "$prooffile" ]; then
local proof_size=$(stat -c %s "$prooffile")
# Base64 encode for transport (first 1KB for preview)
local proof_preview=$(head -c 1024 "$prooffile" | base64 -w 0)
json_init
json_add_boolean "success" 1
json_add_string "name" "$name"
json_add_int "proof_size" "$proof_size"
json_add_string "proof_file" "$prooffile"
json_add_string "proof_preview" "$proof_preview"
json_add_string "output" "$output"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "error" "Prove failed: $output"
json_dump
fi
}
method_verify() {
local name
read -r input
json_load "$input"
json_get_var name name
if [ -z "$name" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Missing key name"
json_dump
return
fi
local graphfile="$GRAPHS_DIR/${name}.graph"
local prooffile="$PROOFS_DIR/${name}.proof"
if [ ! -f "$graphfile" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Graph '$name' not found"
json_dump
return
fi
if [ ! -f "$prooffile" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Proof '$name' not found (run prove first)"
json_dump
return
fi
if ! check_tools; then
json_init
json_add_boolean "success" 0
json_add_string "error" "ZKP tools not installed"
json_dump
return
fi
local output result
output=$(zkp_verifier -g "$graphfile" -p "$prooffile" 2>&1)
local rc=$?
# Parse result from output
if echo "$output" | grep -q "ACCEPT"; then
result="ACCEPT"
elif echo "$output" | grep -q "REJECT"; then
result="REJECT"
else
result="UNKNOWN"
fi
json_init
json_add_boolean "success" 1
json_add_string "name" "$name"
json_add_string "result" "$result"
json_add_boolean "valid" "$([ "$result" = "ACCEPT" ] && echo 1 || echo 0)"
json_add_string "output" "$output"
json_dump
}
method_delete_key() {
local name
read -r input
json_load "$input"
json_get_var name name
if [ -z "$name" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Missing key name"
json_dump
return
fi
local graphfile="$GRAPHS_DIR/${name}.graph"
local keyfile="$KEYS_DIR/${name}.key"
local prooffile="$PROOFS_DIR/${name}.proof"
local deleted=0
[ -f "$graphfile" ] && rm -f "$graphfile" && deleted=$((deleted + 1))
[ -f "$keyfile" ] && rm -f "$keyfile" && deleted=$((deleted + 1))
[ -f "$prooffile" ] && rm -f "$prooffile" && deleted=$((deleted + 1))
json_init
json_add_boolean "success" 1
json_add_string "name" "$name"
json_add_int "files_deleted" "$deleted"
json_dump
}
method_get_graph() {
local name
read -r input
json_load "$input"
json_get_var name name
if [ -z "$name" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Missing key name"
json_dump
return
fi
local graphfile="$GRAPHS_DIR/${name}.graph"
if [ ! -f "$graphfile" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Graph '$name' not found"
json_dump
return
fi
# Extract graph info from binary
local nodes=$(od -A n -t u1 -j 4 -N 1 "$graphfile" 2>/dev/null | tr -d ' ')
local graph_size=$(stat -c %s "$graphfile")
# Generate simple adjacency representation
# Read adjacency bits and create edge list
local edges=""
local i=0
json_init
json_add_boolean "success" 1
json_add_string "name" "$name"
json_add_int "nodes" "${nodes:-0}"
json_add_int "size" "$graph_size"
json_add_string "file" "$graphfile"
json_dump
}
# ============== Main Dispatcher ==============
case "$1" in
list)
echo '{'
echo '"status":{},'
echo '"list_keys":{},'
echo '"get_graph":{"name":"String"},'
echo '"keygen":{"nodes":"Number","density":"String","name":"String"},'
echo '"prove":{"name":"String"},'
echo '"verify":{"name":"String"},'
echo '"delete_key":{"name":"String"}'
echo '}'
;;
call)
case "$2" in
status) method_status ;;
list_keys) method_list_keys ;;
get_graph) method_get_graph ;;
keygen) method_keygen ;;
prove) method_prove ;;
verify) method_verify ;;
delete_key) method_delete_key ;;
*)
json_init
json_add_boolean "success" 0
json_add_string "error" "Unknown method: $2"
json_dump
;;
esac
;;
esac