技術ホワイトペーパー

PDF Proの暗号技術に関する詳細な技術ドキュメント

公開日: 2025年4月16日 最終更新: 2026年4月16日 バージョン: 2.0

ホワイトペーパー索引

  1. エンドツーエンド暗号化ファイル転送
  2. プライバシー優先の暗号文書署名

エンドツーエンド暗号化ファイル転送

PDF Pro ホワイトペーパー WP-001 — アーキテクチャとセキュリティ

1.1 概要

本ホワイトペーパーでは、PDF Proのセキュア転送システムのアーキテクチャについて説明します。このシステムはエンドツーエンド暗号化ファイル転送の仕組みであり、ファイルはアップロード前にAES-256-GCMを使用してクライアントサイドで暗号化されます。サーバーは不透明な暗号文のみを保存し、いかなる時点においてもファイルの内容を復号・検査・読み取る能力を持ちません。システムは2つの主要モードをサポートします。1つはURLフラグメントを介して転送される自動生成ランダム鍵(サーバーには送信されません)、もう1つはPBKDF2を使用したパスフレーズ派生鍵です。いずれのモードでも、暗号化鍵は送信者と受信者のブラウザ内にのみ存在します。本ドキュメントでは、暗号プリミティブ、データフロー、脅威モデル、およびシステムの正直な制限事項について詳述します。用語についての注記:本システムはゼロ知識証明(ZKP)を使用していません。「サーバーはあなたのファイルについてゼロ知識である」と述べる場合、これはクライアントサイド暗号化の結果として、サーバーは復号できない暗号文のみを保持することを意味します。

1.2 アーキテクチャ概要

セキュア転送システムは厳格なクライアントとサーバーの分離に従っており、すべての暗号処理は専らブラウザ内で行われます:

サーバーは意図的に暗号化データの「ダムパイプ」として設計されています。暗号化鍵、パスフレーズ、ファイルの内容については一切の知識を持ちません。これはポリシーによるものではなく、アーキテクチャ的に強制されています。

設計原則: サーバーが侵害されても、ユーザーデータが侵害されないようにする。完全なデータベースアクセスとサーバーサイドのコード実行権限を持つ攻撃者であっても、転送されたファイルを復号することはできません。

1.3 暗号化:Web Crypto API を介した AES-256-GCM

すべてのファイル暗号化は、ブラウザネイティブの Web Crypto API を通じてアクセスされるAES-256-GCM認証付き暗号化アルゴリズムを使用します。これにより、機密性(データを読み取れない)と完全性(検出なしにデータを改ざんできない)の両方が提供されます。

1.3.1 アルゴリズムパラメータ

パラメータ根拠
アルゴリズムAES-256-GCMNIST承認、関連データ付き認証暗号化(AEAD)
鍵サイズ256ビット最大AES鍵長;ブルートフォースに対する128ビットセキュリティを提供
IVサイズ96ビット(12バイト)GCMモードにおけるNIST推奨IV長
タグサイズ128ビット(16バイト)最大完全性保護のためのフル長認証タグ
IV生成crypto.getRandomValues()暗号学的に安全な乱数生成器

1.3.2 暗号化の実装

// Simplified encryption flow (Web Crypto API)

const iv = crypto.getRandomValues(new Uint8Array(12));
const salt = crypto.getRandomValues(new Uint8Array(16));

// Derive key from passphrase (see Section 1.4)
const key = await deriveKey(passphrase, salt);

// ファイルを暗号化する
const ciphertext = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv: iv },
  key,
  fileArrayBuffer
);

// Package: [salt (16B)] + [iv (12B)] + [ciphertext + tag]
const blob = concatenate(salt, iv, ciphertext);

最終的な暗号化ブロブは3つの要素の連結です:16バイトのソルト(鍵導出に使用)、12バイトのIV(AES-GCMに使用)、および付加された16バイトのGCM認証タグを含む暗号文。このブロブがサーバーが受信・保存するものです。

1.4 鍵生成と転送

セキュア転送は、相互に排他的な2つの鍵モードをサポートします。モードは転送作成時に送信者が選択します。

1.4.1 モードA — 自動生成鍵(デフォルト)

デフォルトモードでは、パスフレーズは関与しません。ブラウザは直接、暗号学的にランダムな256ビットのAES鍵を生成します:

1.4.2 モードB — パスフレーズ保護転送

