証明付保管の仕組み — ハッシュ・Merkle 木・ブロックチェーン・署名の技術解説

このページは、TEL050JP の「証明付保管」が発行する証明パッケージ(README.txt・proof.json・certificate.pdf・certificate.sig.json・history.json・ledger.json・verify.html、および選択時の原本・通信記録)が、何をどのような数学的根拠で示しているのかを説明します。技術解説であり、法的効力や証拠としての評価について述べるものではありません。証拠としての評価は裁判所その他の手続の判断に委ねられます。

1. この証明が述べること・述べないこと

証明パッケージが述べるのは次の3点です。

  1. 記載の SHA-256 値をもつファイルと、記載の通信記録とが対応していること。
  2. TEL050JP がこの証明を発行したこと。
  3. そのハッシュ値が、遅くとも記載のファイナライズ済みブロックの時点で存在していたこと。

述べないのは、通信の内容が真実であること、話者が誰であるか、録音に同意があったことや適法であったこと、ファイルの権利の帰属です。また、この仕組みは改ざんを「検出」するものであって、ファイルの改変を物理的に「防止」するものではありません。改変されたファイルは証明と一致しなくなる、という形で検出されます。

2. 暗号学的ハッシュ関数 SHA-256

すべての出発点は、ファイルのバイト列 x から固定長 256 ビット(16 進 64 桁)の値 H(x) を計算する SHA-256 です [1]。証明が頼っているのは、SHA-256 に期待される次の3つの性質です [2][3]。

  • 原像計算困難性: ハッシュ値だけから元のバイト列を求めることは、総当たりで約 2256 回の試行を要し、現実的に不可能です。
  • 第2原像計算困難性: あるファイルと同じハッシュ値をもつ別のファイルを作ることも、同程度に困難です。1 ビットでも異なるファイルは、まったく異なるハッシュ値をもちます。
  • 衝突困難性: 同じハッシュ値をもつ2つのファイルの組を見つけることは、誕生日のパラドックスにより約 2128 回の試行に相当し、これも現実的に不可能です。

したがって、ある時点で記録された SHA-256 値と、手元のファイルから計算し直した SHA-256 値とが一致すれば、そのファイルは記録時点から 1 ビットも変わっていないと結論できます。一致しなければ、どこかが変わっています。証明パッケージでは、音声や FAX の原本ファイルのハッシュ値(artifact.sha256)と、通信記録(発信元・宛先・時刻など)を正準化した JSON のハッシュ値(communication_record_hash)の2つを扱います。

3. 正準化とドメイン分離

同じ内容の通信記録でも、JSON の鍵の順序や空白が違えばバイト列は変わり、ハッシュ値も変わります。そこで通信記録は、鍵を辞書順に並べ、文字列を Unicode NFC に正規化し、余分な空白を含めない正準 JSON にしてからハッシュします。同じ考え方は JSON Canonicalization Scheme [4] として標準化されています。誰が計算しても同じバイト列になることが、独立検証の前提です。

また、ハッシュの入力には用途を示す 1 バイトのドメイン分離バイトを先頭に置きます。0x00 は Merkle 木の葉、0x01 は木の内部ノード、0x02 は証明 Manifest(proof.json)への署名、0x03 は証明書 PDF への署名です。これは Certificate Transparency [5] が葉と内部ノードに異なる前置バイトを使うのと同じ理由で、ある用途のハッシュ値や署名を別の用途のものとして読み替える攻撃を構造的に排除します。可変長のフィールドは長さを前置してから連結し、境界の曖昧さをなくしています。

4. Merkle 木と監査経路

TEL050JP は複数の証明をまとめて 1 件のブロックチェーン記録にします。そのために使うのが Merkle 木 [6][7] です。各証明の葉 Li は、テナント ID・通信 ID・通信記録ハッシュ・ファイルハッシュ・保管期限・延長回数・前回の葉(初回は全ゼロ)を 0x00 に続けて連結し、SHA-256 したものです。隣り合う2つのノードは H(0x01 ‖ 左 ‖ 右) で親ノードにまとめられ、これを繰り返して 1 つのルートに至ります。要素数が奇数の段では、余った 1 つを複製せずそのまま上の段に持ち上げます(複製すると、異なる葉の集合が同じルートを共有しうるためです)。

