把沾着人的日志变成可以送出网外的样子
한국어 원문으로 표시합니다.
목표
사람과 조직이 묻은 운영 로그에서 식별자를 가려내고, 열쇠에 매인 결정적 가명화와 마스킹을 갈라 적용하고, 남는 재식별 위험을 일반화로 줄인 뒤, 반출 꾸러미를 기계로 자기 검증해 내보냅니다.
왜 중요한가
폐쇄망에서 못 푸는 장애가 나면 로그를 밖으로 보내야 하는 순간이 옵니다. 그때 사번을 별표로 덮으면 심사는 통과하지만 분석이 죽습니다. 장애 분석이 쓰는 사실은 대개 값 자체가 아니라 값이 같다는 관계이기 때문입니다. 그래서 필요한 것이 같은 값을 늘 같은 가명으로 바꾸되 되돌릴 수는 없게 만드는 함수이고, 그 자리를 열쇠 있는 해시가 맡습니다. 이 실습에서 어려운 부분은 가명 함수가 아니라 무엇이 식별자인지 세는 일입니다. 이름표가 붙은 필드는 쉽고, 메시지 본문에 문장처럼 박힌 값과 인코딩 뒤에 숨은 값이 반출물을 새게 합니다.
단계
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 를 만드세요. 방법서는 ## 무엇을 바꿨나·## 가명은 어떻게 만들었나·## 무엇을 지웠나·## 남은 위험·## 무결성 다섯 절이고, 매핑표와 열쇠는 꾸러미에 넣지 않습니다.
받는 쪽은 가명만 봅니다. 그래서 무엇이 어떤 규칙으로 바뀌었는지 설명이 함께 가지 않으면 그 자료는 읽을 수 없는 자료가 됩니다. 무결성 해시는 파일을 마지막으로 고친 뒤에 뜨세요. 그리고 꾸러미에 무엇이 들어갔는지 목록으로 한 번 더 보세요 — 금고를 같이 넣는 사고가 가장 흔합니다.