Agent Skills by ALSEL
汎用セキュリティ⭐ リポ 16品質スコア 82/100

schemapin

MCPラグプル攻撃を防ぐための暗号ツールスキーマ検証機能です。ECDSA P-256署名、SHA-256ハッシング、TOFUキーピンニング、.well-knownディスカバリー、署名付き失効ドキュメント、署名の有効期限切れ(v1.4-alpha版は全4言語対応)、DNS TXTクロス検証、スキーマバージョンバインディング(系統チェーン)に対応しています。これらの機能により、エージェント間の通信の真正性と完全性を確保し、セキュアな取引環境を実現できます。

description の原文を見る

Cryptographic tool schema verification to prevent MCP Rug Pull attacks — ECDSA P-256 signing, SHA-256 hashing, TOFU key pinning, .well-known discovery, signed revocation documents, and (v1.4-alpha across all four languages) signature expiration, DNS TXT cross-verification, and schema version binding (lineage chain)

SKILL.md 本文

SchemaPin 開発スキル ガイド

目的: このガイドは、AI アシスタントが暗号化ツール スキーマ検証のために SchemaPin をアプリケーションに迅速に統合するのに役立ちます。

詳細なドキュメント: README技術仕様、および各サブディレクトリ内の言語別 README を参照してください。

SchemaPin の機能

SchemaPin は、開発者がツール スキーマに暗号署名 (ECDSA P-256 + SHA-256) を施し、クライアントがスキーマが改ざんされていないことを検証できるようにすることで、"MCP Rug Pull" 攻撃を防ぎます。Trust-On-First-Use (TOFU) キー ピニングと RFC 8615 .well-known エンドポイントを公開鍵の検出に使用します。

ThirdKey トラスト スタックの一部: SchemaPin (ツール整合性) → AgentPin (エージェント ID) → Symbiont (ランタイム)


言語別クイックスタート

Python

pip install schemapin
from schemapin.crypto import KeyManager, SignatureManager
from schemapin.core import SchemaPinCore

# キーペアを生成
private_key, public_key = KeyManager.generate_keypair()

# スキーマに署名
core = SchemaPinCore()
canonical = core.canonicalize_schema(schema_dict)
signature = SignatureManager.sign_schema(private_key, canonical)

# 検証
is_valid = SignatureManager.verify_signature(public_key, canonical, signature)

JavaScript

npm install schemapin
import { KeyManager, SignatureManager, SchemaPinCore } from 'schemapin';

// キーペアを生成
const { privateKey, publicKey } = KeyManager.generateKeypair();

// スキーマに署名
const core = new SchemaPinCore();
const canonical = core.canonicalizeSchema(schema);
const signature = await SignatureManager.signSchema(privateKey, canonical);

// 検証
const isValid = await SignatureManager.verifySignature(publicKey, canonical, signature);

Go

go get github.com/ThirdKeyAi/schemapin/go@v1.3.0
import (
    "github.com/ThirdKeyAi/schemapin/go/pkg/core"
    "github.com/ThirdKeyAi/schemapin/go/pkg/crypto"
)

// キーペアを生成
km := crypto.NewKeyManager()
privKey, pubKey, _ := km.GenerateKeypair()

// スキーマに署名
spc := core.NewSchemaPinCore()
canonical, _ := spc.CanonicalizeSchema(schema)
sig, _ := crypto.NewSignatureManager().SignSchema(privKey, canonical)

// 検証
valid, _ := crypto.NewSignatureManager().VerifySignature(pubKey, canonical, sig)

Rust

[dependencies]
schemapin = "1.3"
use schemapin::crypto::{generate_key_pair, sign_data, verify_signature};
use schemapin::core::SchemaPinCore;

// キーペアを生成
let key_pair = generate_key_pair()?;

// 署名
let core = SchemaPinCore::new();
let canonical = core.canonicalize_schema(&schema)?;
let signature = sign_data(&key_pair.private_key_pem, &canonical)?;

// 検証
let is_valid = verify_signature(&key_pair.public_key_pem, &canonical, &signature)?;

コア概念

1. スキーマ正規化

スキーマは、ハッシング前に正規化 (ソート済みキーを使用した確定的 JSON シリアライゼーション) されます。これにより、同一のスキーマが常に同じハッシュを生成することが保証されます。キーの順序に関わらず。

2. .well-known ディスカバリー

開発者は公開鍵を https://example.com/.well-known/schemapin.json で公開します:

from schemapin.utils import create_well_known_response

response = create_well_known_response(
    public_key_pem=public_key_pem,
    developer_name="Acme Corp",
    schema_version="1.2",
    revocation_endpoint="https://example.com/.well-known/schemapin-revocations.json"
)

3. TOFU キー ピニング