送信者がパスフレーズの設定を選択した場合、PBKDF2を使用してそのパスフレーズから鍵が導出されます:

1.4.3 PBKDF2パラメータ(モードB)

パラメータ根拠
アルゴリズムPBKDF2NIST SP 800-132推奨;広く監査済み
ハッシュ関数SHA-256標準暗号ハッシュ;256ビット出力
反復回数600,000PBKDF2-SHA256に対するOWASP 2023推奨を満たす
ソルトサイズ128ビット(16バイト)転送ごとに一意;レインボーテーブル攻撃を防止
出力鍵長256ビットAES-256鍵要件に一致

1.4.4 鍵導出の実装(モードB)

async function deriveKey(passphrase, salt) {
  // Import passphrase as raw key material
  const keyMaterial = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(passphrase),
    { name: "PBKDF2" },
    false,
    ["deriveKey"]
  );

  // Derive AES-256-GCM key
  return crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt: salt,
      iterations: 600000,
      hash: "SHA-256"
    },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    false,
    ["encrypt", "decrypt"]
  );
}

セキュリティ注記: モードBでは、セキュリティはパスフレーズのエントロピーに依存します。大文字、小文字、数字、記号を組み合わせた12文字以上のパスフレーズを推奨します。

1.5 データフロー

セキュア転送の完全なライフサイクルは次のパスをたどります:

