Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

한글 난독화 기능 #26

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
7 changes: 7 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
<body>
<div class="container">
<h1>Hangul.js 예제</h1>
<hr>
<ul class="nav nav-pills">
<li role="presentation" class="active"><a href="#">자모음 분리</a></li>
<li role="presentation"><a href="stronger.html">된소리</a></li>
<li role="presentation"><a href="obfuscation.html">난독화</a></li>
</ul>
<br>
<p>이 예제는 입력으로 주어진 문장을 자음 및 모음으로 분리하거나 자음 및 모음을 완성된 문장으로 바꿉니다.</p>
<section>
<form>
Expand Down
106 changes: 106 additions & 0 deletions examples/obfuscation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<!doctype html>
<html>
<head>
<title>Hangul.js 난독화 예제</title>
<script src="../hangul.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<meta charset="utf-8">
</head>
<body>
<div class="container">
<h1>Hangul.js 난독화 예제</h1>
<hr>
<ul class="nav nav-pills">
<li role="presentation"><a href="index.html">자모음 분리</a></li>
<li role="presentation"><a href="stronger.html">된소리</a></li>
<li role="presentation" class="active"><a href="#">난독화</a></li>
</ul>
<br>
<p>이 예제는 입력으로 주어진 문장에 홑받침 중 ㄲ, ㅆ 또는 겹받침을 활용하여, 원문을 훼손하지 않는 상태에서 읽기 힘들도록 만든 문장을 보여줍니다.</p>
<p>받침을 추가할 수 없는 문자는 그대로 유지됩니다.</p>
<table class="table table-stripped table-bordered">
<tr>
<th>입력</th>
<th>출력 예시</th>
</tr>
<tr><td>가</td><td>갔, 갏, 갉 ...</td></tr>
<tr><td>간</td><td>갅, 갆 중 하나</td></tr>
<tr><td>갇</td><td>갇</td></tr>
<tr><td>갔</td><td>갔</td></tr>
<tr><td>갈</td><td>갉, 갊, 갋, 갍, 갎, 갏 중 하나</td></tr>
<tr><td>갑</td><td>값</td></tr>
</table>

<p>난독화에 사용되는 잉여 자음들은 무작위로 만들어지므로, 결과는 매번 다를 수 있습니다.</p>
<ul>
<li>아버지가 방에 들어가신다 &#8594; 앒벏짋갔 방엜 듥얿갂싢닦</li>
<li>여기 호텔 절대 오지 마세요 &#8594; 엹긲 혽텕 젎댃 옧짅 맜셇욣</li>
</ul>

<form>
<div class="form-group">
<label for="input">입력 문장</label>
<textarea class="form-control" id="input" placeholder="아버지가 방에 들어가신다"></textarea>
</div>
<div class="form-group">
<label for="output">출력 문장 #1 (기본값; 모두 적용)</label>
<div class="form-control" id="output"></div>
</div>
<div class="form-group">
<label for="output-2">출력 문장 #2 (자음(종성)만 적용)</label>
<div class="form-control" id="output-2"></div>
</div>
<div class="form-group">
<label for="output-3">출력 문장 #3 (모음(중성)만 적용)</label>
<div class="form-control" id="output-3"></div>
</div>
<div class="form-group">
<label for="output-4">출력 문장 #4 (랜덤하게 50%의 문자만 적용)</label>
<div class="form-control" id="output-4"></div>
</div>
<div class="form-group">
<label for="output-5">출력 문장 #5 (랜덤하게 25%의 문자만 적용)</label>
<div class="form-control" id="output-5"></div>
</div>
</form>
</div>

