
安全なターミナルチャット。 E2E暗号化、ゼロメタデータのブラインドフォワーダーサーバー。 PyNaCl XSalsa20-Poly1305 + Ed25519 + forward secrecy。 クロスプラットフォーム Python。
エンドツーエンド暗号化されたグループチャット、プライベートメッセージ、ファイル転送をターミナルで。サーバーはブラインドフォワーダーです:メッセージを読むことができず、ユーザー名を知らず、参加しているルームを知らず、たとえ完全に侵害されても、同じ人物からの2つのメッセージを関連付けることができません。
https://github.com/user-attachments/assets/d9faabfb-73bd-46dd-92b2-23f63daf5b06
https://github.com/user-attachments/assets/e8e0220d-cd7d-45a2-9443-9a5f20b57f12
https://github.com/user-attachments/assets/15fb383d-a02a-433e-bbd9-8ebadecf9481
https://github.com/user-attachments/assets/bca10cb1-6959-425d-96d6-fc1fbf845538
NoEyesは、信頼できる少人数グループ向けのPythonターミナルチャットツールです。サーバーは決して何も復号化せず、あなたの身元を知ることもありません - 不透明なトークンを処理し、暗号化されたバイトを転送するだけです。
あなたが鍵を生成し、帯域外で共有すれば、サーバーはあなたの会話について何も知ることはありません。
第三者サーバーを信頼せずに暗号化通信を望む信頼できる少人数グループ、真のエンドツーエンド暗号化でプライベートチャットをセルフホスティングしたい方、またはサーバーが何を見ることができて何を見ることができないかを正確に理解したい方に役立ちます。
| 機能 | 詳細 |
|---|---|
| ゼロメタデータサーバー | サーバーはユーザー名、ルーム名、公開鍵を決して見ず、不透明なトークンのみ扱う |
| シールドセンダー | 送信者の身元は暗号化ペイロード内にあり、ルーティングヘッダーには決して含まれない |
| ブラインドフォワーダーサーバー | 復号化はゼロ、サーバーは読み取れない暗号化ブロブを転送する |
| 前方秘匿性 | /ratchet start — Sender Keysプロトコル、各メッセージは一意の派生鍵で暗号化され、現在の鍵が漏洩しても過去のメッセージは安全 |
| グループチャット | ルームごとにBLAKE2bで派生したXSalsa20-Poly1305鍵、ルームは暗号的に分離 |
| プライベートメッセージ | 最初の接触時にX25519 DHハンドシェイク、ペアワイズ鍵は二者のみが保持 |
| ファイル転送 | ChaCha20-Poly1305ストリーミング、任意のサイズ、低RAM使用、再接続時の一時停止/再開 |
| Ed25519アイデンティティ | 自動生成された署名鍵、すべてのメッセージとファイルは署名される |
| TOFU | 初回に見た鍵を信頼;鍵の不一致は目に見えるセキュリティ警告を引き起こす |
| ランダムPBKDF2ソルト | 各デプロイは一意のランダムソルトを取得し、レインボーテーブルは無効 |
| TLS + 証明書ピンニング | トランスポートは暗号化、サーバー証明書は初回接触時にTOFUでピン留め |
| リプレイ保護 | ルームごとのメッセージIDデック、再生されたフレームは静かにドロップ |
| 分割サイドバーパネル | ルーム(上)とユーザー(下)は常に表示、各半分は独立してスクロール |
| CRT起動アニメーション | 起動時にサウンド付きのフルスクリーン蛍光体効果 |
| ラチェット起動アニメーション | 点字ギアアート、グリッチフリッカー、スポットライトスイープ、同期されたSFX、TUIクロムが赤に遷移するフルスクリーンCRT効果 |
| ガイド付きランチャー | 矢印キーメニューUI、コマンドラインの経験は不要 |
| 自動依存関係インストーラ | プラットフォームを検出し、不足しているものをインストールし、変更前に確認を求める |
python ui/setup.py
python ui/launch.py
`ui/launch.py` は、サーバーを起動するか、既存のサーバーに接続する手順を案内します。
---
### オプション B - Python がまだインストールされていない場合
| プラットフォーム | 最初に実行するもの |
|---|---|
| Linux / macOS / Termux / iSH | `sh install/install.sh` |
| Windows | `install\install.bat` |
どちらのスクリプトも、Python が不足している場合はインストールし、自動的に `setup.py` に処理を引き継ぎます。
---
### オプション C - 手動```bash
# 1. Install dependencies
pip install cryptography PyNaCl
# 2. On the server machine — generate the access key
python noeyes.py --generate-access-key
# Prints an access code hex string — share with clients via USB
# 3. On a client machine — generate chat.key from the access code
python noeyes.py --generate-chat-key <ACCESS_CODE_HEX> --key-file ./chat.key
# Distribute chat.key to all other clients via USB. Never put it on the server.
# 4. Start the server (does NOT need the key file)
python noeyes.py --server --port 5000
# Start without bore tunnel (LAN / static IP / custom tunnel)
python noeyes.py --server --port 5000 --no-bore
# Start without adding a firewall rule (not needed when using bore tunnel)
python noeyes.py --server --port 5000 --no-firewall
# 5. Connect clients - each person needs their own identity file
python noeyes.py --connect SERVER_IP --port 5000 --username alice --key-file ./chat.key --identity-path ~/.noeyes/identity_alice.key
python noeyes.py --connect SERVER_IP --port 5000 --username bob --key-file ./chat.key --identity-path ~/.noeyes/identity_bob.key
重要: 各ユーザーは独自のIDファイルを持たなければなりません。2人のクライアントが同じIDファイルを共有すると、同じ受信トレイトークンが取得され、重複セッションとしてサーバーに拒否されます。IDファイルは初回実行時に自動生成されます。ユーザーごとに一意の
--identity-pathを指定してください。
Termux は F-Droid(推奨)からダウンロード:https://f-droid.org/packages/com.termux/
セッションを維持 - tmux をインストールして、アプリを切り替えても NoEyes が実行され続けるようにします:```bash pkg install tmux -y tmux python ui/launch.py
**ストレージ権限** - これがないとファイル転送は失敗します:```bash
termux-setup-storage
| コマンド | 説明 |
|---|---|
/help | すべてのコマンドを表示 |
/quit | 切断して終了 |
/clear | 画面からメッセージを消去 |
/users | 現在のルームのユーザーを一覧表示 |
/join <room> | ルームに切り替え(アクティブなラチェットがある場合は警告) |
/leave | 一般ルームに戻る(アクティブなラチェットがある場合は警告) |
/msg <user> <text> | E2E暗号化されたプライベートメッセージを送信 |
/send <user> <file> | 暗号化ファイルを送信 |
/whoami | 自分のアイデンティティフィンガープリントを表示 |
/trust <user> | ユーザーが再インストール後に新しいキーを信頼する |
/notify on|off | 通知音の切り替え |
/ratchet start | 転送秘密性のローリングキーをすべてのルームメンバーに提案(全員が確認する必要あり) |
/ratchet invite <u> | ユーザーが再参加した後にラチェットに再招待(フル再起動をトリガー、チェーンキーは転送されません) |
/proceed | 移行待機中、オフラインのピアをドロップして再開する投票 |
| キー | アクション |
|---|---|
↑ / ↓ | チャットを上下にスクロール |
PgUp / PgDn | チャットを1ページスクロール |
^P (Ctrl+P) | サイドバーパネルの表示/非表示 |
^C | 終了 |
▶で強調表示。各半分は独立してスクロールします。**^P**を押すとパネルを非表示にして全幅チャットビューを表示します。
メッセージの先頭に!tagを付けると、全員に対して色を付け、通知音をトリガーします。タグは暗号化ペイロード内部で伝送され、サーバーがそれらを見ることはありません。
| タグ | 色 | 使用目的 |
|---|---|---|
!ok <msg> | 🟢 緑 | 成功、確認、完了 |
!warn <msg> | 🟡 黄 | 警告、注意 |
!danger <msg> | 🔴 赤 | 重大、緊急、緊急時 |
!info <msg> | 🔵 青 | ステータス更新、参考情報 |
!req <msg> | 🟣 紫 | リクエスト、アクションが必要 |
!? <msg> | 🩵 シアン | 質問、意見を求める |
例:``` !danger server is going down in 5 minutes !ok deployment successful !req can someone review my PR?
サウンドは `sfx/` フォルダから再生されます。タグ名に対応する `.wav`、`.mp3`、`.ogg`、`.aiff`、`.flac`、または `.m4a` ファイルを配置します(例:`sfx/danger.wav`)。見つからない場合はターミナルベルにフォールバックします。全サウンドを無効にするには `/notify off` を使用します。
---
## アーキテクチャ
> 🗺️ **[ライブインタラクティブセキュリティマップ](https://ymsniper.github.io/NoEyes/)** — 完全な暗号化アーキテクチャ、脅威モデル、ゼロメタデータルーティングのビジュアルな内訳をインタラクティブなダイアグラムで提供します。```
┌──────────────────────────────────────────────────────────────────────┐
│ Alice ──────────────────────────────────────────── Bob │
│ │ Encrypted payload (opaque) │ │
│ │ │ │ │
│ └────────────► SERVER ─┴◄──────────────────────────┘ │
│ │ │
│ Zero-metadata blind forwarder: │
│ routes by opaque inbox tokens only │
│ { "to": "3f9a1c...", "type": "privmsg" } │
│ forwards encrypted bytes verbatim │
└──────────────────────────────────────────────────────────────────────┘
WHAT THE SERVER SEES: WHAT THE SERVER NEVER SEES:
· Encrypted bytes it can't read · Usernames or display names
· Opaque inbox tokens (blake2s) · Room names
· Opaque room tokens (blake2s) · Who is messaging whom
· Frame byte length · Message content
· Connection timing · File contents
· Ed25519 public keys
· DH key exchange values
接続前に各クライアントは、ローカルで2つの不透明なトークンを計算します。``` inbox_token = blake2s(identity_vk_bytes, digest_size=16) room_token = blake2s((room_name + group_key_hex).encode(), digest_size=16)
サーバーはこれらのトークンのみで全てのフレームをルーティングします。表示名、ルーム名、公開鍵を保存することはありません。送信者の身元はルーティングヘッダーではなく、暗号化されたペイロード(シールド送信者)**の中を**伝わります。