1.5.1 送信(アップロード) — モードA(自動生成鍵)

  1. 送信者がブラウザでファイルを選択します。
  2. ブラウザは crypto.getRandomValues() を使用して、ランダムな256ビットのAES-GCM鍵とランダムな12バイトのIVを生成します。
  3. ブラウザはAES-256-GCMを使用してファイルを暗号化し、暗号文+認証タグを生成します。
  4. ブラウザは[IV | 暗号文+タグ]を単一のブロブに連結します。
  5. ブラウザはHTTPS経由で暗号化ブロブをサーバーにアップロードします。
  6. サーバーはブロブをSupabase Storageに保存し、メタデータレコード(転送ID、有効期限、ダウンロード制限、ファイル名、ファイルサイズ)を作成します。
  7. サーバーは転送URLを返します。ブラウザはエクスポートされた鍵をURLフラグメント(#)に付加します。
  8. 送信者はフラグメントを含む完全なURLを受信者と共有します。

1.5.2 送信(アップロード) — モードB(パスフレーズ)

  1. 送信者はブラウザでファイルを選択し、パスフレーズを入力します。
  2. ブラウザは crypto.getRandomValues() を使用して、ランダムな16バイトのソルトと12バイトのIVを生成します。
  3. ブラウザはPBKDF2(60万回の反復)を使用してパスフレーズからAES-256鍵を導出します。
  4. ブラウザはAES-256-GCMを使用してファイルを暗号化し、暗号文+認証タグを生成します。
  5. ブラウザは[ソルト | IV | 暗号文+タグ]を単一のブロブに連結します。
  6. ブラウザはHTTPS経由で暗号化ブロブをサーバーにアップロードします。
  7. サーバーはブロブをSupabase Storageに保存し、メタデータレコード(転送ID、有効期限、ダウンロード制限、ファイル名、ファイルサイズ)を作成します。
  8. サーバーは転送IDを含む転送URLを返します。
  9. 送信者は転送URLとパスフレーズを別々のチャンネルを通じて受信者と共有します。

1.5.3 受信(ダウンロード) — モードA

  1. 受信者はフラグメントに鍵が含まれた完全な転送URLを開きます。
  2. ブラウザはURLフラグメントからAES鍵を抽出します(サーバーには送信されません)。
  3. ブラウザはHTTPS経由でサーバーから暗号化ブロブをダウンロードします。
  4. ブラウザはブロブからIV(最初の12バイト)を抽出します。
  5. ブラウザは抽出された鍵とIVを使用してAES-256-GCMで暗号文を復号します。
  6. 復号が成功した場合(GCMタグが検証される)、平文ファイルがユーザーに提示されます。
  7. サーバーはダウンロードカウンターを更新し、読み取り後消去が有効な場合はブロブを削除します。

1.5.4 受信(ダウンロード) — モードB

  1. 受信者は転送URLを開き、ブラウザでパスフレーズを入力します。
  2. ブラウザはHTTPS経由でサーバーから暗号化ブロブをダウンロードします。
  3. ブラウザはブロブからソルト(最初の16バイト)とIV(次の12バイト)を抽出します。
  4. ブラウザはPBKDF2(60万回の反復)を使用してパスフレーズ+ソルトからAES-256鍵を導出します。
  5. ブラウザは導出された鍵とIVを使用してAES-256-GCMで暗号文を復号します。
  6. 復号が成功した場合(GCMタグが検証される)、平文ファイルがユーザーに提示されます。
  7. 復号が失敗した場合(誤ったパスフレーズ=誤った鍵=無効なGCMタグ)、エラーが表示されます。
  8. サーバーはダウンロードカウンターを更新し、読み取り後消去が有効な場合はブロブを削除します。

1.6 サーバーが保存するものとまったく参照しないもの

データ要素サーバーがアクセス可能か詳細
暗号化ブロブ(ソルト+IV+暗号文+タグ)はい不透明なバイナリデータ;サーバーは内容を解釈できない
転送IDはい転送識別子はPostgreSQLのgen_random_uuid()によって生成されるUUID v4値であり、サーバーのCSPRNGから122ビットの暗号学的ランダム性を提供します
元のファイル名はい受信者への表示用にメタデータに保存
元のファイルサイズはい表示目的でメタデータに保存
有効期限タイムスタンプはい自動削除の実施に使用
ダウンロード数/制限はい読み取り後消去とダウンロード制限の実施に使用
送信者ユーザーID(認証済みの場合)はい管理のためにアカウントに転送をリンク
パスフレーズいいえ — 決してサーバーには送信されない;ブラウザから出ることはない
導出された暗号化鍵いいえ — 決して暗号化/復号操作中のブラウザメモリ内にのみ存在
平文ファイルの内容いいえ — 決して暗号化された暗号文のみがサーバーに到達する
PBKDF2反復回数いいえクライアントにハードコードされており;サーバーには送信されない

1.7 自動有効期限と読み取り後消去

すべてのセキュア転送は設計上、一時的なものです。永続的なストレージのオプションはありません。

1.7.1 有効期限オプション

オプション動作実施方法
読み取り後消去最初のダウンロード成功後、暗号化ブロブは即座に削除されるサーバーサイド:ダウンロードストリーム完了後にストレージからブロブを削除
1時間ダウンロード状況に関わらず1時間後に自動削除サーバーサイド:定期クリーンアップジョブ+アクセス時の有効期限チェック
24時間24時間後に自動削除上記と同様
7日間最大保持期間;7日後に自動削除上記と同様

1.7.2 削除の保証

転送が期限切れになるか読み取り後に消去されると、暗号化ブロブはSupabase Storageから完全に削除されます。メタデータレコードは、完全に消去される前に30日間ソフト削除状態で保持されます(不正使用調査のため)。メタデータレコードには、暗号化鍵、パスフレーズ、またはファイルの再構築に使用できる情報は含まれていません。

1.8 脅威モデルと対策

脅威攻撃ベクター対策
サーバーの侵害 攻撃者がデータベースとストレージへのフルアクセスを取得 保存されたすべてのデータはAES-256-GCM暗号文です。攻撃者は不透明なブロブのみを取得します。パスフレーズなしでは、256ビットAESのブルートフォースは計算上不可能です。
ネットワーク傍受(MITM) 攻撃者が転送中のデータを傍受 すべてのトラフィックはTLS 1.3を使用します。TLSが破られた場合でも、攻撃者は暗号化されたブロブのみを取得します(サーバー侵害と同様)。
弱いパスフレーズ 攻撃者が短いまたは一般的なパスフレーズをブルートフォース攻撃 60万回の反復を持つPBKDF2により、各推測の計算コストが高くなります。4文字のパスフレーズでも、相当な計算リソースを必要とします。UIはパスフレーズの最小長を強制し、強度フィードバックを提供します。
パスフレーズの傍受 攻撃者が送信者と受信者の間で共有されたパスフレーズを傍受 パスフレーズはアウトオブバンドで共有されます(当社のシステムを通じてではありません)。転送URLとは異なるチャンネルを通じて共有することを推奨します。これはユーザーの責任です。
クライアントサイドコードの改ざん 攻撃者がユーザーに提供されるJavaScriptを修正 すべてのアセットはVercelのCDN経由でHTTPS配信されます。サブリソース整合性(SRI)ハッシュはCDNレベルの改ざんを防護します。ユーザーはブラウザのDevToolsでソースコードを確認できます。
メモリ抽出 攻撃者がブラウザメモリから暗号化鍵を抽出 Web Crypto APIの鍵は可能な限り抽出不可としてマークされています。導出された鍵は暗号化/復号操作中のみメモリに存在します。ブラウザのメモリ分離がOSレベルの保護を提供します。
リプレイ攻撃 攻撃者がキャプチャした暗号化ブロブを再生 各転送には一意のIDがあり、ダウンロード制限と有効期限によって保護されています。読み取り後消去転送は最初のアクセス後に削除されます。

1.8.1 前提条件

1.8.2 対象外

1.9 制限事項と正直な開示

正直な制限事項: 完璧なセキュリティシステムは存在しません。当社は既知の制限事項の透明な開示を信じています。


プライバシー優先の暗号文書署名

PDF Pro ホワイトペーパー WP-002 — アーキテクチャとセキュリティ

2.1 概要

本ホワイトペーパーでは、PDF ProのPrivacy Signatureシステムのアーキテクチャについて説明します。このシステムは、PDFドキュメントが署名者のブラウザから出ることのない暗号文書署名の仕組みです。システムはP-256曲線とSHA-256ハッシュを使用したECDSAを使用して、デタッチされたデジタル署名を生成します。ドキュメントハッシュ、暗号署名、公開鍵のみがサーバーに送信されます。秘密鍵はIndexedDBを使用してユーザーのブラウザ内でのみ生成・暗号化・保存され、PBKDF2鍵導出(600,000回の反復)とAES-256-GCM暗号化によって保護されます。本ドキュメントでは、完全な署名と検証のアーキテクチャ、鍵管理モデル、署名済みペイロードスキーマ、監査証跡設計、脅威モデル、および正直な制限事項について詳述します。

2.2 アーキテクチャ概要

Privacy Signatureシステムは、基本的な制約を中心に設計されています:PDFドキュメントはサーバーに送信されてはなりません。これはデタッチ署名モデルによってアーキテクチャ的に強制されています。

核心的保証: サーバーはPDFドキュメントを参照・受信・処理することは決してありません。サーバーがドキュメント関連で受信する唯一のデータは、SHA-256ハッシュ — 固定サイズの256ビット値であり、そこから元のドキュメントを再構築することはできません。

2.3 署名アルゴリズム:ECDSA P-256 / SHA-256

2.3.1 アルゴリズムパラメータ

パラメータ根拠
署名アルゴリズムECDSA(楕円曲線デジタル署名アルゴリズム)NIST FIPS 186-4;コンパクトな署名;鍵ビットあたりの強力なセキュリティ
曲線P-256(secp256r1 / prime256v1)NIST承認;128ビットセキュリティレベル;Web Crypto APIの幅広いサポート
ハッシュ関数SHA-256NIST FIPS 180-4;256ビットダイジェスト;衝突耐性
鍵サイズ256ビット秘密鍵、512ビット公開鍵(非圧縮)P-256の標準;約3072ビットRSAに相当
署名サイズ64バイト(r: 32バイト、s: 32バイト)コンパクト;保存と転送に適合
署名フォーマットIEEE P1363(生の r || s)Web Crypto APIのネイティブ出力;保存のためbase64urlエンコード

署名エンコーディング: P-256を使用したWeb Crypto APIのECDSAは、ビッグエンディアン固定幅フォーマットの2つの32バイト整数(r || s)から構成される生の64バイト署名を生成します。この生の出力は保存のためにbase64urlエンコードされます。これはDERエンコードではありません — Web Crypto APIがネイティブに生成するIEEE P1363フォーマットです。

2.3.2 署名フロー

// 1. Hash the PDF document (client-side)
const fileBuffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest("SHA-256", fileBuffer);
const hashHex = Array.from(new Uint8Array(hashBuffer))
  .map(b => b.toString(16).padStart(2, '0')).join('');

// 2. 秘密鍵でハッシュに署名する(クライアントサイド)
const signature = await crypto.subtle.sign(
  { name: "ECDSA", hash: "SHA-256" },
  privateKey,   // CryptoKey from IndexedDB (decrypted)
  hashBuffer
);

// 3. サーバーに送信: ハッシュ + 署名 + 公開鍵(PDFは送信しない)
await submitSignature({
  documentHash: hashHex,
  signature: base64Encode(signature),
  publicKey: exportedPublicKeyJWK
});

2.4 鍵管理:一時的 vs. 永続的

鍵の種類コンテキストライフサイクルストレージ
一時的 ゲストユーザー(サインインしていない) セッションごとに生成;タブを閉じると破棄 メモリ内のみ(CryptoKeyオブジェクト);永続化されない
永続的 認証済みユーザー(サインイン済み) 一度生成;セッションをまたいで永続化;失効可能 IndexedDB(PBKDF2+AES-256-GCMで暗号化)

2.4.1 鍵生成

// Generate ECDSA P-256 key pair (Web Crypto API)
const keyPair = await crypto.subtle.generateKey(
  {
    name: "ECDSA",
    namedCurve: "P-256"
  },
  true,   // extractable (needed for encryption + storage)
  ["sign", "verify"]
);

// サーバー登録用にJWK形式で公開鍵をエクスポートする
const publicKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey);

