사람이 묻은 로그를 밖으로 보낼 수 있게 만들기
목표
사람과 조직이 묻은 운영 로그에서 식별자를 가려내고, 열쇠에 매인 결정적 가명화와 마스킹을 갈라 적용하고, 남는 재식별 위험을 일반화로 줄인 뒤, 반출 꾸러미를 기계로 자기 검증해 내보냅니다.
왜 중요한가
폐쇄망에서 못 푸는 장애가 나면 로그를 밖으로 보내야 하는 순간이 옵니다. 그때 사번을 별표로 덮으면 심사는 통과하지만 분석이 죽습니다. 장애 분석이 쓰는 사실은 대개 값 자체가 아니라 값이 같다는 관계이기 때문입니다. 그래서 필요한 것이 같은 값을 늘 같은 가명으로 바꾸되 되돌릴 수는 없게 만드는 함수이고, 그 자리를 열쇠 있는 해시가 맡습니다. 이 실습에서 어려운 부분은 가명 함수가 아니라 무엇이 식별자인지 세는 일입니다. 이름표가 붙은 필드는 쉽고, 메시지 본문에 문장처럼 박힌 값과 인코딩 뒤에 숨은 값이 반출물을 새게 합니다.
단계
python3로/root/deid/data에 여섯 개 자료 파일을 만듭니다. 생성 스크립트를 그대로 쓰세요.- 필드마다 분류와 고유값 수와 처리 방법을
/root/deid/classify.csv에 적습니다. - 정규식이 필드에서 찾은 값과 놓친 값을
/root/deid/scan.json에 적습니다. - 열쇠에 매인 가명 함수를 만들어
/root/deid/vault/map.csv와/root/deid/vault/proof.json을 남깁니다. - 가명화와 마스킹을 갈라 적용해
/root/deid/out/access.deid.log와/root/deid/out/app.deid.log를 만듭니다. - 준식별자 조합으로 유일해지는 행을 세어
/root/deid/risk.json에, 일반화한 분석표를/root/deid/out/events.csv에 남깁니다. - 반출물을 원본 식별자 목록으로 대조한 결과를
/root/deid/selfcheck.json에 적습니다. /root/deid/release에 가명 자료와 방법서와 무결성만 담은 반출 꾸러미를 만듭니다.
참고
- 식별자 패턴, 마스킹할 필드, 인코딩된 필드, k 기준값은 모두
/root/deid/data/policy.json에 있습니다. 숫자나 정규식을 코드에 박지 말고 그 파일에서 읽으세요. - 가명 열쇠는
/root/deid/data/key.hex에 있습니다. 이 파일은 망 안에 남고 반출 꾸러미에는 들어가지 않습니다. - 가명은
HMAC-SHA256(열쇠, 종류 + "|" + 값)의 16진 출력 앞pseudo_len글자에prefix를 붙인 것입니다. 예:EMP-0123456789ab. - 변환 순서가 결과를 바꿉니다. 자유 서술 필드를 먼저 마스킹하고, 인코딩된 필드를 디코딩해 가명으로 바꾼 다음, 남은 줄 전체에서 패턴에 걸리는 것을 가명으로 바꿉니다.
- 기준일은
/root/deid/data/asof.txt에 있습니다.date로 오늘을 쓰면 같은 자료에서 날마다 다른 답이 나옵니다. - 흔한 실수 1: 이름표가 붙은 필드만 훑는 것. 메시지 본문과 인코딩된 값은 그렇게 해서는 나오지 않습니다.
- 흔한 실수 2: 매핑표를 반출 꾸러미에 함께 넣는 것. 그 파일이 들어가면 가명화를 하지 않은 것과 같습니다.
- 표준 문서: RFC 2104, FIPS 198-1, NIST SP 800-92, NIST IR 8053. 이 실습의 필드 분류와 k 기준값은 표준의 통제 번호가 아니라 자료 안에서만 쓰는 이 실습의 가정입니다.
비식별의 바탕이 될 자료 만들기
python3 로 /root/deid/data 에 access.log·app.log·roster.csv·policy.json·key.hex·asof.txt 여섯 개를 만듭니다. 난수를 쓰지 않는 생성 스크립트를 그대로 쓰세요.
폐쇄망에는 내려받을 표본이 없으니 자료부터 직접 만듭니다. 난수를 쓰지 않아야 누가 몇 번을 돌려도 같은 자료가 나오고, 서로의 판정을 대조할 수 있습니다. 채점기는 자료를 표준형으로 바꿔 지문을 대조하므로 자료를 손으로 고치면 뒤 단계가 전부 막힙니다.
어떤 필드가 무엇인지 가르기
/root/deid/classify.csv 에 첫 줄 field,category,distinct_values,action 을 두고, policy.json 의 fields 마다 한 줄씩 적으세요. distinct_values 는 그 필드가 자료에서 갖는 고유값 수이고, action 은 action_by_category 가 그 분류에 정해 놓은 처리입니다.
분류는 조직이 정한 것이라 policy.json 에 이미 적혀 있습니다. 당신이 할 일은 그 분류에 맞는 처리를 붙이고, 자료를 실제로 세어 고유값 수를 채우는 것입니다. 고유값 수가 적은 열은 혼자서는 사람을 못 가리키지만 다른 열과 합치면 가릴 수 있습니다 — 그게 준식별자입니다.
정규식이 찾은 것과 놓친 것을 함께 세기
/root/deid/scan.json 에 field_values(종류별 필드 고유값 수), message_only(msg 안에만 있고 어떤 필드에도 없는 값), encoded(payload 를 base64 로 디코딩해 나온 값), note_only(note 안에만 있는 값) 네 항목을 적으세요. 뒤 세 항목은 정렬한 목록입니다.
이름표가 붙은 자리는 종류=값 으로 찾습니다. 그다음이 이 단계의 핵심입니다 — msg 와 note 안의 큰따옴표 사이를 따로 훑고, payload 는 먼저 디코딩한 뒤에 훑으세요. 어떤 정규식도 인코딩된 값을 원문 상태로는 찾지 못합니다.
열쇠에 매인 결정적 가명 만들기
/root/deid/vault/map.csv 에 첫 줄 kind,value,pseudonym 을 두고 자료에서 찾은 식별자마다 한 줄씩 적고, /root/deid/vault/proof.json 에 values·pseudonyms·collisions·stable·key_sensitive·alt_key_overlap 여섯 항목을 적으세요.
가명은 HMAC-SHA256 으로 만듭니다. 종류와 값을 세로줄로 이어 붙여 넣으면 사번과 주소가 우연히 같은 문자열이어도 가명이 갈립니다. 시험은 세 가지입니다 — 같은 값을 두 번 계산해 같은가, 서로 다른 값이 같은 가명이 되지 않는가, policy.json 의 다른 열쇠로 계산하면 가명 집합이 하나도 겹치지 않는가. 이 금고는 망 안에 남습니다.
가명화할 것과 마스킹할 것을 갈라 적용하기
/root/deid/out/access.deid.log 와 /root/deid/out/app.deid.log 를 만드세요. 자유 서술 필드는 policy.json 의 mask_token 으로 통째로 바꾸고, 인코딩된 필드는 디코딩한 값의 가명으로 바꾸고, 나머지 패턴은 모두 가명으로 바꿉니다. 줄 수와 줄 순서는 원본과 같아야 합니다.
순서가 결과를 바꿉니다. 마스킹을 먼저 하지 않으면 자유 서술 안의 값이 가명으로 바뀌어 남고, 그러면 지워야 할 것이 지워지지 않은 채 나갑니다. 인코딩된 필드는 디코딩해서 어떤 종류인지 판정한 뒤 그 종류의 가명을 붙이세요 — 같은 사람이 원문으로 나온 자리와 같은 가명이 되어야 합니다.
직접 식별자를 다 바꿔도 남는 위험 세기
/root/deid/risk.json 에 rows·k·groups_before·unique_before·groups_after·unique_after 여섯 수를 적고, /root/deid/out/events.csv 에 첫 줄 pseudo_emp,dept,grade,hour 를 둔 일반화 분석표를 접속 로그 줄 순서대로 남기세요.
준식별자 조합은 policy.json 의 quasi 에 적혀 있습니다. 부서와 직급은 명부에서, 시각은 접속 로그에서 옵니다. 먼저 분 단위 시각으로 묶어 같은 조합의 행이 k개 미만인 행을 세고, 그다음 시각을 시 단위로 버려 다시 세세요. 줄어든 만큼이 일반화로 산 안전이고, 잃은 정밀도가 그 값입니다.
반출물에 원본이 남았는지 기계로 대조하기
/root/deid/selfcheck.json 에 files_checked·forbidden_values·hits·pseudonyms_found 네 수를 적으세요. forbidden_values 는 자료에 있던 식별자 전체의 수이고, hits 는 그중 반출물에서 발견된 건수이며 0 이어야 합니다.
금지 목록은 가명 금고보다 넓습니다. 마스킹해서 없앤 값은 가명이 없지만 반출물에 나와서도 안 되기 때문입니다. 자유 서술 안의 값까지 목록에 넣으세요. 대조 대상은 out 디렉터리의 파일이고 금지 목록과 selfcheck 결과는 그 바깥에 둡니다 — 목록 자체가 가장 위험한 파일입니다.
금고는 안에 남기고 꾸러미만 내보내기
/root/deid/release 에 access.deid.log·app.deid.log·events.csv 세 파일과 /root/deid/release/method.md, /root/deid/release/SHA256SUMS 를 만드세요. 방법서는 ## 무엇을 바꿨나·## 가명은 어떻게 만들었나·## 무엇을 지웠나·## 남은 위험·## 무결성 다섯 절이고, 매핑표와 열쇠는 꾸러미에 넣지 않습니다.
받는 쪽은 가명만 봅니다. 그래서 무엇이 어떤 규칙으로 바뀌었는지 설명이 함께 가지 않으면 그 자료는 읽을 수 없는 자료가 됩니다. 무결성 해시는 파일을 마지막으로 고친 뒤에 뜨세요. 그리고 꾸러미에 무엇이 들어갔는지 목록으로 한 번 더 보세요 — 금고를 같이 넣는 사고가 가장 흔합니다.