PDF Proの暗号技術に関する詳細な技術ドキュメント
エンドツーエンド暗号化ファイル転送
PDF Pro ホワイトペーパー WP-001 — アーキテクチャとセキュリティ
本ホワイトペーパーでは、PDF Proのセキュア転送システムのアーキテクチャについて説明します。このシステムはエンドツーエンド暗号化ファイル転送の仕組みであり、ファイルはアップロード前にAES-256-GCMを使用してクライアントサイドで暗号化されます。サーバーは不透明な暗号文のみを保存し、いかなる時点においてもファイルの内容を復号・検査・読み取る能力を持ちません。システムは2つの主要モードをサポートします。1つはURLフラグメントを介して転送される自動生成ランダム鍵(サーバーには送信されません)、もう1つはPBKDF2を使用したパスフレーズ派生鍵です。いずれのモードでも、暗号化鍵は送信者と受信者のブラウザ内にのみ存在します。本ドキュメントでは、暗号プリミティブ、データフロー、脅威モデル、およびシステムの正直な制限事項について詳述します。用語についての注記:本システムはゼロ知識証明(ZKP)を使用していません。「サーバーはあなたのファイルについてゼロ知識である」と述べる場合、これはクライアントサイド暗号化の結果として、サーバーは復号できない暗号文のみを保持することを意味します。
セキュア転送システムは厳格なクライアントとサーバーの分離に従っており、すべての暗号処理は専らブラウザ内で行われます:
サーバーは意図的に暗号化データの「ダムパイプ」として設計されています。暗号化鍵、パスフレーズ、ファイルの内容については一切の知識を持ちません。これはポリシーによるものではなく、アーキテクチャ的に強制されています。
設計原則: サーバーが侵害されても、ユーザーデータが侵害されないようにする。完全なデータベースアクセスとサーバーサイドのコード実行権限を持つ攻撃者であっても、転送されたファイルを復号することはできません。
すべてのファイル暗号化は、ブラウザネイティブの Web Crypto API を通じてアクセスされるAES-256-GCM認証付き暗号化アルゴリズムを使用します。これにより、機密性(データを読み取れない)と完全性(検出なしにデータを改ざんできない)の両方が提供されます。
| パラメータ | 値 | 根拠 |
|---|---|---|
| アルゴリズム | AES-256-GCM | NIST承認、関連データ付き認証暗号化(AEAD) |
| 鍵サイズ | 256ビット | 最大AES鍵長;ブルートフォースに対する128ビットセキュリティを提供 |
| IVサイズ | 96ビット(12バイト) | GCMモードにおけるNIST推奨IV長 |
| タグサイズ | 128ビット(16バイト) | 最大完全性保護のためのフル長認証タグ |
| IV生成 | crypto.getRandomValues() | 暗号学的に安全な乱数生成器 |
// 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認証タグを含む暗号文。このブロブがサーバーが受信・保存するものです。
セキュア転送は、相互に排他的な2つの鍵モードをサポートします。モードは転送作成時に送信者が選択します。
デフォルトモードでは、パスフレーズは関与しません。ブラウザは直接、暗号学的にランダムな256ビットのAES鍵を生成します:
crypto.getRandomValues() と crypto.subtle.generateKey() を使用してランダムな256ビットのAES-GCM鍵を生成します。#)に配置されます。送信者がパスフレーズの設定を選択した場合、PBKDF2を使用してそのパスフレーズから鍵が導出されます:
| パラメータ | 値 | 根拠 |
|---|---|---|
| アルゴリズム | PBKDF2 | NIST SP 800-132推奨;広く監査済み |
| ハッシュ関数 | SHA-256 | 標準暗号ハッシュ;256ビット出力 |
| 反復回数 | 600,000 | PBKDF2-SHA256に対するOWASP 2023推奨を満たす |
| ソルトサイズ | 128ビット(16バイト) | 転送ごとに一意;レインボーテーブル攻撃を防止 |
| 出力鍵長 | 256ビット | AES-256鍵要件に一致 |
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文字以上のパスフレーズを推奨します。
セキュア転送の完全なライフサイクルは次のパスをたどります:
crypto.getRandomValues() を使用して、ランダムな256ビットのAES-GCM鍵とランダムな12バイトのIVを生成します。#)に付加します。crypto.getRandomValues() を使用して、ランダムな16バイトのソルトと12バイトのIVを生成します。| データ要素 | サーバーがアクセス可能か | 詳細 |
|---|---|---|
| 暗号化ブロブ(ソルト+IV+暗号文+タグ) | はい | 不透明なバイナリデータ;サーバーは内容を解釈できない |
| 転送ID | はい | 転送識別子はPostgreSQLのgen_random_uuid()によって生成されるUUID v4値であり、サーバーのCSPRNGから122ビットの暗号学的ランダム性を提供します |
| 元のファイル名 | はい | 受信者への表示用にメタデータに保存 |
| 元のファイルサイズ | はい | 表示目的でメタデータに保存 |
| 有効期限タイムスタンプ | はい | 自動削除の実施に使用 |
| ダウンロード数/制限 | はい | 読み取り後消去とダウンロード制限の実施に使用 |
| 送信者ユーザーID(認証済みの場合) | はい | 管理のためにアカウントに転送をリンク |
| パスフレーズ | いいえ — 決して | サーバーには送信されない;ブラウザから出ることはない |
| 導出された暗号化鍵 | いいえ — 決して | 暗号化/復号操作中のブラウザメモリ内にのみ存在 |
| 平文ファイルの内容 | いいえ — 決して | 暗号化された暗号文のみがサーバーに到達する |
| PBKDF2反復回数 | いいえ | クライアントにハードコードされており;サーバーには送信されない |
すべてのセキュア転送は設計上、一時的なものです。永続的なストレージのオプションはありません。
| オプション | 動作 | 実施方法 |
|---|---|---|
| 読み取り後消去 | 最初のダウンロード成功後、暗号化ブロブは即座に削除される | サーバーサイド:ダウンロードストリーム完了後にストレージからブロブを削除 |
| 1時間 | ダウンロード状況に関わらず1時間後に自動削除 | サーバーサイド:定期クリーンアップジョブ+アクセス時の有効期限チェック |
| 24時間 | 24時間後に自動削除 | 上記と同様 |
| 7日間 | 最大保持期間;7日後に自動削除 | 上記と同様 |
転送が期限切れになるか読み取り後に消去されると、暗号化ブロブはSupabase Storageから完全に削除されます。メタデータレコードは、完全に消去される前に30日間ソフト削除状態で保持されます(不正使用調査のため)。メタデータレコードには、暗号化鍵、パスフレーズ、またはファイルの再構築に使用できる情報は含まれていません。
| 脅威 | 攻撃ベクター | 対策 |
|---|---|---|
| サーバーの侵害 | 攻撃者がデータベースとストレージへのフルアクセスを取得 | 保存されたすべてのデータは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があり、ダウンロード制限と有効期限によって保護されています。読み取り後消去転送は最初のアクセス後に削除されます。 |
正直な制限事項: 完璧なセキュリティシステムは存在しません。当社は既知の制限事項の透明な開示を信じています。
プライバシー優先の暗号文書署名
PDF Pro ホワイトペーパー WP-002 — アーキテクチャとセキュリティ
本ホワイトペーパーでは、PDF ProのPrivacy Signatureシステムのアーキテクチャについて説明します。このシステムは、PDFドキュメントが署名者のブラウザから出ることのない暗号文書署名の仕組みです。システムはP-256曲線とSHA-256ハッシュを使用したECDSAを使用して、デタッチされたデジタル署名を生成します。ドキュメントハッシュ、暗号署名、公開鍵のみがサーバーに送信されます。秘密鍵はIndexedDBを使用してユーザーのブラウザ内でのみ生成・暗号化・保存され、PBKDF2鍵導出(600,000回の反復)とAES-256-GCM暗号化によって保護されます。本ドキュメントでは、完全な署名と検証のアーキテクチャ、鍵管理モデル、署名済みペイロードスキーマ、監査証跡設計、脅威モデル、および正直な制限事項について詳述します。
Privacy Signatureシステムは、基本的な制約を中心に設計されています:PDFドキュメントはサーバーに送信されてはなりません。これはデタッチ署名モデルによってアーキテクチャ的に強制されています。
核心的保証: サーバーはPDFドキュメントを参照・受信・処理することは決してありません。サーバーがドキュメント関連で受信する唯一のデータは、SHA-256ハッシュ — 固定サイズの256ビット値であり、そこから元のドキュメントを再構築することはできません。
| パラメータ | 値 | 根拠 |
|---|---|---|
| 署名アルゴリズム | ECDSA(楕円曲線デジタル署名アルゴリズム) | NIST FIPS 186-4;コンパクトな署名;鍵ビットあたりの強力なセキュリティ |
| 曲線 | P-256(secp256r1 / prime256v1) | NIST承認;128ビットセキュリティレベル;Web Crypto APIの幅広いサポート |
| ハッシュ関数 | SHA-256 | NIST 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フォーマットです。
// 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 });
| 鍵の種類 | コンテキスト | ライフサイクル | ストレージ |
|---|---|---|---|
| 一時的 | ゲストユーザー(サインインしていない) | セッションごとに生成;タブを閉じると破棄 | メモリ内のみ(CryptoKeyオブジェクト);永続化されない |
| 永続的 | 認証済みユーザー(サインイン済み) | 一度生成;セッションをまたいで永続化;失効可能 | IndexedDB(PBKDF2+AES-256-GCMで暗号化) |
// 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として計算されます。
永続的な秘密鍵は平文で保存されることはありません。IndexedDBへの書き込み前に、秘密鍵(JWK JSONとしてエクスポート)はセキュア転送と同じパターンを使用して暗号化されます:
| パラメータ | 値 |
|---|---|
| 鍵導出 | PBKDF2-SHA256、600,000回の反復 |
| ソルト | ランダム16バイト(鍵ごと) |
| 暗号化 | AES-256-GCM |
| IV | ランダム12バイト(暗号化ごと) |
| 入力 | 秘密鍵JWK(JSON文字列、UTF-8エンコード) |
| IndexedDBに保存される出力 | { salt, iv, ciphertext, publicKeyJWK, keyId, createdAt } |
// 暗号化署名キーの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保護を迂回するメカニズムを持っていません。ユーザーは鍵のバックアップをエクスポートすることを推奨します。
PDF Proはデタッチ署名モデルを使用しています。これは署名がドキュメントとは別に保存されることを意味します。これが重要なプライバシーメカニズムです:ドキュメントは署名者のデバイスから出ることはありません。
暗号学的保証: SHA-256は一方向ハッシュ関数です。ハッシュ e3b0c44298fc1c14... のみが与えられた場合、ECDSAとSHA-256のセキュリティ前提のもと、元のドキュメントを再構築できないという強力な暗号学的保証を提供します。ハッシュは、再ハッシュ時のID確認を超えて、ドキュメントの内容、長さ、または構造については何も明らかにしません。
以下の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フェーズのプロセスです:クライアントサイドの暗号検証に続いて、サーバーサイドのクロスチェックが行われます。
const isValid = await crypto.subtle.verify( { name: "ECDSA", hash: "SHA-256" }, importedPublicKey, signatureBuffer, hashBuffer );
isValid === true の場合、署名は暗号学的に有効です:ドキュメントは署名以降改ざんされておらず、署名は対応する秘密鍵の保有者によって生成されました。| 結果 | 意味 |
|---|---|
| 有効(認証済み) | 署名は暗号学的に有効であり、公開鍵は登録済みの認証されたPDF Proユーザーに属します。 |
| 有効(自己申告) | 署名は暗号学的に有効ですが、署名者のアイデンティティは自己申告です(ゲストユーザーまたは未確認の名前)。 |
| 無効 | 暗号検証が失敗しました。ドキュメントは署名以降改ざんされているか、署名が破損しています。 |
| 失効済み | 署名は有効でしたが、署名者によって明示的に失効されました。 |
| 署名が見つかりません | このドキュメントハッシュに対する署名レコードが存在しません。 |
すべての署名および検証イベントは、改ざん防止の監査証跡に記録されます。イベントはハッシュチェーン化されています:各イベントには前のイベントのSHA-256ハッシュが含まれており、ブロックチェーンに似た追記専用のチェーンを形成します。
| イベント種別 | トリガー | 記録されるデータ |
|---|---|---|
KEY_REGISTERED | ユーザーが新しい公開鍵を登録 | 公開鍵JWK、ユーザーID、タイムスタンプ |
DOCUMENT_SIGNED | ユーザーがドキュメントに署名 | ドキュメントハッシュ、署名、公開鍵、署名者アイデンティティ、タイムスタンプ |
SIGNATURE_VERIFIED | 任意のユーザーが署名を検証 | ドキュメントハッシュ、検証結果、検証者情報(認証済みの場合)、タイムスタンプ |
SIGNATURE_REVOKED | 署名者が署名を失効 | 署名ID、失効理由、タイムスタンプ |
KEY_REVOKED | ユーザーが公開鍵を失効 | 公開鍵ID、失効理由、タイムスタンプ |
// 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.
チェーン内のいずれかのイベントが変更されると、それ以降のすべてのハッシュリンクが壊れ、改ざんが即座に検出可能になります。これにより、監査証跡の整合性が強力に保証されます。
重要な制限事項: ハッシュチェーンにより、記録されたイベントシーケンス内での改ざんが検出可能になります。ただし、直接アクセスを持つデータベース管理者は、理論上チェーンを削除して再構築することができます。より強固な保証には外部タイムスタンプやサードパーティの証明が必要ですが、このバージョンでは実装されていません。
| レベル | 要件 | 信頼プロパティ | ユースケース |
|---|---|---|---|
| 認証済み | メールが確認済みのサインイン中のPDF Proユーザー;アカウントに登録された永続鍵ペア | Supabase Authによるメール確認;認証済みアカウントに公開鍵がバインド;監査証跡がユーザーIDにリンク | ビジネス文書、契約書、正式な合意 |
| 自己申告 | ゲストユーザーまたは自己入力の名前を持つ認証済みユーザー;一時的または永続的な鍵ペア | 暗号完全性は保証;署名者のアイデンティティは自己申告であり、独立して確認されていない | クイック署名、個人文書、非公式な合意 |
注記: 製品UIでは、「self_asserted」は「自己申告アイデンティティ」または「ゲスト署名」として表示される場合があります。「authenticated」は「認証済みアカウント」として表示される場合があります。これらは同じ基礎アイデンティティレベルの表示ラベルです。
アイデンティティバインディング: 「認証済み」署名は、公開鍵がメール確認済みのPDF Proアカウントに登録されていることを意味します。署名者の実世界のアイデンティティが政府ID、生体認証、または対面確認によって確認されたことを意味するものではありません。当社はKYC(本人確認)チェックを実施していません。
| 脅威 | 攻撃ベクター | 対策 |
|---|---|---|
| リプレイ攻撃 | 攻撃者が有効な署名をコピーして別のドキュメントに適用 | 署名は特定のドキュメントのSHA-256ハッシュにバインドされています。異なるドキュメントは異なるハッシュを持ち、ECDSA検証は失敗します。 |
| 偽造 | 攻撃者が秘密鍵なしに有効な署名を作成 | ECDSA P-256のセキュリティは楕円曲線離散対数問題(ECDLP)に基づいています。秘密鍵なしで署名を偽造することは計算上不可能です(128ビットセキュリティレベル)。 |
| 鍵の置換 | 攻撃者が自分の公開鍵を登録し、署名が他の人によって作成されたと主張 | 認証済み署名は公開鍵を確認済みメールにバインドします。監査証跡はどの鍵がどのドキュメントに署名したかを記録します。鍵登録イベントはハッシュチェーン化されています。 |
| ドキュメントの置換 | 攻撃者が署名済みPDFを変更し、署名がまだ有効だと主張 | PDFへのいかなる変更もSHA-256ハッシュを変更します。既存の署名は新しいハッシュに対して検証が失敗します。衝突の発見(同じハッシュを持つ別のドキュメント)には約2^128回の操作が必要です。 |
| 秘密鍵の盗取 | 攻撃者がIndexedDBから暗号化された秘密鍵を抽出 | 秘密鍵はPBKDF2(60万回の反復)でキーされたAES-256-GCMで暗号化されています。パスフレーズなしでは、鍵の復号は計算上不可能です。 |
| サーバーの侵害 | 攻撃者がサーバーフルアクセスを取得 | サーバーは公開鍵と署名レコードのみを持ちます。秘密鍵はサーバーに到達しません。攻撃者は新しい署名を偽造できません。既存のレコードを削除・変更することはできますが、ハッシュチェーンの破損が検出可能になります。 |
| 監査証跡の改ざん | 攻撃者がサーバー上の監査証跡イベントを変更 | ハッシュチェーン化されたイベント:いずれかのイベントを変更すると、その時点以降のチェーンが壊れます。独立した検証ツールがチェーンの破損を検出できます。 |
PDF Proの署名でないもの:
当社のコミットメント: 当社はマーケティングではなく、アーキテクチャを通じてセキュリティを構築します。これらのホワイトペーパーは、制限事項を含め、当社のシステムがどのように機能するかを正確に説明しています。セキュリティ意識の高いユーザーは完全な技術的透明性を求めていると信じています。アーキテクチャに関するご質問は、info@webdesign9.com までご連絡ください。