// 暗号化ストレージ用にJWK形式で秘密鍵をエクスポートする
const privateKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.privateKey);

公開鍵フォーマット: 公開鍵はJWK(JSON Web Key)フォーマットでエクスポートおよび保存されます。鍵のフィンガープリントは、キーがアルファベット順に並んだ公開フィールド{crv, kty, x, y}のみを含む正規JWKのSHA-256として計算されます。

2.5 秘密鍵の保護:PBKDF2 + AES-GCM → IndexedDB

永続的な秘密鍵は平文で保存されることはありません。IndexedDBへの書き込み前に、秘密鍵(JWK JSONとしてエクスポート)はセキュア転送と同じパターンを使用して暗号化されます:

2.5.1 保護パラメータ

パラメータ
鍵導出PBKDF2-SHA256、600,000回の反復
ソルトランダム16バイト(鍵ごと)
暗号化AES-256-GCM
IVランダム12バイト(暗号化ごと)
入力秘密鍵JWK(JSON文字列、UTF-8エンコード)
IndexedDBに保存される出力{ salt, iv, ciphertext, publicKeyJWK, keyId, createdAt }

2.5.2 ストレージスキーマ

// 暗号化署名キーのIndexedDBレコード構造
{
  "keyId":       "uuid-v4-unique-identifier",
  "publicKey":   { /* JWK format, unencrypted */ },
  "encryptedPrivateKey": {
    "salt":       "base64-encoded-16-bytes",
    "iv":         "base64-encoded-12-bytes",
    "ciphertext": "base64-encoded-aes-gcm-ciphertext"
  },
  "algorithm":   "ECDSA",
  "curve":       "P-256",
  "createdAt":   "2026-04-16T00:00:00.000Z",
  "userId":      "supabase-auth-user-id"
}