最初の検証時に、開発者の公開鍵フィンガープリントが固定されます。その後の検証では、同じドメインに対して異なるキーを拒否します — キー置換攻撃を検出します。

4. 検証ワークフロー

オンライン (標準):

workflow = SchemaVerificationWorkflow(pin_store)
result = workflow.verify_schema(schema, signature, "https://example.com")

オフライン (v1.2.0 — HTTP は不要):

from schemapin.verification import verify_schema_offline, KeyPinStore

pin_store = KeyPinStore()
result = verify_schema_offline(
    schema, signature_b64, domain, tool_id,
    discovery_data, revocation_doc, pin_store
)

v1.2.0 の機能

スタンドアロン失効ドキュメント

運用プレイブック、すべての4言語、インライン + スタンドアロン統合セマンティクスを含む完全ガイド: docs/revocation.md

from schemapin.revocation import (
    build_revocation_document, add_revoked_key,
    check_revocation, check_revocation_combined, RevocationReason
)

doc = build_revocation_document("example.com")
add_revoked_key(doc, fingerprint, RevocationReason.KEY_COMPROMISE)
check_revocation(doc, some_fingerprint)  # 失効している場合は例外を発生

# 本番環境では、常に統合チェック (インラインリスト + スタンドアロン ドキュメント) を使用します:
check_revocation_combined(
    revoked_keys_list=discovery.revoked_keys,
    revocation_doc=doc,
    fingerprint=some_fingerprint,
)

トラスト バンドル (オフライン / エアギャップ)

インターネットがない環境用に、ディスカバリー + 失効データを事前にパッケージ化します:

from schemapin.bundle import SchemaPinTrustBundle

bundle = SchemaPinTrustBundle.from_json(bundle_json_str)
discovery = bundle.find_discovery("example.com")
revocation = bundle.find_revocation("example.com")

プラガブル ディスカバリー リゾルバー

from schemapin.resolver import (
    WellKnownResolver,    # HTTP .well-known ルックアップ
    LocalFileResolver,    # ローカル JSON ファイル
    TrustBundleResolver,  # インメモリ トラスト バンドル
    ChainResolver,        # ファーストマッチ フォールスルー
)

# チェーン: バンドルを最初に試し、HTTP にフォールバック
resolver = ChainResolver([
    TrustBundleResolver.from_json(bundle_json),
    WellKnownResolver(timeout=10),
])

リゾルバー ベースの検証

from schemapin.verification import verify_schema_with_resolver

result = verify_schema_with_resolver(
    schema, signature_b64, domain, tool_id,
    resolver, pin_store
)

v1.3.0 の機能

SkillSigner — ファイル ベースのスキル フォルダー署名

スキル ディレクトリ全体 (例: SKILL.md を含むフォルダー) に ECDSA P-256 で署名します。ファイルの横に .schemapin.sig マニフェストを生成し、ファイルが改ざんされていないことを証明します。

Python:

from schemapin.skill import sign_skill, verify_skill_offline

# スキル ディレクトリに署名
sig = sign_skill("./my-skill/", private_key_pem, "example.com")
# ./my-skill/ に .schemapin.sig を書き込みます

# オフラインで検証
from schemapin.verification import KeyPinStore
result = verify_skill_offline("./my-skill/", discovery_data, sig, revocation_doc, KeyPinStore())

JavaScript:

import { signSkill, verifySkillOffline } from 'schemapin/skill';

const sig = await signSkill('./my-skill/', privateKeyPem, 'example.com');
const result = verifySkillOffline('./my-skill/', discoveryData, sig, revDoc, pinStore);

Go:

import "github.com/ThirdKeyAi/schemapin/go/pkg/skill"

sig, err := skill.SignSkill("./my-skill/", privateKeyPEM, "example.com", "", "")
result := skill.VerifySkillOffline("./my-skill/", disc, sig, rev, pinStore, "")

Rust:

use schemapin::skill::{sign_skill, verify_skill_offline};

let sig = sign_skill("./my-skill/", &private_key_pem, "example.com", None, None)?;
let result = verify_skill_offline("./my-skill/", &disc, Some(&sig), rev.as_ref(), Some(&pin_store), None);

.schemapin.sig 形式

{
  "schemapin_version": "1.3",
  "skill_name": "my-skill",
  "skill_hash": "sha256:<root_hash>",
  "signature": "<base64_ecdsa_signature>",
  "signed_at": "2026-02-14T00:00:00Z",
  "domain": "example.com",
  "signer_kid": "sha256:<key_fingerprint>",
  "file_manifest": {
    "SKILL.md": "sha256:<file_hash>"
  }
}

改ざん検出

from schemapin.skill import detect_tampered_files, canonicalize_skill

