아이디 마스킹 기준 - aidi maseuking gijun

마스킹 처리를 위한 TLD 파일 이용에 대해서 포스팅을 올렸었다.. 그런데 생각을 해보니 마스킹 기준을 알아야 될거 아닌감.. 이건 현 회사에서 사용하는 기준이기도 하지만, 기본적으로 금감원이라던지 기타 기관에서 개인정보 마스킹 체크를 할 때 항상 내려오는 기준이다.. [내가 보기엔 시간이 흐를수록 그 기준도 변화되는 듯하다.. 내가 처음 감사를 받을 때 마스킹 기준하고 비교하면, 또 틀려졌기 때문이다..]

고로.. 어떤 회사에서건 해당 방식을 기준으로 사용할 것이라고 생각되므로 나중에 내가 어떻게 쓸지 모르니 올려둔다.. 이것도 올리기에 앞서서.. 표나 그런거로 하면 좋을텐데.. 내 상황이 상황인지라 직접 다 타이핑 했다.. 아오;; 그래도 이렇게 올리고 나면 상당히 뿌듯하단 말이지.. 캬캬캬캬캬..

식별정보..

  • 성명 : 성명 중 성을 제외한 나머지 Ex. 김**
  • 성명 : 성명 중 이름의 첫 번째 글자 이상 Ex. 김*용
  • 성명[영문] : 영문 성명 중 앞 4자리 철자 노출 Ex. KIM **********
  • 주소[지번주소] : 읍/면/동 미만의 숫자 Ex. 서울시 서초구 서초동 *** 번지
  • 주소[도로명주소] : 도로명 이하의 건물번호 및 상세주소의 숫자 Ex. 서울시 종로구 세종대왕로 ***, *** 호(세종로)
  • 주소[도로명주소] : 건물번호, 상세주소(동/층/호) Ex. 서울시 영등포구 여의나루로 *, *** 동 **** 호
  • 주민번호[외국인 포함] : 뒤에서부터 7자리 Ex. 711231-*******
  • 주민번호[외국인 포함] : 성별이 필요한 경우에는 뒤에서부터 6자리 Ex. 711231-1******
  • CI : 88자리의 숫자 중 앞 7자리 노출 Ex. cDR34cv***** ~~ ****
  • 연락처 : 전화번호 또는 휴대폰 뒤 4자리 Ex. 02-1234-****, 010-1234-****
  • 여권번호 : 뒤에서부터 4자리 Ex. 12345****
  • 이메일주소 : ID 중 앞 2자리를 제외한 나머지 Ex. at******@gmail.com