各証明の proof.json には、自分の葉からルートまでの経路上の兄弟ノード(監査経路)が入っています。検証者は葉を計算し直し、経路に沿ってハッシュを積み上げ、得られた値がブロックチェーンに記録されたルートと一致するかを確かめます。経路の長さは証明の総数 n に対して ⌈log2 n⌉ で、1,000 件をまとめても 10 段です。他の証明の内容は経路に含まれないため、同じバッチの他の利用者の情報は一切開示されません。

5. ブロックチェーンへの記録と「存在時点」

「このハッシュ値がある時点に存在していた」ことを、発行者自身の言葉に頼らずに示す方法は、Haber と Stornetta による電子タイムスタンプの研究 [8][9] に遡ります。要点は、ハッシュ値を発行者の手の届かない公開の記録に載せることです。Bitcoin [10] 以降のブロックチェーンは、多数の独立したノードが同じ台帳を保持し、ブロックが時系列に連鎖する公開記録であり、この用途に適しています。

TEL050JP は Symbol ブロックチェーン [11] に、TEL050JP 専用の署名アカウントから転送トランザクションを送り、そのメッセージ欄に tel050jp:proof:v1 kind=communication root=sha256:<ルート> batch=<バッチ ID> という固定形式でルートを書き込みます。トランザクションはブロック高とともに記録され、Symbol の投票ノードによるファイナライズ手続を経た高さまでのブロックは、以後巻き戻されません。証明パッケージは、記録されたブロック高がファイナライズ済み高以下であることを確認したうえで初めて発行されます。ブロックのタイムスタンプは Symbol ネットワークの多数のノードが合意した値であり、TEL050JP が後から日付を遡らせることはできません。「遅くともこの時点で存在していた」という表現は、この構造から来ています。

なお、公的な時刻認証局(RFC 3161 [12])によるタイムスタンプとは異なり、単一の認証局を信頼する必要がない代わりに、公開台帳の継続性に依存します。この点は §9 で扱います。

6. 発行者署名 Ed25519

「TEL050JP が発行した」ことは、電子署名で示します。proof.json は、署名フィールドを除いた本文を正準 JSON にし、0x02 とスキーマ名を前置した上で、TEL050JP の Ed25519 秘密鍵で署名されています。Ed25519 [13][14] は楕円曲線 Curve25519 上の署名方式で、公開鍵 32 バイト・署名 64 バイト、約 128 ビットの安全性をもち、署名の偽造には秘密鍵が必要です。対応する公開鍵は certificate.pdf の「発行者の署名鍵」欄と verify.html に埋め込まれた許可リストに記載されており、第三者は proof.json の署名がその鍵によるものかを、TEL050JP に問い合わせることなく検証できます。

ブロックチェーンに記録するための Symbol アカウントの鍵と、proof.json に署名する鍵は別のものです。前者は公開台帳への書き込みに、後者は「この証明は TEL050JP のものである」という表明に使い分け、どちらか一方の鍵の問題が他方に波及しないようにしています。

署名鍵の台帳(ledger.json)

ledger.json は、証明に署名する公開鍵の一覧です。口座やポイント残高の台帳ではなく、証明の発行者署名を確認するための情報です。秘密鍵は含まれません。ZIP を作成した時点の台帳の写しとして、証明と一緒に保管します。

形式は tel050jp-signer-ledger-v1 です。keys の各項目には、鍵の識別子 key_id、公開鍵 public_key、有効期間の始点 not_before と終点 not_after(UTC、null はその境界の指定なし)、状態 status が入っています。

  • active:使用中の鍵。新しい証明への署名に使います。
  • retired:使用を終了した鍵。新しい署名には使いませんが、有効期間内の過去の署名を確認するために残します。
  • compromised:漏えい扱いの鍵。現在の信頼対象から除外します。

台帳の検証:verify.html に ledger.json を指定すると、形式・鍵識別子・重複を検査し、検証画面が保持する台帳の写し、または照会で確認した最新台帳と照合します。ファイルが持ち込んだ鍵をそのまま信用することはありません。証明と履歴の署名鍵について、漏えい状態・鍵識別子・記載の発行時刻と有効期間を確認します。PDF の署名鍵も確認しますが、PDF 署名には署名時刻が含まれないため、有効期間は未確認です。発行時刻との照合は署名時刻を独立に証明するものではありません。