鍵の回復: ユーザーが署名パスフレーズを忘れた場合、秘密鍵を回復することはできません。当社はパスフレーズ、導出された鍵、またはPBKDF2+AES-GCM保護を迂回するメカニズムを持っていません。ユーザーは鍵のバックアップをエクスポートすることを推奨します。

2.6 デタッチ署名モデル

PDF Proはデタッチ署名モデルを使用しています。これは署名がドキュメントとは別に保存されることを意味します。これが重要なプライバシーメカニズムです:ドキュメントは署名者のデバイスから出ることはありません。

2.6.1 サーバーに送信されるもの

2.6.2 サーバーに送信されないもの

暗号学的保証: SHA-256は一方向ハッシュ関数です。ハッシュ e3b0c44298fc1c14... のみが与えられた場合、ECDSAとSHA-256のセキュリティ前提のもと、元のドキュメントを再構築できないという強力な暗号学的保証を提供します。ハッシュは、再ハッシュ時のID確認を超えて、ドキュメントの内容、長さ、または構造については何も明らかにしません。

2.7 署名済みペイロードスキーマ v1.0

以下のJSONスキーマは、サーバーに保存される完全な署名レコードを定義します:

{
  "schemaVersion":  "1.0",
  "signatureId":    "uuid-v4",
  "documentHash":   "sha256-hex-64-chars",
  "hashAlgorithm":  "SHA-256",
  "signature":      "base64-encoded-ecdsa-signature",
  "signatureAlgorithm": "ECDSA",
  "curve":          "P-256",
  "publicKey": {
    "kty": "EC",
    "crv": "P-256",
    "x":   "base64url-encoded-x-coordinate",
    "y":   "base64url-encoded-y-coordinate"
  },
  "signer": {
    "identityLevel": "authenticated | self-asserted",
    "displayName":   "string or null",
    "email":         "string or null",
    "userId":        "supabase-uid or null"
  },
  "timestamp":      "ISO-8601-UTC",
  "metadata": {
    "fileName":     "original-file-name.pdf",
    "fileSize":     123456,
    "pageCount":    12,
    "clientVersion": "2.0.0",
    "userAgent":    "browser-user-agent-string"
  },
  "auditChain": {
    "previousEventHash": 「前の監査イベントのsha256、または null」,
    "eventHash":         「このレコードのsha256」
  }
}