<script>
function ready(fn) {
if (document.readyState != 'loading'){
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}

function obfuscateCustom(str, percentage) {
var result = '';
for (var i = 0; i < str.length; i++) {
var ch = str[i];
if (Math.random() < percentage) {
ch = Hangul.assemble(Hangul.obfuscate(str[i]));
}
result += ch;
}
return result;
}

var $ = document.querySelector.bind(document);

ready(function(){
$('#input').addEventListener('keyup', function(){
var input = this.value;
$('#output').innerHTML = Hangul.obfuscateAll(input);
$('#output-2').innerHTML = Hangul.obfuscateAll(input, 1); // 자음만
$('#output-3').innerHTML = Hangul.obfuscateAll(input, 2); // 모음만
for (var i = 4; i <= 5; ++i) {
var percentage = i == 4 ? 0.5 : 0.25;
$('#output-' + i).innerHTML = obfuscateCustom(input, percentage);
}
});
});
</script>

</body>
</html>
7 changes: 7 additions & 0 deletions examples/stronger.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
<body>
<div class="container">
<h1>Hangul.js 된소리 예제</h1>
<hr>
<ul class="nav nav-pills">
<li role="presentation"><a href="index.html">자모음 분리</a></li>
<li role="presentation" class="active"><a href="#">된소리</a></li>
<li role="presentation"><a href="obfuscation.html">난독화</a></li>
</ul>
<br>
<p>이 예제는 입력으로 주어진 문장에 있는 예사소리와, 거센소리를 모두 된소리로 바꾼 문장을 보여줍니다.</p>
<table class="table table-stripped table-bordered">
<tr>
Expand Down
128 changes: 127 additions & 1 deletion hangul.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ',
'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
],
/* Assembled 종성 (복잡한 자음) */
COMPLETE_COMPLEX_JONG = [
'ㄲ', 'ㄳ', 'ㄵ', 'ㄶ', 'ㄺ', 'ㄻ', 'ㄼ',
'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅄ', 'ㅆ'
],
/* 복잡한 자음: [ 자음1, 자음2, 자음1+자음2 ] */
COMPLEX_CONSONANTS = [
['ㄱ', 'ㅅ', 'ㄳ'],
Expand Down Expand Up @@ -85,7 +90,9 @@
JUNG_HASH,
JONG_HASH,
COMPLEX_CONSONANTS_HASH,
COMPLEX_VOWELS_HASH
COMPLEX_VOWELS_HASH,
COMPLEXABLE_CONSONANTS_HASH,
COMPLEXABLE_VOWELS_HASH
;

function _makeHash(array) {
Expand Down Expand Up @@ -121,8 +128,34 @@
return hash;
}

var _makeComplexableHash = function (array) {
var length = array.length,
hash = {},
code1,
code2,
value
;
for(var i = 0; i < length; ++i){
code1 = array[i][0].charCodeAt(0);
code2 = array[i][1].charCodeAt(0);
value = array[i][2].charCodeAt(0);
if(typeof hash[code1] === 'undefined') {
hash[code1] = [];
}
if(typeof hash[code2] === 'undefined') {
hash[code2] = [];
}
hash[code1].push(value);
hash[code2].push(value);
}
return hash;
};

COMPLEX_CONSONANTS_HASH = _makeComplexHash(COMPLEX_CONSONANTS);
COMPLEX_VOWELS_HASH = _makeComplexHash(COMPLEX_VOWELS);
COMPLEXABLE_CONSONANTS_HASH = _makeComplexableHash(COMPLEX_CONSONANTS);
COMPLEXABLE_VOWELS_HASH = _makeComplexableHash(COMPLEX_VOWELS);


/* c 가 CONSONANTS의 멤버일 경우 true 반환 (c가 자음일 경우 true 반환) */
function _isConsonant(c) {
Expand Down Expand Up @@ -420,6 +453,97 @@
return result.join('');
};

function _randomElement(array) {
if (typeof array === 'undefined') {
return undefined;
}
var length = array.length;
return array[Math.floor(Math.random() * length)];
}

/* 가능한 복잡한 자음 또는 모음을 hash를 참고하여 반환한다. (ㄴ -> ㄵ, ㅗ -> ㅘ 등) */
var _toComplex = function (hash, code) {
var complexed = hash[code];
if (typeof complexed === 'undefined') {
// 불가능한 경우에는 그대로 유지한다. (ㅇ, ㅎ 등)
return String.fromCharCode(code);
} else {
return String.fromCharCode(_randomElement(complexed));
}
};

/* 완성형 한글 하나를 난독화한다. */
/* option => 0: 적용 안 함, 1: 자음(종성)만, 2: 모음(중성)만, 3: 둘 다 적용 (기본값) */
var obfuscate = function (arr, option) {
if (typeof arr === 'string') {
return obfuscateToString(arr[0], option);
}
if (typeof option === 'undefined') {
option = 3;
}
// 자음 적용
if (option & 1) {
var length = arr.length;
var lastCode = arr[arr.length - 1].charCodeAt(0); // 마지막 음의 코드
if (length == 2) { // ㄱㅏ 인 경우, 복잡한 받침을 추가한다.
arr.push(_randomElement(COMPLETE_COMPLEX_JONG));
} else if (length == 3) { // ㄱㅏㅇ 또는 ㄱㅏㅆ 또는 ㄱㅗㅏ
if (_isJung(lastCode)) { // ㄱㅗㅏ
arr.push(_randomElement(COMPLETE_COMPLEX_JONG));
} else { // ㄱㅏㅇ 또는 ㄱㅏㅆ
// 마지막 자리를 복잡하게 바꾼다.
arr[arr.length - 1] = _toComplex(COMPLEXABLE_CONSONANTS_HASH, lastCode);
}
} else if (length == 4) { // ㄱㅏㄹㅁ 또는 ㅇㅗㅏㅇ
// ㄱㅏㄹㅁ은 받침이 더 이상 들어갈 자리가 없다.
if (_isJung(arr[2])) { // ㅇㅗㅏㅇ은 마지막 자음만 변환하면 된다. (괄->괅)
arr[arr.length - 1] = _toComplex(COMPLEXABLE_CONSONANTS_HASH, lastCode);
}
}
}
// 모음 적용
if (option & 2) {
// 이중모음이 아닌 경우에만 변형한다. (ㅇㅜㅓㅇ -> 그대로)
if (_isJung(arr[1].charCodeAt(0)) && !_isJung((arr[2] || '').charCodeAt(0))) {
arr[1] = _toComplex(COMPLEXABLE_VOWELS_HASH, arr[1].charCodeAt(0));
}
}
return arr;
};

var obfuscateToString = function (char, option) {
if (!_isHangul(char.charCodeAt(0))) {
return char;
} else {
var result = obfuscate(disassemble(char, true)[0], option);
return assemble(result);
}
};

/* 문장을 훼손하지 않고, 종성에 자음을 최대한 추가하여 난독화한다. */
/* option => 0: 적용 안 함, 1: 자음(종성)만, 2: 모음(중성)만, 3: 둘 다 적용 (기본값) */
var obfuscateAll = function (str, option) {
// 문자열이 아닌 경우에는 빈 문자열을 반환
if (typeof str !== 'string') {
return '';
}
var array = disassemble(str, true); // 종성 변형을 위해 초성, 중성, 종성을 분리하여 저장한다.
var result = [],
length = str.length
;
for (var i = 0; i < length; i++) {
if (_isHangul(str.charCodeAt(i))) { // 완성형 한글만 변형한다.
var char = disassemble(array[i]); // 자음 모음으로 분리한다.
char = obfuscate(char, option);
result.push(assemble(char)); // 다시 완성형 한글로 합친다.
} else {
// 아닌 경우는 그대로 유지한다.
result.push(str[i]);
}
}
return result.join('');
};

var search = function (a, b) {
/* a 와 b 를 disassemble한 후 문자열로 반환해 ad, bd에 각각 저장 */
var ad = disassemble(a).join(''),
Expand Down Expand Up @@ -508,6 +632,8 @@
Searcher: Searcher,
endsWithConsonant: endsWithConsonant,
endsWith: endsWith,
obfuscate: obfuscate,
obfuscateAll: obfuscateAll,
isHangul: function (c) {
if (typeof c === 'string')
c = c.charCodeAt(0);
Expand Down
Loading