고급정보..

  • 카드번호 : 카드번호 중 7~12 번째 숫자 또는 9~12 번째 숫자 Ex. 9430-20**-****-2399, 9430-2000-****-2399
  • 카드번호 : Amex 15자리 카드번호체계 동일하게 적용 Ex. 9430-20**-****-239, 9430-2000-****-239
  • 카드번호 : 국제카드업계 표준(PCI-DSS) 준용 Ex. 9430-****-****-239*
  • 카드유효기간 : 연/월을 모두 마스킹 Ex. **/**
  • 온라인 회원 ID : ID 중 앞 2자리를 제외한 나머지 Ex. at********
  • 계좌번호 : 뒤에서부터 5자리 변환(단, 회원사에 오너쉽이 있는 경우 해당 회원사의 요청 기준에 준함) Ex. 430-20-1*****, 484220-01-1*****, 103-910096-*****
  • I-PIN : 뒤에서부터 5자리 변환 Ex. 123*****
  • 고객의 IP 주소 : 앞에서부터 3자리 변환 Ex. ***.1.1.12

이상이다.. 내가 가지고 있는 정보 및 기준을 잡고 있는 것은 위와 같다.. 서두에도 얘기 했지만, 각 회사에 따라서 기준이 또 틀릴 수도 있다.. 그런 경우에는 당연히 해당 케이스에 준해서 작업을 하면 된다.. 조금 더 여건이 괜찮아서 표로 정리한다던지 하면 더 좋을텐데 그게 좀 아쉽다.. 포스팅을 하다보면 나도 모르게 욕심이 생기는 것 같다.. ㅎㅎ..

아이디 마스킹 기준 - aidi maseuking gijun

마스킹?

마스킹이 뭐냐면 마스크를 연상하면 쉽게 이해가 갈 것이다. 마스크를 쓰면 얼굴 반절정도를 가려주는 역할을 하게된다. 이처럼 고유정보에 해당될 수 있는 정보들을 웹사이트에서 표시할때 * , ?표시등을 활용해서 가려주는 역할을 하는것을 마스킹이라고 한다.

아이디 마스킹 기준 - aidi maseuking gijun

(출처 : 브랜디 QnA게시판)

위와 같이 많은 사이트들이 ID마스킹을 사용하고 있다.

SQL문에서 마스킹을 사용하는 방법

SUBSTR(REGEXP_REPLACE('donate3434', '(?<=.{3}).', '*'), 1, 6)

브랜디 홈페이지를 기준으로 생각해보면 세번째 글자 이후로는 마스킹처리가 되어있고, 총 여섯글자가 반환되고 있다.

우선적으로 정규식을 사용해서 3번째 글자 이후에 글자를 *처리하도록 한다..
그럼 다음과 같이 don*******형태로 나오게된다.

이를 SUBSTR로 첫 번째 글자 = 1 부터 여섯번째 글자 = 6 까지 출력되도록 다시 감싸준다.

아이디 마스킹 기준 - aidi maseuking gijun

그럼 don***라는 형태로 잘 나오게 된다.

[JavaScript ] 개인정보 마스킹 함수(이름 마스킹, 이메일 마스킹, 휴대폰 번호 마스킹, 주민번호 마스킹)

안녕하세요. 갓대희 입니다. 이번 포스팅은 [  개인정보 마스킹 하기 입니다. : ) 

아이디 마스킹 기준 - aidi maseuking gijun

▶ 개인정보 마스킹 함수

 - 사실 데이터를 프론트단에서 마스킹 처리하는건 선호하지 않지만, 꼭 프론트에서 한번더 마스킹 처리를 해야한다면 사용할 예정이다.

1. 이메일 마스킹

 - 1.1 @ 뒷부분 마스킹 처리 하지 않는 경우 

ex)

원본 데이터 : 
변경 데이터 : ab**********@naver.com

 - 1.2 @ 뒷부분도 마스킹 처리 하는 경우

ex)

원본 데이터 : abcdefg12345@naver.com 
변경 데이터 : ab**********@nav******

2. 휴대폰 번호 마스킹

ex1) 원본 데이터 : 01012345678, 변경 데이터 : 010****5678
ex2) 원본 데이터 : 010-1234-5678, 변경 데이터 : 010-****-5678
ex3) 원본 데이터 : 0111234567, 변경 데이터 : 011***4567
ex4) 원본 데이터 : 011-123-4567, 변경 데이터 : 011-***-4567

3. 주민등록 번호 마스킹 (Resident Registration Number, RRN Masking)
ex1) 원본 데이터 : 990101-1234567, 변경 데이터 : 990101-1******
ex2) 변경 데이터 : 9901011234567, 변경 데이터 : 9901011******

4. 이름 마스킹

ex1) 원본 데이터 : 갓댐희, 변경 데이터 : 갓댐*
ex2) 원본 데이터 : 하늘에수, 변경 데이터 : 하늘**
ex3) 원본 데이터 : 갓댐, 변경 데이터 : 갓*

let maskingFunc = {
	checkNull : function (str){
		if(typeof str == "undefined" || str == null || str == ""){
			return true;
		}
		else{
			return false;
		}
	},
	/*
	※ 이메일 마스킹
	ex1) 원본 데이터 : 
		 변경 데이터 : ab**********@naver.com
	ex2) 원본 데이터 : 
	     변경 데이터 : ab**********@nav******
	*/
	email : function(str){
		let originStr = str;
		let emailStr = originStr.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
		let strLength;
		
		if(this.checkNull(originStr) == true || this.checkNull(emailStr) == true){
			return originStr;
		}else{
			strLength = emailStr.toString().split('@')[0].length - 3;
			
			// ex1)  => ab**********@naver.com
			// return originStr.toString().replace(new RegExp('.(?=.{0,' + strLength + '}@)', 'g'), '*');

			// ex2)  => ab**********@nav******
			return originStr.toString().replace(new RegExp('.(?=.{0,' + strLength + '}@)', 'g'), '*').replace(/.{6}$/, "******");
		}
	},
	/* 
	※ 휴대폰 번호 마스킹
	ex1) 원본 데이터 : 01012345678, 변경 데이터 : 010****5678
	ex2) 원본 데이터 : 010-1234-5678, 변경 데이터 : 010-****-5678
	ex3) 원본 데이터 : 0111234567, 변경 데이터 : 011***4567
	ex4) 원본 데이터 : 011-123-4567, 변경 데이터 : 011-***-4567
	*/
	phone : function(str){
		let originStr = str;
		let phoneStr;
		let maskingStr;
		
		if(this.checkNull(originStr) == true){
			return originStr;
		}
		
		if (originStr.toString().split('-').length != 3)
		{ // 1) -가 없는 경우
			phoneStr = originStr.length < 11 ? originStr.match(/\d{10}/gi) : originStr.match(/\d{11}/gi);
			if(this.checkNull(phoneStr) == true){
				return originStr;
			}
			
			if(originStr.length < 11)
			{ // 1.1) 0110000000
				maskingStr = originStr.toString().replace(phoneStr, phoneStr.toString().replace(/(\d{3})(\d{3})(\d{4})/gi,'$1***$3'));
			}
			else
			{ // 1.2) 01000000000
				maskingStr = originStr.toString().replace(phoneStr, phoneStr.toString().replace(/(\d{3})(\d{4})(\d{4})/gi,'$1****$3'));
			}
		}else
		{ // 2) -가 있는 경우
			phoneStr = originStr.match(/\d{2,3}-\d{3,4}-\d{4}/gi);
			if(this.checkNull(phoneStr) == true){
				return originStr;
			}
			
			if(/-[0-9]{3}-/.test(phoneStr))
			{ // 2.1) 00-000-0000
				maskingStr = originStr.toString().replace(phoneStr, phoneStr.toString().replace(/-[0-9]{3}-/g, "-***-"));
			} else if(/-[0-9]{4}-/.test(phoneStr))
			{ // 2.2) 00-0000-0000
				maskingStr = originStr.toString().replace(phoneStr, phoneStr.toString().replace(/-[0-9]{4}-/g, "-****-"));
			}
		}
		
		return maskingStr;
	},
	/*
	※ 주민등록 번호 마스킹 (Resident Registration Number, RRN Masking)
	ex1) 원본 데이터 : 990101-1234567, 변경 데이터 : 990101-1******
	ex2) 원본 데이터 : 9901011234567, 변경 데이터 : 9901011******
	*/
	rrn : function(str){
		let originStr = str;
		let rrnStr;
		let maskingStr;
		let strLength;
		
		if(this.checkNull(originStr) == true){
			return originStr;
		}
		
		rrnStr = originStr.match(/(?:[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1,2][0-9]|3[0,1]))-[1-4]{1}[0-9]{6}\b/gi);
		if(this.checkNull(rrnStr) == false){
			strLength = rrnStr.toString().split('-').length;
			maskingStr = originStr.toString().replace(rrnStr,rrnStr.toString().replace(/(-?)([1-4]{1})([0-9]{6})\b/gi,"$1$2******"));
		}else {
			rrnStr = originStr.match(/\d{13}/gi);
			if(this.checkNull(rrnStr) == false){
				strLength = rrnStr.toString().split('-').length;
				maskingStr = originStr.toString().replace(rrnStr,rrnStr.toString().replace(/([0-9]{6})$/gi,"******"));
			}else{
				return originStr;
			}
		}
		return maskingStr;
	},
	/*
	※ 이름 마스킹
	ex1) 원본 데이터 : 갓댐희, 변경 데이터 : 갓댐*
	ex2) 원본 데이터 : 하늘에수, 변경 데이터 : 하늘**
	ex3) 원본 데이터 : 갓댐, 변경 데이터 : 갓*
	*/
	name : function(str){
		let originStr = str;
		let maskingStr;
		let strLength;
		
		if(this.checkNull(originStr) == true){
			return originStr;
		}
		
		strLength = originStr.length;
		
		if(strLength < 3){
			maskingStr = originStr.replace(/(?<=.{1})./gi, "*");
		}else {
			maskingStr = originStr.replace(/(?<=.{2})./gi, "*");
		}
		
		return maskingStr;
	}
}

◎ 사용 예시

아이디 마스킹 기준 - aidi maseuking gijun

ex)

maskingFunc.email(""); // "ab**********@nav******"
maskingFunc.phone("0111234567"); // "011***4567"
maskingFunc.phone("011-123-4567"); // "011-***-4567"
maskingFunc.phone("01012345678"); // "010****5678"
maskingFunc.phone("010-1234-5678"); // "010-****-5678"
maskingFunc.rrn("9901011234567"); // "9901011******"
maskingFunc.rrn("990101-1234567"); // "990101-1******"
maskingFunc.name("갓댐"); // "갓*"
maskingFunc.name("갓댐희"); // "갓댐*"
maskingFunc.name("하늘에수"); // "하늘**"