SIGABA-EX

使用上の注意点・採用アルゴリズム
← 暗号化ツールに戻る

SIGABA-EXとは?

SIGABA-EXは、第二次世界大戦期の暗号機SIGABAへの敬意を受け継ぎ、その先を 目指して開発した現代の暗号通信端末です。

「EX」には、3つの意味を込めています。

歴史への敬意、技術の発展、そして人と人との安全な通信。その3つを一つの 名前に込めています。

この暗号ツールを使用する際の注意点

SIGABA-EXは、学習・個人利用を目的とした暗号化ツールです。ブラウザ内だけで 暗号化・復号化が完結し、平文・暗号文・鍵コードのいずれもサーバーへ送信・ 保存されません。安心してお使いいただくために、採用しているアルゴリズムと、 あらかじめ知っておいていただきたい限界をこのページにまとめます。

このツールはHTTPS(またはlocalhost)でのみ動作します。
暗号化・復号化にはブラウザ標準のWeb Crypto API(crypto.subtle)を使用しており、これはブラウザの仕様上、HTTPSで配信されたページでしか利用できません。平文HTTPで開いた場合はエラーメッセージが表示され、処理が中止されます。

2つの鍵方式

SIGABA-EXは、用途に応じて選べる2つの鍵方式を提供しています。

合言葉モード(既定・FORMAT_VERSION 7)乱数鍵モード(FORMAT_VERSION 8)
鍵の形式 人間が読める半角英数16〜32文字 256bitの完全ランダム値(Base64URL・43文字)
鍵導出 PBKDF2-HMAC-SHA256(400,000回反復)を経由してAES-256-GCM鍵を導出 経由しない。生成した256bitの乱数をそのままAES-256-GCM鍵としてインポートする
鍵空間 文字列の長さ・種類に依存(総当たり耐性はPBKDF2の反復回数に頼る) 常に256bit(原理的に最大。鍵導出のステップ自体が存在しないため、反復回数の妥当性という論点自体がない)
向いている場面 鍵を対面・電話など口頭ベースで伝える場合 鍵自体をテキストとして安全な経路(パスワードマネージャー等)で受け渡しできる場合

復号時はモードを意識する必要がありません。 暗号文のヘッダに埋め込まれたバージョン番号(マスクされた状態で格納) から、どちらのモードで暗号化されたかを自動的に判別します。利用者は、 受け取った鍵の値(合言葉、またはBase64URL形式の乱数鍵)を そのまま「鍵」欄に貼り付けるだけで復号できます。

この機能を追加した経緯:ネット上の他の暗号化ツールには、 パスワードを経由せず256bitの完全ランダム鍵をブラウザで直接生成する 方式を採用しているものがあります。この方式は、PBKDF2でどれだけ強化 しても有限の文字列空間に留まる合言葉モードよりも、鍵空間という 観点では原理的に優れています。SIGABA-EXでも、合言葉モードの 使いやすさ(口頭・電話で伝えられる)を維持しつつ、より高い鍵強度を 求める利用者向けの選択肢として、この方式を追加のオプションとして 用意しました。

「生成ボタンでしか作れない」制限は、セキュリティ境界ではありません。
乱数鍵モードでは、画面上「乱数鍵生成」ボタンで作った値以外は暗号化に使えないようになっています。ただし、これはあくまで「弱い鍵を自分で考えて打ち込んでしまう」という誤操作を防ぐためのUI上の配慮であり、暗号学的なセキュリティ境界ではありません。実装は、直近で生成ボタンが作った値をJavaScriptの変数として保持し、暗号化時に入力欄の値と一致するかを照合しているだけです。ブラウザの開発者ツールを使えば、この照合は誰でも数秒で回避できます。守ろうとしているのは「攻撃者からの防御」ではなく「利用者自身のうっかりミス」である点を理解した上でお使いください。なお、この制限は乱数鍵モードのみに適用されており、合言葉モードでは引き続き任意の16〜32文字を自由に手入力できます。

採用アルゴリズム

