一覧SP-10-1 · DLP:機微情報の識別と制御

DLPの情報識別方式

識別条件、読める範囲、宛先別の制御と監査記録を分けて評価します。

説明

DLPは機微情報を識別し、持出しなどの操作に規則を適用します。文字列の形式、登録データとの一致、付与されたラベルは異なる根拠であり、どれか一つがすべての内容を識別するわけではありません。

EMPから始まる架空のIDを使い、正規表現による検査と登録値との照合を比較します。最後にAES-GCMで暗号化したデータを使い、鍵の有無で検査できる範囲がどう変わるかを確認します。

識別条件、読める範囲、宛先別の制御と監査記録を分けて評価します。

1本文と登録値を開く

EMP-0042とEMP-0071だけを登録済みとします。

from sp10 import * print(TEXT) print(sorted本文と登録値を開く(KNOWN))

本文には登録値、未登録の同形式値、長い文字列に埋まった値があります。これらを同じ条件で検査します。

2広いパターンの一致を確認する

境界条件を持たない正規表現です。

print(re.findall広いパターンの一致を確認する(r'EMP-[0-9]{4}',TEXT))

埋込み文字列の途中もEMP-0042として一致します。形式が同じだけでは独立したIDの出現とは限りません。

3前後の英数字を除外する

前後に英大文字や数字がある一致を除くパターンです。

print(PATTERN.pattern) found=PATTERN.findall前後の英数字を除外する(TEXT) print(found)

EMP-0042とEMP-9999の2件が残ります。この境界は教材のID書式に合わせた条件で、日本語や任意の識別子すべての区切り規則ではありません。

4登録データとの完全一致を加える

形式一致から登録済みの値だけを抽出します。

print([x for x in found if x in KNOWN登録データとの完全一致を加える])

EMP-0042だけです。登録値照合は未知の値を見つける方法ではありません。登録範囲や更新時点も検査範囲に影響します。

5ラベルと内容検査の結果を並べる

ラベルは固定の文書属性として与えます。

files=[('a.txt','internal',TEXT),('b.txt','confidential','public sample')] for name,label,body in files: print(name,label,[x for x in PATTERN.findallラベルと内容検査の結果を並べる(body) if x in KNOWN])

aはinternalでも登録値を含み、bはconfidentialでも今回のIDはありません。ラベルの付与方法と内容検査の根拠を混ぜずに扱います。

6暗号化した内容への文字列検索を試す

公開試験鍵と固定nonceで一つの試料を作成します。

aes=AESGCM(PUBLIC_KEY) nonce=bytes(range(12)) cipher=aes.encrypt暗号化した内容への文字列検索を試す(nonce,TEXT.encode(),b'file:a') print(len(TEXT.encode()),len(cipher)) print(b'EMP-0042' in cipher)

暗号文には平文のIDがそのまま現れません。固定nonceはこの単一の再現試料用で、同じ鍵による別の暗号化に再利用しません。

7鍵と認証情報を使って検査可能な値へ戻す

同じ鍵、nonce、付加認証データで復号します。

plain=aes.decrypt鍵と認証情報を使って検査可能な値へ戻す(nonce,cipher,b'file:a').decode() print(plain==TEXT) print([x for x in PATTERN.findall(plain) if x in KNOWN])

元の本文と一致し、登録値が見つかります。暗号文しか見えない検査地点と、復号できる地点では識別できる範囲が変わります。

8認証に失敗したデータを正常な空文書にしない

別のファイル用の認証情報で復号します。

try: aes.decrypt認証に失敗したデータを正常な空文書にしない(nonce,cipher,b'file:b') except InvalidTag as e: print(type(e).__name__)

InvalidTagです。検査不能を「機微情報なし」に変換すると、読めなかったデータを許可してしまいます。

まとめ

形式一致と登録データ一致は別の識別条件です。

ラベルと内容検査の根拠を確認します。

暗号化などによる検査不能を陰性と扱いません。

操作履歴と解説を振り返れます。

Python 3.15 / AES-GCM / SQLiteの配送待ちモデル

1
from sp10 import * print(TEXT) print(sorted(KNOWN))
owner=EMP-0042; sample=EMP-9999; embedded=XEMP-0042Z
['EMP-0042', 'EMP-0071']
2
print(re.findall(r'EMP-[0-9]{4}',TEXT))
['EMP-0042', 'EMP-9999', 'EMP-0042']
3
print(PATTERN.pattern) found=PATTERN.findall(TEXT) print(found)
(?<![A-Z0-9])EMP-[0-9]{4}(?![A-Z0-9])
['EMP-0042', 'EMP-9999']
4
print([x for x in found if x in KNOWN])
['EMP-0042']
5
files=[('a.txt','internal',TEXT),('b.txt','confidential','public sample')] for name,label,body in files: print(name,label,[x for x in PATTERN.findall(body) if x in KNOWN])
a.txt internal ['EMP-0042']
b.txt confidential []
6
aes=AESGCM(PUBLIC_KEY) nonce=bytes(range(12)) cipher=aes.encrypt(nonce,TEXT.encode(),b'file:a') print(len(TEXT.encode()),len(cipher)) print(b'EMP-0042' in cipher)
52 68
False
7
plain=aes.decrypt(nonce,cipher,b'file:a').decode() print(plain==TEXT) print([x for x in PATTERN.findall(plain) if x in KNOWN])
True
['EMP-0042']
8
try: aes.decrypt(nonce,cipher,b'file:b') except InvalidTag as e: print(type(e).__name__)
InvalidTag

演習完了