オンラインとオフラインの違い:公開版の検証画面は、検証時に公開署名鍵台帳と最新の確定済み Symbol 台帳アンカーを TEL050JP へ照会します。ファイルは送信しません。結果はサーバーに設定された Symbol ノードの応答に依存し、トランザクションハッシュ・ブロック高・照会時刻を表示します。台帳未公表、ノード障害、検索上限到達などは未確認とし、古い成功結果で代用しません。オフラインでは台帳の写しとの一致は確認できますが、公開記録・最新の失効状態は未確認です。古い ZIP や検証画面は自動更新されません。記録先が testnet の場合は試験用であり、リセットにより記録が失われる可能性があります。

台帳はハッシュ照合に使えるように一定の形式で保存されています。読みやすくするための整形や書き換えも避け、そのまま保管してください。台帳の真正性や公開台帳への記録は、ファイルが同梱されているだけでは確認できません。

7. 証明書 PDF とその分離署名

certificate.pdf は人が読むための書面で、検証に用いる正式なデータは proof.json です。PDF はダウンロードのたびに proof.json から生成されるため、proof.json の署名は PDF を対象にしていません。そこで、PDF のバイト列の SHA-256 を 0x03 とスキーマ名の後ろに置いて同じ Ed25519 鍵で署名し、certificate.sig.json として同梱しています。verify.html に PDF と sig を指定すると、PDF が 1 バイトでも編集されていれば、記載されたハッシュ値と一致しないことが示されます。PDF の見た目(罫線や配色)は装飾であり、それ自体は何も証明しません。証明するのは署名です。

8. 独立した検証手順(verify.html)

証明パッケージには、単一の HTML ファイルとして検証器 verify.html が同梱されています。外部のスクリプトやサーバーへの接続を一切行わず、ブラウザ標準の WebCrypto だけで次を検査します。

  1. proof.json のスキーマと、発行者署名(Ed25519、許可リスト照合)。
  2. 手元のファイルの SHA-256 と artifact.sha256 の一致。
  3. communication.json の SHA-256 と communication_record_hash の一致。
  4. proof.json の値だけから葉を再計算し、監査経路を積み上げてルートに一致すること。
  5. ブロックチェーンに書き込まれたメッセージが、そのルートとバッチ ID から定まる固定形式と一致すること。
  6. 記録した Symbol アカウントとネットワークが許可リストと一致し、ブロック高がファイナライズ済み高以下であること。
  7. history.json がある場合、各版が前回の葉で連結していること。
  8. certificate.pdf と certificate.sig.json がある場合、PDF が署名時と同一であること。
  9. ledger.json がある場合、信頼する台帳との一致と署名鍵の状態・記載発行時刻の有効期間。PDF 署名の有効期間と、オフラインでの最新失効状態は未確認。

ブロックチェーン上の記録そのものは、Symbol の公開ノードやブロックエクスプローラーで、トランザクションハッシュを手掛かりに誰でも参照できます。verify.html が確認するのは「proof.json が内部的に整合しており、記載のルートが記載のメッセージとして記録されたはずである」ことまでで、実際にその記録が台帳にあるかは、公開台帳を参照して確かめます。TEL050JP のサーバーは、この手順のどこにも必要ありません。

公開版 verify.html は、ファイルをブラウザ内で検証し、現在の公開台帳とその記録状況を別途照会します。選択したファイルは送信されません。同梱の verify.html が改変されていないか疑わしい場合は、信頼できる配布元から新しい検証画面を取得してください。オフライン版では、その後の失効は確認できません。

9. 何が検出でき、何が検出できないか

状況結果
ファイルの一部が後から書き換えられたSHA-256 が一致せず、検出される
通信記録(番号や時刻)が後から書き換えられた通信記録ハッシュが一致せず、検出される
証明書 PDF が編集されたcertificate.sig.json と一致せず、検出される
proof.json の値が書き換えられた発行者署名が一致せず、検出される。葉・ルートも再計算で一致しない
証明の日付を実際より前に見せかけるブロックのタイムスタンプは公開台帳の合意値であり、発行者にも変更できない
TEL050JP 以外の者が TEL050JP 名義の証明を作る署名鍵がないため署名が一致しない。Symbol アカウントも許可リスト外となる
ファイルが、ハッシュを取る前に編集されていた検出されない。証明が示すのは記録時点以降の不変性である
通信の内容が事実と異なる、話者が別人である対象外。証明は内容の真偽・人物の同一性を扱わない