_, current_manifest = canonicalize_skill("./my-skill/")
tampered = detect_tampered_files(current_manifest, sig.file_manifest)
# tampered.modified, tampered.added, tampered.removed

v1.4.0-alpha.2 の機能 (すべての4言語 — プレビュー)

スキーマ バージョン バインディング (schema_version + previous_hash)

.schemapin.sig 上の2つの付加的なオプショナル フィールドにより、パブリッシャーが系統を宣言し、ベリファイアーがそれを強制する方法を提供します。攻撃者が同じ名前の下で改ざんされたスキーマを置き換える rug-pull 置換に対して防御します。

Rust:

use schemapin::skill::{sign_skill_with_options, SignOptions, verify_chain};

let v1 = sign_skill_with_options(&dir_v1, &priv_pem, "example.com",
    SignOptions::new().with_schema_version("1.0.0"))?;

let v2 = sign_skill_with_options(&dir_v2, &priv_pem, "example.com",
    SignOptions::new()
        .with_schema_version("1.1.0")
        .with_previous_hash(&v1.skill_hash))?;

verify_chain(&v2, &v1)?;  // 純粋なメタデータ チェック; 両方はすでに暗号化検証されている必要があります。

Python:

from schemapin.skill import SkillSigner, SignOptions, verify_chain
v2 = SkillSigner.sign_with_options(dir_v2, priv_pem, "example.com",
    SignOptions(schema_version="1.1.0", previous_hash=v1["skill_hash"]))
verify_chain(v2, v1)

JavaScript:

import { signSkillWithOptions, verifyChain } from 'schemapin';
const v2 = signSkillWithOptions(dirV2, privPem, 'example.com',
    { schemaVersion: '1.1.0', previousHash: v1.skill_hash });
verifyChain(v2, v1);

Go:

v2, _ := skill.SignSkillWithOptions(dirV2, privPEM, "example.com", skill.SignOptions{
    SchemaVersion: "1.1.0",
    PreviousHash:  v1.SkillHash,
})
err := skill.VerifyChain(v2, v1)

VerificationResultschema_versionprevious_hash フィールドを獲得します — ベリファイアーはこれらを情報として表示します。チェーン強制は verify_chain (または言語相当) を通じてオプトインです。ChainError は2つの障害モード を区別します: no_previous_hash (現在の署名がフィールドを欠いている) と mismatch (両方存在するが不相等 — 置換の可能性)。

完全ガイド: docs/schema-version-binding.md


v1.4.0-alpha.1 の機能 (すべての4言語 — プレビュー)

両方の機能は 付加的なオプショナル フィールド/レコード です: v1.3 ベリファイアーはそれらを無視し、これらのフィールドなしの v1.4 署名は v1.3 と同一に動作します。Python、JavaScript、および Go ポートは、v1.4.0 リリース前の後続のアルファで続きます。

署名有効期限 (expires_at)

.schemapin.sig 上のオプショナル ISO 8601 / RFC 3339 タイムスタンプ。ベリファイアーがタイムスタンプを過ぎると、結果が低下します (警告) 失敗の代わりに — validtrue のままで、expiredtrue になり、signature_expired 警告が追加されます。

use schemapin::skill::{sign_skill_with_options, SignOptions, verify_skill_offline};

// 180 日の TTL で署名 — .schemapin.sig に expires_at を書き込みます
let opts = SignOptions::new().with_expires_in(chrono::Duration::days(180));
let sig = sign_skill_with_options(dir, &priv_pem, "example.com", opts)?;

// 検証 — expires_at を過ぎると valid=true で expired=true と
// "signature_expired" 警告を返します。ハード失敗は決してありません
let result = verify_skill_offline(dir, &discovery, None, None, None, Some("tool"));
if result.expired {
    log::warn!("signature past {}", result.expires_at.unwrap_or_default());
}

SignOptions はビルダーです; レガシー sign_skill(...) 関数は v1.3 呼び出し元のために保持され、expires_at なしで署名を書き込みます (依然として schemapin_version: "1.3" として広告)。

DNS TXT クロス検証 (_schemapin.{domain})

ツール プロバイダーは .well-known/schemapin.json の横に TXT レコードを公開 できます:

_schemapin.example.com.  IN TXT  "v=schemapin1; kid=acme-2026-04; fp=sha256:a1b2c3..."

ディスカバリー キーに対して TXT をクロスチェックすることで、セカンド チャネル 検証を与えます — DNS 認証チェーンは HTTPS ホスティング チェーンから独立しています。不一致はハード失敗です (DOMAIN_MISMATCH); レコードがない場合はノーオペレーションです。

use schemapin::dns::{parse_txt_record, fetch_dns_txt};
use schemapin::skill::verify_skill_offline_with_dns;