2.8 検証フロー

署名検証は2フェーズのプロセスです:クライアントサイドの暗号検証に続いて、サーバーサイドのクロスチェックが行われます。

2.8.1 フェーズ1:クライアントサイドの暗号検証

  1. ユーザーがブラウザにPDFを読み込みます。
  2. ブラウザが読み込まれたPDFのSHA-256ハッシュを計算します。
  3. ブラウザがこのハッシュに一致する署名レコードのサーバーに問い合わせます。
  4. 返された各署名レコードについて、ブラウザはECDSA検証を実行します:
    const isValid = await crypto.subtle.verify(
      { name: "ECDSA", hash: "SHA-256" },
      importedPublicKey,
      signatureBuffer,
      hashBuffer
    );
  5. isValid === true の場合、署名は暗号学的に有効です:ドキュメントは署名以降改ざんされておらず、署名は対応する秘密鍵の保有者によって生成されました。

2.8.2 フェーズ2:サーバーサイドのクロスチェック

  1. サーバーは署名レコードの公開鍵が既知のユーザーに登録されていることを確認します(認証済み署名の場合)。
  2. サーバーは署名レコードが失効していないことを確認します。
  3. サーバーは監査証跡の整合性を確認します(ハッシュチェーン検証)。
  4. サーバーは署名者のアイデンティティレベルと登録ステータスを返します。

2.8.3 検証結果

結果意味
有効(認証済み)署名は暗号学的に有効であり、公開鍵は登録済みの認証されたPDF Proユーザーに属します。
有効(自己申告)署名は暗号学的に有効ですが、署名者のアイデンティティは自己申告です(ゲストユーザーまたは未確認の名前)。
無効暗号検証が失敗しました。ドキュメントは署名以降改ざんされているか、署名が破損しています。
失効済み署名は有効でしたが、署名者によって明示的に失効されました。
署名が見つかりませんこのドキュメントハッシュに対する署名レコードが存在しません。

2.9 監査証跡:ハッシュチェーンイベント

すべての署名および検証イベントは、改ざん防止の監査証跡に記録されます。イベントはハッシュチェーン化されています:各イベントには前のイベントのSHA-256ハッシュが含まれており、ブロックチェーンに似た追記専用のチェーンを形成します。

2.9.1 監査イベントの種類

イベント種別トリガー記録されるデータ
KEY_REGISTEREDユーザーが新しい公開鍵を登録公開鍵JWK、ユーザーID、タイムスタンプ
DOCUMENT_SIGNEDユーザーがドキュメントに署名ドキュメントハッシュ、署名、公開鍵、署名者アイデンティティ、タイムスタンプ
SIGNATURE_VERIFIED任意のユーザーが署名を検証ドキュメントハッシュ、検証結果、検証者情報(認証済みの場合)、タイムスタンプ
SIGNATURE_REVOKED署名者が署名を失効署名ID、失効理由、タイムスタンプ
KEY_REVOKEDユーザーが公開鍵を失効公開鍵ID、失効理由、タイムスタンプ

2.9.2 ハッシュチェーン構造

// Each audit event includes:
{
  "eventId":            "uuid-v4",
  "eventType":          "DOCUMENT_SIGNED",
  "timestamp":          "ISO-8601-UTC",
  "data":               { /* event-specific payload */ },
  "previousEventHash": "sha256-of-previous-event-json",
  "eventHash":          「eventHashを除くこのイベントJSONのsha256」
}

// 改ざん検出: チェーンを検証するには次を計算する:
// SHA-256(JSON.stringify(event without eventHash field))
// and confirm it matches eventHash.
// Then confirm previousEventHash matches the prior event's eventHash.

