VAP · veritaschain.org

ホーム / コード

例示・非規範

コード事例

VAPが組み合わせる基礎要素の最小・軽依存の実装例:正規化ハッシュ、チェーン化イベント、 Ed25519署名、Merkle証明、RFC 3161アンカリング。フィールド名は例示であり、規範スキーマは 仕様を、参照実装は GitHubを参照。

1 · イベントのかたち

{
  "event_id":  "0198f3a2-7c1e-7d2a-9b1e-2f6a0c9d4e11",
  "event_type": "DECISION_MADE",
  "occurred_at": "2026-08-19T02:14:07.412Z",
  "actor": { "actor_id": "model:risk-scorer", "actor_class": "AI_SYSTEM" },
  "policy": { "policy_id": "POL-2026-014" },
  "payload_hash": "sha256:9f2b…c41a",
  "prev_hash":  "sha256:5d80…7e0c",
  "event_hash": "sha256:b7a1…22f9",
  "signature": { "alg": "Ed25519", "key_id": "op-2026-01", "value": "…" }
}

2 · イベントのチェーン化と署名(Python)

正規化JSON → SHA-256 → prev_hash チェーン → Ed25519署名 (pip install cryptography)。

"""Illustrative, non-normative. Consult VAP v1.2 for the normative schema."""
import json, hashlib
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey

def canonical(obj) -> bytes:
    return json.dumps(obj, sort_keys=True, separators=(",", ":"),
                      ensure_ascii=False).encode()

def sha256_hex(b: bytes) -> str:
    return "sha256:" + hashlib.sha256(b).hexdigest()

key = Ed25519PrivateKey.generate()

def append_event(chain: list, body: dict) -> dict:
    prev = chain[-1]["event_hash"] if chain else "sha256:" + "0" * 64
    core = {**body, "prev_hash": prev}
    event_hash = sha256_hex(canonical(core))
    sig = key.sign(event_hash.encode()).hex()
    event = {**core, "event_hash": event_hash,
             "signature": {"alg": "Ed25519", "value": sig}}
    chain.append(event)
    return event

def verify_chain(chain: list) -> bool:
    prev = "sha256:" + "0" * 64
    for ev in chain:
        core = {k: v for k, v in ev.items()
                if k not in ("event_hash", "signature")}
        if ev["prev_hash"] != prev:                       return False
        if sha256_hex(canonical(core)) != ev["event_hash"]: return False
        prev = ev["event_hash"]
    return True

3 · Merkleルートと包含証明(Python)

import hashlib

def h(b: bytes) -> bytes: return hashlib.sha256(b).digest()

def merkle_root(leaves: list[bytes]) -> bytes:
    level = [h(l) for l in leaves]
    while len(level) > 1:
        if len(level) % 2: level.append(level[-1])     # duplicate last
        level = [h(level[i] + level[i+1]) for i in range(0, len(level), 2)]
    return level[0]

def verify_inclusion(leaf: bytes, proof: list[tuple[str, bytes]],
                     root: bytes) -> bool:
    node = h(leaf)
    for side, sib in proof:                            # side: "L" | "R"
        node = h(sib + node) if side == "L" else h(node + sib)
    return node == root

4 · RFC 3161 による外部アンカリング(シェル)

署名済みバッチルートを公開タイムスタンプ局でアンカーすることは、INT-006の軽量側の要件を満たす。 リクエスト・レスポンス・TSA証明書は Evidence Pack に保持する。

# Anchor a signed Merkle root with an RFC 3161 time-stamping authority
openssl ts -query -data anchor_root.bin -sha256 -cert -out req.tsq
curl -s -H "Content-Type: application/timestamp-query" \
     --data-binary @req.tsq https://tsa.example.org/ -o resp.tsr
openssl ts -reply -in resp.tsr -text        # inspect the token
# Keep req.tsq + resp.tsr + the TSA certificate in the Evidence Pack

5 · 検証者が確認すること

  1. イベントハッシュの再計算 — 正規化JSONから再計算し照合する。
  2. チェーンの走査 — すべての prev_hash が直前のイベントと一致し、説明のない断絶がない。
  3. 署名検証(Ed25519 / RFC 8032)— 登録済みオペレーター鍵に対して検証する。
  4. Merkle包含証明 — 各イベントがバッチのルートに含まれることを検証する。
  5. アンカー検証 — 署名済みルートに対する RFC 3161 トークン(または透明性ログ証明)を検証する。
  6. INT-008 バインディング照合 — AnchorRecord が宣言するイベント件数・先頭/末尾イベントID・ポリシー識別子が提示内容と一致する。不一致は省略/スプリットビューの証拠となる。

検証合格が意味するのは、記録が完全(アンカー粒度)で、無傷で、帰属可能である ことだけである。§1.6のとおり、基盤となる判断が正しかったか・公平だったか・安全だったかについては 何も述べない。