バックアップの保持と鍵の保護
バックアップと鍵のそれぞれに対する破壊経路と、保持条件を説明します。
説明
バックアップを復旧に使うには、保存データだけでなく復号鍵も利用できる必要があります。削除権限、保持期限、管理主体の分離をそれぞれ点検します。
SQLiteのコピーをAES-GCMで暗号化し、固定の保管権限モデルで削除条件を試します。データが残っていても鍵の削除で復旧できなくなる例を確認します。
バックアップと鍵のそれぞれに対する破壊経路と、保持条件を説明します。
1バックアップ世代と管理主体を読む
b7はbackup-account、鍵管理は別のkey-accountというモデルです。
from sp22 import *
from sp02 import showバックアップ世代と管理主体を読む
lab=Backup()
show(lab.db,"SELECT id,account,retain_until,hold FROM backup")
show(lab.db,"SELECT * FROM permission ORDER BY actor")アプリ管理者には削除権限がなく、バックアップ管理者と鍵管理者の権限も分かれています。実アカウント分離の有効性は、委譲や共通の管理経路も確認します。
2元データと暗号化後の長さを確認する
実際に作ったSQLiteコピーのバイト数です。
print(len元データと暗号化後の長さを確認する(lab.original),len(lab.cipher))
print(b'SQLite format 3' in lab.original,b'SQLite format 3' in lab.cipher)暗号文は認証タグ分の16バイトだけ長くなります。固定nonceは同じ一つの公開試料の再現に使い、別内容へ再利用しません。
3アプリ管理者による削除を拒否する
保持期限を過ぎていても権限を確認します。
print(lab.deleteアプリ管理者による削除を拒否する('app-admin',101))
show(lab.db,"SELECT id FROM backup")permission_deniedでb7は残ります。期限の判定だけで削除を許す設計ではありません。
4権限があっても保持期限内は削除しない
バックアップ管理者で99秒を指定します。
print(lab.delete権限があっても保持期限内は削除しない('backup-admin',99))
show(lab.db,"SELECT id,retain_until FROM backup")retainedです。このモデルは期限内の削除を認めません。実サービスでは保持モードや例外権限を含めて評価します。
5期限のない保留条件を加える
holdを1にして期限後も保持します。
lab.db.execute("UPDATE backup SET hold=1 WHERE id='b7'")
print(lab.delete期限のない保留条件を加える('backup-admin',101))retainedのままです。期限と保留は別の条件として評価されています。
6データが残ったまま鍵を失う場合を試す
教材DB内の公開試験鍵だけを削除します。
lab.db.execute("DELETE FROM key_store WHERE id='k7'")
print(lab.restoreデータが残ったまま鍵を失う場合を試す())
show(lab.db,"SELECT id FROM backup")key_missingで復旧できません。b7が残っていることだけでは復旧可能性を保証できないと分かります。
7保管していた別コピーの鍵で復旧する
固定の別保管試験鍵を再登録し、復旧結果を確認します。
lab.db.execute("INSERT INTO key_store VALUES (?,?)",('k7',PUBLIC_KEY))
restored=lab.restore保管していた別コピーの鍵で復旧する()
show(restored,"SELECT * FROM orders ORDER BY id")
restored.close()100と200の2行を取得できました。鍵の別保管も、権限・取得手順・実際の復号まで確かめます。
まとめ
データと鍵の管理権限を別々に点検します。
期限と保留の両方を確認します。
保存の存在だけでなく復号と復旧を試します。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite backup / AES-GCM / 固定の保管権限モデル
from sp22 import *
from sp02 import show
lab=Backup()
show(lab.db,"SELECT id,account,retain_until,hold FROM backup")
show(lab.db,"SELECT * FROM permission ORDER BY actor")id | account | retain_until | hold b7 | backup-account | 100 | 0 actor | account | action backup-admin | backup-account | delete key-admin | key-account | delete_key restore-operator | backup-account | read
print(len(lab.original),len(lab.cipher))
print(b'SQLite format 3' in lab.original,b'SQLite format 3' in lab.cipher)8192 8208 True False
print(lab.delete('app-admin',101))
show(lab.db,"SELECT id FROM backup")permission_denied id b7
print(lab.delete('backup-admin',99))
show(lab.db,"SELECT id,retain_until FROM backup")retained id | retain_until b7 | 100
lab.db.execute("UPDATE backup SET hold=1 WHERE id='b7'")
print(lab.delete('backup-admin',101))retained
lab.db.execute("DELETE FROM key_store WHERE id='k7'")
print(lab.restore())
show(lab.db,"SELECT id FROM backup")key_missing id b7
lab.db.execute("INSERT INTO key_store VALUES (?,?)",('k7',PUBLIC_KEY))
restored=lab.restore()
show(restored,"SELECT * FROM orders ORDER BY id")
restored.close()id | amount 1 | 100 2 | 200
演習完了