チェーン内のいずれかのイベントが変更されると、それ以降のすべてのハッシュリンクが壊れ、改ざんが即座に検出可能になります。これにより、監査証跡の整合性が強力に保証されます。

重要な制限事項: ハッシュチェーンにより、記録されたイベントシーケンス内での改ざんが検出可能になります。ただし、直接アクセスを持つデータベース管理者は、理論上チェーンを削除して再構築することができます。より強固な保証には外部タイムスタンプやサードパーティの証明が必要ですが、このバージョンでは実装されていません。

2.10 アイデンティティレベル

レベル要件信頼プロパティユースケース
認証済み メールが確認済みのサインイン中のPDF Proユーザー;アカウントに登録された永続鍵ペア Supabase Authによるメール確認;認証済みアカウントに公開鍵がバインド;監査証跡がユーザーIDにリンク ビジネス文書、契約書、正式な合意
自己申告 ゲストユーザーまたは自己入力の名前を持つ認証済みユーザー;一時的または永続的な鍵ペア 暗号完全性は保証;署名者のアイデンティティは自己申告であり、独立して確認されていない クイック署名、個人文書、非公式な合意

注記: 製品UIでは、「self_asserted」は「自己申告アイデンティティ」または「ゲスト署名」として表示される場合があります。「authenticated」は「認証済みアカウント」として表示される場合があります。これらは同じ基礎アイデンティティレベルの表示ラベルです。

アイデンティティバインディング: 「認証済み」署名は、公開鍵がメール確認済みのPDF Proアカウントに登録されていることを意味します。署名者の実世界のアイデンティティが政府ID、生体認証、または対面確認によって確認されたことを意味するものではありません。当社はKYC(本人確認)チェックを実施していません。

2.11 脅威モデル

脅威攻撃ベクター対策
リプレイ攻撃 攻撃者が有効な署名をコピーして別のドキュメントに適用 署名は特定のドキュメントのSHA-256ハッシュにバインドされています。異なるドキュメントは異なるハッシュを持ち、ECDSA検証は失敗します。
偽造 攻撃者が秘密鍵なしに有効な署名を作成 ECDSA P-256のセキュリティは楕円曲線離散対数問題(ECDLP)に基づいています。秘密鍵なしで署名を偽造することは計算上不可能です(128ビットセキュリティレベル)。
鍵の置換 攻撃者が自分の公開鍵を登録し、署名が他の人によって作成されたと主張 認証済み署名は公開鍵を確認済みメールにバインドします。監査証跡はどの鍵がどのドキュメントに署名したかを記録します。鍵登録イベントはハッシュチェーン化されています。
ドキュメントの置換 攻撃者が署名済みPDFを変更し、署名がまだ有効だと主張 PDFへのいかなる変更もSHA-256ハッシュを変更します。既存の署名は新しいハッシュに対して検証が失敗します。衝突の発見(同じハッシュを持つ別のドキュメント)には約2^128回の操作が必要です。
秘密鍵の盗取 攻撃者がIndexedDBから暗号化された秘密鍵を抽出 秘密鍵はPBKDF2(60万回の反復)でキーされたAES-256-GCMで暗号化されています。パスフレーズなしでは、鍵の復号は計算上不可能です。
サーバーの侵害 攻撃者がサーバーフルアクセスを取得 サーバーは公開鍵と署名レコードのみを持ちます。秘密鍵はサーバーに到達しません。攻撃者は新しい署名を偽造できません。既存のレコードを削除・変更することはできますが、ハッシュチェーンの破損が検出可能になります。
監査証跡の改ざん 攻撃者がサーバー上の監査証跡イベントを変更 ハッシュチェーン化されたイベント:いずれかのイベントを変更すると、その時点以降のチェーンが壊れます。独立した検証ツールがチェーンの破損を検出できます。

2.11.1 前提条件

2.11.2 対象外

2.12 正直な開示

PDF Proの署名でないもの:

2.12.1 PDF Pro署名が適しているもの

当社のコミットメント: 当社はマーケティングではなく、アーキテクチャを通じてセキュリティを構築します。これらのホワイトペーパーは、制限事項を含め、当社のシステムがどのように機能するかを正確に説明しています。セキュリティ意識の高いユーザーは完全な技術的透明性を求めていると信じています。アーキテクチャに関するご質問は、info@webdesign9.com までご連絡ください。