限度額を上げた人を証明する
目標
その場でのUPDATEで消えた証拠を数字で浮かび上がらせ、正規化シリアライズとハッシュチェーンで追記のみの監査記録を作ったうえで、協力会社の持ち出し版の改ざんを見つけ出し、HMACと相関IDまで付けて証跡バンドルを出します。
なぜ重要なのか
監査で争うのは値ではなく経緯です。現在の限度額だけを保存するシステムは、「誰がいつなぜ上げたか」に答えられず、その答えがなければ、正しい値も説明できない値になります。 ハッシュチェーンは、記録を直せなくする仕組みではなく、直せば表に出るようにする仕組みです。そのため、同じイベントが常に同じバイトになる正規化シリアライズがまず必要で、チェーンをまるごと再計算する偽造を防ぐには、鍵が必要です。 採点ツールは、書かれたハッシュを信用しません。元のデータから最初から再計算して突き合わせ、実行のたびに異なる乱数ベクターと、新しく作ったチェーンで、作成したツールを試します。
ステップ
- 材料スクリプトを/root/audit/gen_audit.pyとして保存して実行し、/root/audit/core.dbと/root/audit/vendor_chain.jsonlを作ってください。
- 月初のスナップショットと現在の限度額を突合し、消えた証拠を/root/audit/lost.txtにchanged・ticketed・untraceable・mismatched・raised_totalで書いてください。
- /root/audit/canon.pyを作成し、標準入力のJSON行ごとに、正規化シリアライズしたバイトのsha256を1行ずつ出力するようにしてください。
- /root/audit/build_chain.pyで、app_log 400行を/root/audit/audit.dbのaudit_logテーブルにハッシュチェーンとして移してください。
- /root/audit/verify_chain.pyで協力会社の持ち出し版を検証し、見つけた箇所を/root/audit/tamper.txtに書いてください。
- /root/audit/hmac.keyと/root/audit/mac_chain.pyで、チェーンの上にMACを載せて/root/audit/audit_mac.jsonlを作ってください。
- 相関IDでイベントをリクエスト単位に束ね直し、/root/audit/corr.txtに書いてください。
- /root/audit/evidence/manifest.jsonと/root/audit/audit_report.mdで、証跡バンドルを出してください。
参考
- 監査記録のハッシュルール: seq・ts・corr_id・actor・action・target・amount・prev_hashの8つのキーを正規化シリアライズしたバイトのsha256です。最初の項目のprev_hashは、0が64個です。
- 協力会社のチェーンのハッシュルールは異なります: prev_hash、seq、ts、actor、action、target、amountをこの順に縦棒1つでつないだ文字列のsha256です。
- MACのルール: entry_hash・prev_mac・seqの3つのキーを正規化シリアライズしたバイトに対するHMAC-SHA256で、鍵は、ファイルに書かれた16進数の文字列のASCIIバイトをそのまま使います。
- verify_chain.pyの出力契約: 問題ごとに1行で
BAD seq=<번호> reason=content|link|missing、きれいならOK lines=<줄수>と終了コード0、問題があれば1です(プレースホルダーは、順に番号と行数です)。 - sqlite3は
sqlite3 -readonly /root/audit/core.db "SELECT ..."で接続します。Pythonではsqlite3.connect("file:/root/audit/core.db?mode=ro", uri=True)です。 - よくある間違い: json.dumpsのデフォルト(ensure_ascii=True)でハングルをエスケープしてしまう、チェーンの最初の項目のprev_hashを空文字列にする、鍵ファイルを644にする。
限度額のスナップショットと協力会社の持ち出し版を作る
材料スクリプトを/root/audit/gen_audit.pyとして保存して実行し、/root/audit/core.dbと/root/audit/vendor_chain.jsonlを作ってください。
まず/root/auditを作成し、その中でpython3で実行します。テーブルはlimit_opening、customer_limit、change_ticket、app_logの4つで、協力会社のチェーンは399行です。
その場でのUPDATEが消したものを数える
月初のスナップショットと現在の限度額を突合し、/root/audit/lost.txtにchanged・ticketed・untraceable・mismatched・raised_totalを書いてください。
limit_openingとcustomer_limitをcustomer_idで結合し、限度額が異なる顧客を数えます。そのうち、change_ticketがない件が、誰にも説明できない変更で、申請書のnew_limitと今の値が違う件は、承認と反映が分かれた箇所です。
同じイベントを常に同じバイトにする
/root/audit/canon.pyを作成し、標準入力のJSON行ごとに、正規化シリアライズしたバイトのsha256を1行ずつ出力するようにしてください。
キーの並べ替え、空白のない区切り文字、非ASCIIをエスケープしないUTF-8の3つがすべてです。Pythonのjson.dumpsのsort_keys、separators、ensure_asciiを見てください。入れ子のオブジェクトのキーも、一緒に並べ替える必要があります。
ログ400行をハッシュチェーンで束ねる
/root/audit/build_chain.pyでapp_logを/root/audit/audit.dbのaudit_logテーブルに移し、prev_hash・entry_hashを埋めてください。
列はseq・ts・corr_id・actor・action・target・amount・prev_hash・entry_hashです。entry_hashは、最初の7つの値とprev_hashをまとめたオブジェクトを正規化シリアライズしたバイトのsha256で、最初の項目のprev_hashは0が64個です。採点ツールはcore.dbから再計算して突き合わせます。
協力会社の持ち出し版で手が加えられた箇所を探す
/root/audit/verify_chain.pyでvendor_chain.jsonlを検証し、/root/audit/tamper.txtにcontent_bad_seq・link_bad_seq・missing_seq・total_linesを書いてください。
協力会社のチェーンのハッシュは、prev_hash・seq・ts・actor・action・target・amountを縦棒でつないだ文字列のsha256です。内容を直した箇所は、その行のentry_hashがずれ、項目が抜けた箇所は、次の行のprev_hashがずれます。2つの症状は違います。
チェーンの上に鍵を載せる
/root/audit/hmac.key(16進数64文字、権限600)と/root/audit/mac_chain.pyで、/root/audit/audit_mac.jsonlを作ってください。
鍵はopenssl rand -hex 32で作り、chmod 600します。MACは、entry_hash・prev_mac・seqの3つのキーを正規化シリアライズしたバイトに対するHMAC-SHA256で、最初の行のprev_macは0が64個です。鍵の文字列が記録ファイルの中に入ってはいけません。
イベントを1つのリクエストに束ね直す
相関IDでイベントを束ね直し、/root/audit/corr.txtにno_corr・corr_groups・corr_of_seq140・target_of_seq140・events_in_group・actors_in_groupを書いてください。
corr_idが空文字列の行は、あとでどのリクエストの一部だったかを復元できません。seq 140は、協力会社の持ち出し版で内容がずれていた、まさにその箇所です。そのイベントのcorr_idでapp_logを再び走査して、いくつのシステムを経たかを見てください。
証跡バンドルとレポートを出す
/root/audit/evidence/manifest.jsonにfiles・chain・verified・vendor_findingsを入れ、/root/audit/audit_report.mdに5つの節のレポートを書いてください。
manifestのfilesは、path・sha256・bytesを持つオブジェクトの配列で、audit.db・audit_mac.jsonl・vendor_chain.jsonlがすべて入る必要があります。chainにはrows・genesis・headを書きます。採点ツールは、書かれたハッシュを実物から再計算して突き合わせます。レポートの節の見出しは、確認したこと、証拠が消えた箇所、チェーンと検証、協力会社の持ち出し版、勧告です。