鍵が漏えいした場合: 新しい鍵に切り替え、漏えい扱いの鍵を現在の検証画面の許可リストから除外します。古い ZIP 内の検証画面は自動更新されません。過去の署名も無条件に信頼できるとは限らず、ブロックチェーンの記録だけで漏えい鍵の署名を信頼できるようになるわけではありません。署名鍵の台帳と検証画面の制限も確認してください。

TEL050JP がサービスを終了した場合: 検証に必要なのは proof.json・手元のファイル・verify.html・公開台帳だけであり、TEL050JP のサーバーには依存しません。Symbol ネットワークが停止した場合: 台帳の写しやブロックエクスプローラーのアーカイブが残る限り検証可能です。長期の保全が必要な場合は、トランザクションの記録(ブロック高・タイムスタンプ・メッセージ)を証明パッケージとともに手元に保存しておくことを勧めます。

10. 用語

SHA-256
任意長の入力から 256 ビットの値を計算するハッシュ関数。NIST 標準 [1]。
Merkle 木
多数のハッシュ値を二分木状にまとめ、1 つのルートで全体を代表させる構造 [6]。
監査経路
ある葉からルートまでを再計算するのに必要な兄弟ノードの列。
ファイナライズ
Symbol において、投票ノードの合意により、その高さまでのブロックが確定し巻き戻されなくなること [11]。
Ed25519
楕円曲線 Curve25519 上の電子署名方式 [13][14]。
正準 JSON
同じ内容が常に同じバイト列になるよう、鍵順・空白・文字正規化を固定した JSON 表現 [4]。
ドメイン分離
ハッシュや署名の入力に用途を示すバイトを前置し、用途間の混同を防ぐ手法 [5]。

11. 参考文献

  1. National Institute of Standards and Technology. Secure Hash Standard (SHS). FIPS PUB 180-4, 2015. doi:10.6028/NIST.FIPS.180-4
  2. P. Rogaway and T. Shrimpton. "Cryptographic Hash-Function Basics: Definitions, Implications, and Separations for Preimage Resistance, Second-Preimage Resistance, and Collision Resistance." Fast Software Encryption (FSE 2004), LNCS 3017, Springer, 2004, pp. 371–388.
  3. J. Katz and Y. Lindell. Introduction to Modern Cryptography, 3rd ed. CRC Press, 2020.
  4. A. Rundgren, B. Jordan, and S. Erdtman. JSON Canonicalization Scheme (JCS). RFC 8785, IETF, 2020.
  5. B. Laurie, A. Langley, and E. Kasper. Certificate Transparency. RFC 6962, IETF, 2013.
  6. R. C. Merkle. "A Digital Signature Based on a Conventional Encryption Function." Advances in Cryptology — CRYPTO '87, LNCS 293, Springer, 1988, pp. 369–378.
  7. R. C. Merkle. "Protocols for Public Key Cryptosystems." IEEE Symposium on Security and Privacy, 1980, pp. 122–134.
  8. S. Haber and W. S. Stornetta. "How to Time-Stamp a Digital Document." Journal of Cryptology 3(2), 1991, pp. 99–111.
  9. D. Bayer, S. Haber, and W. S. Stornetta. "Improving the Efficiency and Reliability of Digital Time-Stamping." Sequences II: Methods in Communication, Security, and Computer Science, Springer, 1993, pp. 329–334.
  10. S. Nakamoto. Bitcoin: A Peer-to-Peer Electronic Cash System. 2008.
  11. NEM Group. Symbol Technical Reference. 2021. https://docs.symbol.dev/
  12. C. Adams, P. Cain, D. Pinkas, and R. Zuccherato. Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP). RFC 3161, IETF, 2001.
  13. D. J. Bernstein, N. Duif, T. Lange, P. Schwabe, and B.-Y. Yang. "High-speed high-security signatures." Journal of Cryptographic Engineering 2(2), 2012, pp. 77–89.
  14. S. Josefsson and I. Liusvaara. Edwards-Curve Digital Signature Algorithm (EdDSA). RFC 8032, IETF, 2017.

本ページの記述は、証明パッケージの仕様 tel050jp-communication-proof-v1 に基づきます。仕様は版ごとに掲載しており、改訂された場合も旧版の証明は旧版の規則のまま検証できます。手元の証明がどの版かは、proof.json の protocol 欄(プロトコルの版)と schema 欄(パッケージ形式の版)で識別できます。