QR コードの内部:バージョン・モジュール・エンコードモード
QR コード(ISO/IEC 18004)にはバージョンと呼ばれる 40 のサイズがあります。バージョン 1 は 21×21 のモジュール(白黒の正方形)グリッドで、バージョンが 1 上がるごとに 1 辺 4 モジュールずつ増え、バージョン 40 では 177×177 になります。データが増えるほどバージョンが上がり、同じ印刷サイズならモジュールが小さくなり、スキャンは難しくなります。大きな正方形 3 つはファインダーパターン、小さいものはアライメントパターン、ファインダー間の交互の線はタイミングパターンです — いずれもデータは持たず、どれも隠してはいけません。
容量はセグメントごとに自動選択されるエンコードモードに依存します。数字モードは 3 桁を 10 ビットに、英数字モードは 2 文字を 11 ビットに詰めますが 45 文字集合(数字、大文字 A〜Z、空白、$ % * + - . / :)のみ対応。バイトモードは 1 バイトにフル 8 ビットを使い、テキストは事実上 UTF-8。漢字モードは Shift-JIS 文字を 13 ビットに収めます。バージョン 40・最低誤り訂正での上限は、数字 7,089 桁、英数字 4,296 文字、バイト 2,953 個です。
実務的な帰結が 2 つ。第一に、小文字はバイトモードを強制します — HTTPS://EXAMPLE.COM/ABC のような大文字 URL は英数字モードでエンコードでき、小文字版より目に見えて疎なコードになります(スキームとホストは大文字小文字を区別しませんが、パスは通常区別するので、制御できる部分だけ大文字化を)。第二に、30〜50 文字の典型的な短縮 URL はバージョン 2〜4(25×25〜33×33)に収まり、ポスターから確実にスキャンできるスイートスポットです。
Alphanumeric capacity by version and EC level:
Version 1 (21×21): L 25 / M 20 / Q 16 / H 10
Version 5 (37×37): L 154 / M 122 / Q 87 / H 64
Version 10 (57×57): L 395 / M 311 / Q 221 / H 174
Version 40 (177×177): L 4296 / M 3391 / Q 2420 / H 1852
Same 60-char URL: EC L -> version 3, EC H -> version 5
(more correction = physically denser code)
HTTPS://SDK.IS/QR -> alphanumeric mode (sparser)
https://sdk.is/qr -> byte mode (denser, same length)誤り訂正:L・M・Q・H が実際に引き換えにするもの
QR コードは Reed-Solomon 誤り訂正でペイロードを保護します — CD や深宇宙通信で使われるのと同じ系統の符号です。4 つのレベルは、どれだけのコードワードが破壊されても復元できるかを表します:L 約 7%、M 約 15%、Q 約 25%、H 約 30%。代償は容量です。訂正バイトは同じグリッドに住むため、同じ URL でもレベル H はレベル L のおよそ 2 倍のモジュールを必要とし、バージョンが 1〜2 段上がります。
このパーセンテージは印刷面積ではなくコードワードの話であり、復元可能性は損傷の位置にも依存します。Reed-Solomon は散在するエラーに強い一方、コードを横切る反射光の帯や折り目は、インターリーブされたブロックを見かけの数字より速く壊すことがあります。さらに機能パターン — ファインダー、タイミング、フォーマット情報 — は誤り訂正の保護をまったく受けません。角のファインダーを覆うシール 1 枚で、レベルに関係なくスキャンは死にます。
ロゴの重ね置きは、誤り訂正の予算を意図的に使う手法です — デコーダは覆われたモジュールを損傷とみなして再構築します。ロゴを載せるならレベル H を使い、ロゴはコード面積の約 10% 以下、中央配置、3 つのファインダーから離すこと。そうすればロゴのコストに加えて、現実の擦れや反射への余裕が残ります。実務的な既定値:画面ときれいな印刷には M、メニューなど人が触れる物には Q、ブランドロゴを載せる場合や摩耗する面への印刷にのみ H — そしてレベルを上げるたびにコードが物理的に密になることをお忘れなく。
Level Recoverable codewords Overhead Typical use
L ~7% lowest controlled screens
M ~15% default posters, docs
Q ~25% higher menus, packaging
H ~30% ~2x vs L logo overlay, harsh env
NOT protected by any level:
- the 3 corner finder patterns
- timing patterns / format info
- a missing quiet zone around the code印刷の物理:クワイエットゾーン・コントラスト・距離の法則
実地での QR の失敗はほとんどがデジタルではなく物理的なものです。仕様はクワイエットゾーン — 四辺すべてに最低 4 モジュール幅の空白余白 — を要求します。デザイナーは無駄なスペースに見えるといって頻繁に切り落としますが、そうするとスキャナーが騒がしい背景からシンボルを分離できず、コードは断続的に失敗します — しかも机の上では決して再現しない形で。
サイズには単純な現場則があります:最小コード幅 ≈ スキャン距離 ÷ 10。10cm から読む名刺のコードは 1cm で足り、3m から読むポスターには 30cm のコードが必要です。これにモジュール数を掛け合わせてください。同じ印刷幅でも、バージョン 10 のコードは 1 辺 57 モジュールで、各モジュールはバージョン 2 の 3 分の 1 のサイズになります — 高バージョンのコードは不釣り合いに大きな印刷面積を要します。印刷解像度は 1 モジュールあたりプリンタドット 4 個以上を確保。オフィスプリンタでモジュールが約 0.4mm を下回ると、インクのにじみがモジュールを融合させ始めます。
コントラストはもう 1 つの静かな殺し屋です。デコーダは画像を二値化するため、明るい背景に暗いモジュール、強い輝度差が必要です — 白地に濃紺は大丈夫でも、白地に黄色はダメです。反転コード(暗い背景に明るいモジュール)は仕様違反です。iOS や多くの Android スキャナーは一部を読んでくれますが、読めないスキャナーアプリや組み込みリーダーも多数あります — テストなしで出荷しないこと。光沢ラミネートは鏡面反射で領域全体を消し得ますし、曲面(ボトル、マグ)は幾何を歪めます。できるだけ平らな面に配置し、千枚刷る前に必ず iPhone と Android のカメラ両方でテストを。
Field rules of thumb:
min code width ≈ scan distance / 10
business card (10 cm) -> 1 cm
shelf label (50 cm) -> 5 cm
poster (3 m) -> 30 cm
quiet zone >= 4 modules, all four sides
module size >= 0.4 mm on office printers (>= 4 dots)
contrast dark-on-light; inverted codes fail many readers
surfaces flat > gently curved; avoid gloss + direct light知っておく価値のあるペイロード形式:Wi-Fi・vCard・otpauth・動的 QR
QR コードはバイトをエンコードするだけで、スマートフォンがそれをどう扱うかはプレフィックスに基づく慣例です。URL はブラウザを開きます。WIFI: 文字列はネットワークに接続します:WIFI:T:WPA;S:MyNetwork;P:secret;; — T は認証方式(WPA が WPA2/WPA3 パーソナルをカバー、オープンネットワークは nopass)、S は SSID、P はパスワード、H:true を付ければ隠し SSID です。値の中のバックスラッシュ、セミコロン、カンマ、コロン、二重引用符はバックスラッシュでエスケープが必要です — Wi-Fi パスワード内のエスケープされていないセミコロンが、Wi-Fi QR が「時々」失敗する古典的な原因です。
連絡先データには 2 つの慣例があります。vCard(BEGIN:VCARD ... END:VCARD)は冗長ですがどこでも理解され、複数行の住所も無事に運べます。MeCard(MECARD:N:...;TEL:...;;)は NTT ドコモ由来のコンパクト形式で、コードはずっと小さくなりますが対応フィールドは少なめです。二要素認証設定用の TOTP シークレットは otpauth://totp/Issuer:account?secret=BASE32&issuer=Issuer として運ばれます — その QR 自体をシークレットとして扱ってください。スキャンした人は誰でも、あなたのコードを永遠に生成できます。他に有用なプレフィックス:tel:、mailto:、sms:、geo:37.5665,126.9780。
静的か動的かの区別は形式ではなくプロダクト上の判断です。静的コードは最終 URL を直接埋め込みます — メンテナンス不要で永遠に動きますが、印刷後は変更不能。「動的」コードは自分が管理する短いリダイレクト URL をエンコードしただけのもので、印刷後の編集可能性、スキャン分析、短いペイロード(=疎なコード)が得られる代わりに依存が生まれます — リダイレクトサービスが死ぬか課金が切れれば、印刷済みのコードもすべて道連れです。紙の上で長生きさせるものには、サードパーティの短縮サービスより自分の所有するリダイレクトドメインを。
WIFI:T:WPA;S:Cafe Guest;P:s3cret;;
WIFI:T:WPA;S:My\;Cafe;P:pa\:ss\,word;; <- ; : , escaped
WIFI:T:WPA;S:BackOffice;P:secret;H:true;; <- hidden SSID
otpauth://totp/GitHub:octocat?secret=JBSWY3DPEHPK3PXP&issuer=GitHub
MECARD:N:Doe,Jane;TEL:+821012345678;EMAIL:[email protected];;
BEGIN:VCARD
VERSION:3.0
N:Doe;Jane
TEL;TYPE=CELL:+82-10-1234-5678
EMAIL:[email protected]
END:VCARDセキュリティとプライバシー:クイッシング・シークレット・データの行き先
QR コードは暗号化されておらず、署名もされておらず、目視で検証もできません。この 3 つの欠如が QR の脅威モデルを定義します。
クイッシング(quishing)— QR を使ったフィッシング — は、人間がスキャン前にペイロードを読めないという事実を悪用します。標準的な攻撃は、パーキングメーター、飲食店のテーブル、請求書などの正規のコードの上に悪意あるコードのシールを貼るもの。決済詐欺の変種は偽の決済ページへリダイレクトします。防御は地味ですが有効です:コードの隣に人間が読める URL を印刷してスキャナーのプレビューと見比べられるようにする、汎用短縮サービスではなくブランドドメインを使う(プレビューに pay.yourbrand.com と出れば確認可能、ランダムな短縮コードでは不可能)、長期間掲示される公共のコードは物理的な改ざんを点検する。最近のスマホカメラは開く前にリンク先ドメインを表示します — ユーザーがそれを実際に読むよう習慣づけましょう。
カメラの届く場所に掲示・印刷される QR にシークレットを入れないでください。Wi-Fi QR にはパスワードが平文で入っています — ポスターを撮影した人は誰でも入手できます。otpauth の QR は 2FA のシードそのものです。イベントチケットや搭乗券には予約を複製・キャンセルするに足る情報が入っています — SNS に投稿する人々は高い授業料でそれを学びます。
最後に、生成がどこで行われるかを知っておくこと。一部のウェブ生成ツール(このページを含む)はサーバー側 API を呼んで画像を作ります。つまりペイロードはあなたのマシンを離れます。他方、JavaScript ライブラリでブラウザ内だけで描画するものや、qrencode CLI のようなオフラインツールもあります。公開ウェブサイトの URL なら違いはありません。Wi-Fi 認証情報、TOTP シード、社内向けの情報ならオフラインで生成を — qrencode コマンドやローカルライブラリなら、ネットワーク往復なしに同じ PNG が得られます。
# offline generation — payload never leaves the machine
qrencode -o wifi.png -l H 'WIFI:T:WPA;S:BackOffice;P:secret;;'
# checklist for public, long-lived codes
[ ] human-readable URL printed next to the code
[ ] branded domain (pay.yourbrand.com), not a generic shortener
[ ] HTTPS destination — camera previews show the domain
[ ] periodic physical check for sticker-over-sticker tampering
[ ] no secrets in the payload (Wi-Fi passwords ARE plaintext)