用途アルゴリズム備考
鍵導出(合言葉→AES-256-GCM用鍵) PBKDF2-HMAC-SHA256, 400,000回反復(crypto.subtleのPBKDF2で直接鍵を導出) 合言葉モードのみ。ソルトは暗号化のたびにランダム生成(16byte)。事前計算(レインボーテーブル)攻撃の使い回しを防ぐ
鍵のインポート(乱数鍵モード) 256bitの乱数をcrypto.subtle.importKeyで直接AES-256-GCM鍵として使用 PBKDF2を経由しない。鍵そのものが既に最大エントロピーのため、鍵導出による強化が不要
暗号化+改ざん検知 AES-256-GCM(NIST標準AEAD、crypto.subtleネイティブ実装) 暗号化と認証を1つの標準構成で行う。両モード共通
ヘッダマスク用ハッシュ SHA-256(crypto.subtle.digest) 秘密鍵は使わない(下記参照)
乱数源 crypto.getRandomValues(Web Crypto API)のみ 利用できない端末・ブラウザでは、弱い乱数へフォールバックせず処理を中止する
ノンスの生成方式 AES-GCMの96bitノンスを暗号化のたびにcrypto.getRandomValuesで生成 カウンタ管理はしていない(下記「既知の限界」を参照)
暗号文表現 ヘッダをBase36・本文をBase62 半角英数字のみで構成し、コピー&ペーストしやすくするため
ヘッダの識別性対策 version+長さ(5byte)をソルト由来のマスクでXOR 短文では固定パターン(例:毎回同じ先頭文字列)が出ないようにし、どのツールで暗号化したかの推測を難しくする
平文の長さの秘匿(パディング) 暗号化前に平文を256byte単位にパディング(ISO/IEC 7816-4方式) 短いメッセージと少し長いメッセージが同じ長さの暗号文になり、内容を知らない第三者が長さから文脈を推測する難易度を上げる(下記参照)

v7での変更点:v6までは、平文をそのままAES-256-GCMで暗号化して いました。AES-GCMは平文と同じ長さの暗号文を生成するストリーム暗号モード のため、暗号文の長さから平文のバイト数がほぼそのまま推測できてしまう という弱点がありました(後述の「既知の限界」で以前から明記していました)。 v7では、暗号化前の平文を256byte単位にパディングしてから暗号化することで、 この弱点を緩和しています。例えば「はい」のような数バイトの短文も、それ より長い数十〜100文字程度の文章も、同じ1ブロック分の暗号文の長さに なります。ただし、これは完全な秘匿ではなく「長さの粒度を粗くする」 対策である点に注意してください。256byteを超える長文では、依然として おおよそ何ブロック分(256byte区切り)かは暗号文の長さから推測できます。

v6での大きな変更点:v5まではChaCha20-Poly1305 AEADをこの プロジェクト独自にJavaScriptで実装していました。RFC準拠であることや Node.js組み込み実装との出力一致はテストで確認していましたが、それでも 「ブラウザベンダーが実装・監査しているネイティブコードと同等に信頼できるか」 という点では見劣りするという指摘がありました。v6では、鍵導出(PBKDF2)・ 暗号化+認証(AES-256-GCM)・ヘッダマスク用のハッシュ(SHA-256)の すべてを、ブラウザ・Node.js共通のWeb Crypto API(crypto.subtle)に 置き換えています。これにより、暗号処理の実体はブラウザベンダー (Chromium/Firefox/WebKit)が実装・監査しているネイティブコードが担う ことになり、このプロジェクト固有の自前実装(PBKDF2/HMAC/SHA-256/ ChaCha20/Poly1305の手書きJS実装)はコードベースから完全に削除しました。 復号時は必ずタグを検証し、検証に失敗した場合(鍵違い・改ざん・破損の いずれか)は平文を画面に出力しません。

Webセキュリティ強化(v8)

暗号アルゴリズム自体は既に十分な強度に達していると判断し、v8では 「暗号システム全体を堅牢化する」観点から、Webアプリケーションとしての 土台部分を強化しました。暗号の中身がどれだけ強くても、XSS等で鍵や 平文が盗聴されてしまえば意味がないため、これは暗号強化と並んで 重要な対策です。

