# 技術プロトタイプ検証結果

2026-10-27。**Pillowによるチャネル模擬試験。iPhone実機スクリーンショット試験は未実施。**

## 判定と試験データ

成功は「AES-GCM認証成功、全文一致」。不成功も分母に含めた。全フレームが136バイト固定なので、50文字版が100文字版より強いECCを使うわけではない。

画像は3種類：実写真1枚（Grace Hopperの肖像、中央4:3、512×384）と、合成の滑らかな画像・細かい模様の画像の2枚。多数の独立した実写真を代表する母集団ではない。試行間では文・ランダムsalt・nonce・paddingを変えた。方式比較では2フレーム（50/100文字各1）、追加試験では10フレームを使い、うち2フレームを共通とした。試験ベクトルは`tests/vectors.json`に保存。

Node v24.22.1 / Python 3.12 / Pillow 12.3.0 / NumPy。元RGBと8bit丸め・クリップ後のRGBを比較。縮小・拡大はPillow BICUBIC。各変換後に512×384へ戻して復号。元写真からの差分を使わないblind extraction。

## 方式・強度比較

50/100文字 × 各1試行 × 3画像 × 10変換 = 各設定60条件、計540条件。総成功数はこの特定の変換群に対するもので、実利用の成功確率ではない。平均PSNRは埋め込み前後の512×384 RGB画像で計算。

|方式|強度|全10変換での成功|171px縮小での成功|平均PSNR dB|
|---|---:|---:|---:|---:|
|DCT低周波|32|51/60|2/6|33.9|
|DCT低周波|48|58/60|4/6|32.1|
|DCT低周波|64|58/60|4/6|30.6|
|DCT中周波|32|58/60|4/6|38.0|
|DCT中周波|48|58/60|4/6|35.2|
|DCT中周波|64|59/60|5/6|33.1|
|画素ブロック差分|32|50/60|2/6|34.4|
|画素ブロック差分|48|58/60|4/6|32.4|
|画素ブロック差分|64|58/60|4/6|30.9|

この限定条件では中周波DCTが画質と復元の両面で有望だった。標準候補は**中周波DCT・強度48**とした。強度64はより高い復元数になったが視覚変化も増える。PSNRのみから「見えない」と判定していない。

## 標準候補の追加試験

中周波DCT・強度48。50/100文字 × 各5試行 × 3画像 × 10変換 = 300条件。下表の各分母15は5フレーム×3画像、合計30は50/100文字の合算。

|模擬変換|50文字|100文字|合計|
|---|---:|---:|---:|
|元PNG相当・無変換|15/15|15/15|30/30|
|343×257→512×384|15/15|15/15|30/30|
|256×192→512×384|15/15|15/15|30/30|
|171×128→512×384|10/15|10/15|20/30|
|各辺1px切出し→正規化|15/15|15/15|30/30|
|輝度1.1倍|15/15|15/15|30/30|
|JPEG品質85|15/15|15/15|30/30|
|JPEG品質60|15/15|15/15|30/30|
|343×257 + JPEG品質75|15/15|15/15|30/30|
|343 CSS px・DPR 3相当・既知範囲切出し|15/15|15/15|30/30|

画像ごとの平均PSNRと強い縮小の結果：

|画像|平均PSNR dB|171×128での成功|
|---|---:|---:|
|portrait|34.0|0/10|
|smooth|37.3|10/10|
|texture|34.5|10/10|

DPR 3相当の条件は、1125×2436の合成画面に1029×771の写真を貼り、既知の正確な座標で切り出したもの。375×812 CSS pxの画面に343×257 CSS pxの写真を置く仮定であり、iPhone 13 miniから取得した画像ではない。

各辺1pxの切出し試験で今回成功しても、任意の範囲ずれに対応したことにはならない。自動検出や部分欠けの復元も実装していない。171pxへ強く縮小する条件の失敗から、画像の物理画素数と画像特徴が重要であることが分かる。

## 自動試験

`npm test`の4試験を通過：全割当文字・長さ・未対応文字、畳み込み符号の手計算インパルス列と孤立誤り、AES-GCMのランダム性・誤合言葉・フレーム各領域の改変拒否、3方式の8bit RGB抽出。ECCに任意の一定誤り率での訂正保証は置かない。

## ブラウザー試験

公開先 `https://kakure.pages.dev` を接続Chromeで操作し、以下を確認した。端末実機試験ではない。

|操作・条件|50文字|100文字|
|---|---|---|
|サンプル写真で作成・保存前の認証復号|成功|成功|
|PNG相当・無変換|成功|成功|
|343×257へ縮小|成功|成功|
|256×192へ縮小|成功|成功|
|171×128へ縮小|失敗|失敗|
|JPEG品質85%|成功|成功|
|JPEG品質60%|成功|成功|
|343×257 + JPEG品質75%|成功|成功|
|343 CSS px・DPR 3相当の再補間|成功|成功|
|「この画像を読み解く」経由の受信画面で全文復元|成功|成功|

各条件は各1回、同じサンプル写真。100文字では通常のかな文・句読点・かぎ括弧も使った。送信と受信の間で文章を参照せず画像から再抽出し、合言葉で認証する。50文字画像は誤った合言葉で拒否され、平文が表示されないことも確認。Chromeのエラーログは0件。オフライン用キャッシュの準備完了表示を確認。

100文字作成・受信は375×812を指定したレスポンシブ表示でも操作した（記録画像は360×812。iPhoneの再現ではない）。[認証復号の操作画面](browser-check.jpg)を保存。

ブラウザー操作用接続ではPNGのダウンロード完了イベントを取得できなかったため、**保存ファイルの再選択、写真ファイル入力、完全オフライン再起動は今回のブラウザーQAでは未確認**。PNG Blobの生成と保存リンク、受信画面への直接引き渡し・復号は確認した。iPhoneの保存・再読込も実機検証に含める。Pillow結果とブラウザー結果は混ぜない。

## 生データと再現

- [方式比較540条件 CSV](results-comparison.csv)
- [標準候補300条件 CSV](results-default.csv)
- `tests/vectors.json`：試験用のかな文と暗号フレーム。合言葉は`KAKUREGA benchmark only`。
- `npm run bench` / `node tests/benchmark.mjs --full`

CSVの`rawBER`は既知の送信ビットと比較したECC前の誤り率。`pilot`は既知同期信号の一致率。いずれも全文復元率の代用ではない。`extractMs`には再復号確認が成功した条件では鍵導出・GCM処理も含むため、純粋なDSP処理時間の比較には使わない。

次は[実機検証手順](TEST_PLAN.md)に従い、iPhone 13 miniと独立した複数写真で測る。