// パーサー/マッチャーは常に利用可能です
let txt = parse_txt_record("v=schemapin1; fp=sha256:a1b2c3...")?;

// 非同期フェッチは `dns` Cargo フィーチャー (hickory-resolver) の背後に存在します
#[cfg(feature = "dns")]
let txt = fetch_dns_txt("example.com").await?;

let result = verify_skill_offline_with_dns(
    dir, &discovery, None, None, None, Some("tool"), txt.as_ref(),
);
Cargo フィーチャーデフォルト含まれるもの
fetchオフreqwest, tokio, async-trait
dns (新規)オフhickory-resolver, tokio, async-trait

サーバー側のセットアップ

.well-known エンドポイントの公開

Python CLI ツールが含まれています:

# キーペアを生成
schemapin-keygen --output-dir ./keys

# スキーマに署名
schemapin-sign --key ./keys/private.pem --schema schema.json

# 署名を検証
schemapin-verify --key ./keys/public.pem --schema schema.json --signature sig.b64

Go CLI 相当物も利用可能です (go install github.com/ThirdKeyAi/schemapin/go/cmd/...@v1.3.0)。


アーキテクチャ

開発者                             クライアント (AI プラットフォーム)
─────────────────────────────────────────────────────────────
1. ECDSA P-256 キーペアを生成
2. 公開鍵を                         3. 公開鍵を
   /.well-known/schemapin.json        /.well-known/schemapin.json
   で公開                             から検出
4. ツール スキーマに署名           5. 署名を検証
   (正規化 → SHA-256                  (正規化 → SHA-256
    → ECDSA 署名)                      → ECDSA 検証)
                                    6. キー フィンガープリントを TOFU ピン
                                    7. 失効状態をチェック

言語別 API リファレンス

操作PythonJavaScriptGoRust
キー生成KeyManager.generate_keypair()KeyManager.generateKeypair()km.GenerateKeypair()generate_key_pair()
スキーマ署名SignatureManager.sign_schema()SignatureManager.signSchema()sm.SignSchema()sign_data()
署名検証SignatureManager.verify_signature()SignatureManager.verifySignature()sm.VerifySignature()verify_signature()
正規化SchemaPinCore().canonicalize_schema()new SchemaPinCore().canonicalizeSchema()spc.CanonicalizeSchema()SchemaPinCore::new().canonicalize_schema()
キー検出PublicKeyDiscovery.fetch_well_known()PublicKeyDiscovery.fetchWellKnown()FetchWellKnown()WellKnownResolver (fetch フィーチャー)
オフライン検証verify_schema_offline()verifySchemaOffline()VerifySchemaOffline()verify_schema_offline()
リゾルバー検証verify_schema_with_resolver()verifySchemaWithResolver()VerifySchemaWithResolver()verify_schema_with_resolver()
スキル フォルダー署名sign_skill()signSkill()skill.SignSkill()sign_skill()
スキル検証verify_skill_offline()verifySkillOffline()skill.VerifySkillOffline()verify_skill_offline()
改ざん検出detect_tampered_files()detectTamperedFiles()skill.DetectTamperedFiles()detect_tampered_files()

テスト

# Python
cd python && python -m pytest tests/ -v

# JavaScript
cd javascript && npm test

# Go
cd go && go test ./...

# Rust
cd rust && cargo test

AI アシスタントのための Pro ヒント

  1. 常に正規化してから 署名または検証します — 生の JSON 比較は失敗します
  2. 事前取得されたディスカバリー データがある場合はオフライン検証を使用します — スキーマ検証中の HTTP コールを回避します
  3. トラスト バンドルは CI/CD およびエアギャップ デプロイメントに理想的です
  4. ChainResolver でリゾルバーをレイアー化できます: バンドル → ローカル ファイル → HTTP としてフォールバック
  5. TOFU ピニングは ドメイン用に見られた最初のキーが信頼されることを意味します — キー変更時はユーザーに警告します
  6. すべての言語は同じ暗号を使用します — ECDSA P-256 + SHA-256、したがってクロス言語検証が機能します
  7. 失効チェックは 常に実行されるべきです — シンプルなリストとスタンドアロン ドキュメント両方
  8. SkillSigner はディレクトリ全体に署名します — ClaWHub などのレジストリにアップロードされた SKILL.md フォルダーに理想的です
  9. .schemapin.sig はハッシング から自動的に除外されます — 古い署名を削除せずにディレクトリを再署名できます

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
ThirdKeyAI
リポジトリ
ThirdKeyAI/SchemaPin
ライセンス
MIT
最終更新
2026/5/8

Source: https://github.com/ThirdKeyAI/SchemaPin / ライセンス: MIT

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: ThirdKeyAI · ThirdKeyAI/SchemaPin · ライセンス: MIT