対策内容設定方法
CSP(Content-Security-Policy) script-src/style-srcを'self'のみに限定し、'unsafe-inline'は一切許可しない HTMLの<meta>タグ、および_headers(Cloudflare Pages)/.htaccess(Apache系ホスト)
HSTS(Strict-Transport-Security) HTTPSでの接続を強制し、HTTPへのダウングレードを防ぐ _headers/.htaccessのみ(HTTPレスポンスヘッダでしか設定できない仕様のため)
SRI(Subresource Integrity) 該当なし。外部CDN・外部スクリプトを一切使用しておらず、すべてのリソースを自ドメインから配信しているため、SRIを付与する対象自体が存在しない -
X-Frame-Options / frame-ancestors 他サイトへの埋め込み(クリックジャッキング対策) _headers/.htaccessのみ(frame-ancestorsは<meta>タグでは効果を持たない仕様のため)
X-Content-Type-Options MIMEスニッフィング対策 _headers/.htaccess
Referrer-Policy no-referrer。リファラー経由の情報送出を最小化 _headers/.htaccess
Permissions-Policy カメラ・マイク・位置情報など、このツールが使わないブラウザ機能を明示的に無効化 _headers/.htaccess

SIGABA-EXは2種類のヘッダー設定ファイルを同梱しています。デプロイ先に 応じて、該当する方が自動的に使われます(両方置いておいても問題 ありません。使われない方は単に無視されます)。

ヘッダー設定の確実性という観点では、Cloudflare Pagesでの運用を推奨します。
CSPの主要部分(script-src/style-src等)はHTML側の<meta>タグでも併せて設定しているため、.htaccessが効かない環境でも最低限の防御は機能しますが、反映状況はブラウザの開発者ツール(ネットワークタブ→レスポンスヘッダ)で確認することをおすすめします。

既知の限界

想定する利用シーン

個人間・小規模チーム内での、学習目的や日常的なメモ・メッセージの簡易的な 保護を想定しています。暗号化・改ざん検知そのものはAES-256-GCMという NIST標準AEADに、ブラウザネイティブの実装(crypto.subtle)を 通じて委ねていますが、鍵導出方式(ランダムソルト、反復回数400,000回)や 暗号文のヘッダ構造はこのプロジェクト独自の設計です。国家レベルの攻撃者や 高度な標的型攻撃からの保護、法令上の機密情報保護義務がある用途には 使用しないでください。そのような用途には、監査済みの商用・OSSライブラリ の利用を検討してください。

使い方

  1. 画面上部で鍵の方式を選びます。合言葉モード (既定)では、人間が読める半角英数16〜32文字の鍵を「合言葉」欄に 入力します(「合言葉生成」ボタンでも生成できます)。 乱数鍵モードに切り替えると、256bitの完全 ランダムな鍵(Base64URL・43文字)を「乱数鍵生成」ボタンで生成 できます(誤って弱い鍵を打ち込んでしまわないよう、乱数鍵モードは 生成ボタンで作った値のみ暗号化に使えます)。
  2. 左側の「平文 → 暗号文」パネルに文章を入力し、「暗号化」を押します。
  3. 生成された暗号文を、鍵を共有した相手にコピーして送ります。
  4. 相手は同じ鍵を入力し、右側の「暗号文 → 平文」パネルに暗号文を貼り付けて 「復号化」を押すと、平文が復元されます(復号時は鍵の方式を選ぶ必要は ありません。暗号文のヘッダから自動的に判別されます)。

鍵が違う場合や、暗号文が途中で改ざん・破損した場合は、タグ検証エラーとして 表示され、平文は復元されません。

合言葉や乱数鍵は暗号文と一緒に相手に送らないでください。
暗号文をLINEやメールで送る場合でも、合言葉や乱数鍵は対面で伝える、電話など別の通信経路を利用するなど、暗号文とは異なる経路で安全に共有してください。

このページの内容は、リポジトリ内の技術文書(SECURITY.md)と同じものです。 サーバーの設定によっては.mdファイルを直接開くと文字化けする場合があるため、 このページ(HTML)を正式な閲覧先としてご利用ください。