퓨니코드
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
퓨니코드는 ASCII 문자 집합에 포함되지 않은 문자를 ASCII 문자로 인코딩하는 방식이다. 이는 일반화된 가변 길이 정수를 사용하며, 특히 국제화 도메인 이름(IDN)에서 사용되어, 유니코드 문자를 포함하는 도메인 이름을 ASCII 호환 형식으로 변환한다. 퓨니코드는 델타 인코딩과 가변 길이 정수를 활용하여 문자열을 압축하며, 인코딩 과정은 ASCII 문자 분리, 비ASCII 문자 인코딩, 가변 길이 숫자 인코딩, ACE 접두어 추가의 단계를 거친다. 퓨니코드는 피싱 공격에 악용될 수 있으며, 웹 브라우저는 이를 방지하기 위해 퓨니코드 도메인 표시를 제한하는 등의 대응책을 사용한다.
더 읽어볼만한 페이지
- 유니코드 변환 형식 - UTF-8
UTF-8은 유니코드 문자를 표현하는 가변 길이 문자 인코딩 방식으로, ASCII 코드와 호환성을 유지하며 다양한 언어의 문자를 표현할 수 있도록 설계되었지만, 보안 문제점과 공간 효율성 측면에서 단점을 가진다. - 유니코드 변환 형식 - UTF-1
UTF-1은 유니코드 초기 버전을 인코딩하기 위해 1992년에 설계된 가변 길이 문자 인코딩 방식으로, ASCII 호환성을 유지하고 ISO 2022 및 MIME과의 호환성을 고려했지만, "모듈로 190" 산술을 사용하는 특징과 현대 유니코드 표준과의 차이점을 가진다. - 유니코드에 관한 - UTF-8
UTF-8은 유니코드 문자를 표현하는 가변 길이 문자 인코딩 방식으로, ASCII 코드와 호환성을 유지하며 다양한 언어의 문자를 표현할 수 있도록 설계되었지만, 보안 문제점과 공간 효율성 측면에서 단점을 가진다. - 유니코드에 관한 - UTF-1
UTF-1은 유니코드 초기 버전을 인코딩하기 위해 1992년에 설계된 가변 길이 문자 인코딩 방식으로, ASCII 호환성을 유지하고 ISO 2022 및 MIME과의 호환성을 고려했지만, "모듈로 190" 산술을 사용하는 특징과 현대 유니코드 표준과의 차이점을 가진다. - 컴퓨터에 관한 - 고속 패킷 접속
고속 패킷 접속(HSPA)은 3세대 이동통신(3G)의 데이터 전송 속도를 높이는 기술 집합체로, 고속 하향/상향 패킷 접속(HSDPA/HSUPA)을 통해 속도를 개선하고 다중 안테나, 고차 변조, 다중 주파수 대역 활용 등의 기술로 진화했으나, LTE 및 5G 기술 발전으로 현재는 상용 서비스가 중단되었다. - 컴퓨터에 관한 - 데이터베이스
데이터베이스는 여러 사용자가 공유하고 사용하는 정보의 집합으로, 데이터베이스 관리 시스템을 통해 접근하며, 검색 및 갱신 효율을 높이기 위해 고도로 구조화되어 있고, 관계형, NoSQL, NewSQL 등 다양한 모델로 발전해왔다.
퓨니코드 | |
---|---|
설명 | |
유형 | 문자 인코딩 |
설계자 | 마크 데이비스 |
출판 | 2001년 3월 5일 |
상세 정보 | |
IETF | RFC 3492 |
등록 기관 | 유니코드 컨소시엄 |
인코딩 범위 | 유니코드 |
사용 | |
사용처 | 국제화 도메인 이름 (IDNA) |
2. 구조
퓨니코드는 문자열에서 ASCII 문자만 남기고, ASCII가 아닌 문자들이 원래 문자열 어디에 삽입되어야 하는지를 일반화된 가변 길이 기수법을 사용하여 부호화한다. 이 부호화 과정에서는 코드 포인트가 델타 인코딩으로 저장되기 때문에, 삽입될 문자들이 비슷한 코드 포인트를 사용하면 짧은 길이로 부호화될 수 있다.
RFC 3492에 따르면, "퓨니코드는 더 일반적인 알고리즘인 ''부트스트링''의 한 예시이며, 이는 작은 '기본' 코드 포인트 집합으로 구성된 문자열이 더 큰 집합에서 추출된 모든 코드 포인트 문자열을 고유하게 나타낼 수 있도록 한다." 퓨니코드는 일반적인 부트스트링 알고리즘의 매개변수를 정의하여 유니코드 텍스트의 특성과 일치시킨다. 예를 들어 독일어 문자열 "bücher" (영어: ''books'')는 "bcher-kva"라는 레이블로 변환된다.
인코딩 및 디코딩 알고리즘을 간단하게 만들기 위해, 일부 인코딩된 값이 허용되지 않는 유니코드 값을 인코딩하는 것을 방지하려는 시도는 없었다. 그러나 이러한 값은 디코딩 중에 확인하고 감지해야 한다.
퓨니코드는 모든 스크립트에서 작동하도록 설계되었으며, 문자열 내의 문자 집합 범위에 적응하여 자체 최적화된다. 문자열이 0개 이상의 ASCII 문자와 다른 하나의 스크립트 시스템의 문자로 구성된 경우에 최적화되지만, 임의의 유니코드 문자열도 처리할 수 있다. DNS 사용의 경우, 도메인 이름 문자열은 퓨니코드화되기 전에 nameprep을 사용하여 정규화되고 (최상위 도메인의 경우) 공식적으로 등록된 언어 테이블에 대해 필터링된 것으로 간주되며, DNS 프로토콜은 출력 퓨니코드 문자열의 허용 가능한 길이에 제한을 설정한다.
2. 1. 델타 인코딩
코드 포인트는 델타 인코딩으로 저장되어, 비슷한 코드 포인트를 사용하는 문자들을 짧은 길이로 부호화할 수 있다.2. 2. 가변 길이 정수
퓨니코드는 값을 표현하기 위해 일반화된 가변 길이 정수를 사용한다. 일반화 가변 길이 정수에서는 각 자리에 다른 임계값을 설정하고, 이보다 작은 숫자가 나타나는 자리를 최대 자리로 하여 숫자열의 구분을 결정한다. 퓨니코드에서 사용되는 리틀 엔디안의 경우, 작은 자리부터 표기되므로 선행 계산 없이 임의의 자리수의 숫자를 표기할 수 있다.퓨니코드에서는 각 자리에 사용할 수 있는 숫자로서 36종류의 문자를 사용한다. 알파벳(대소문자를 구별하지 않음)의 '`a`'부터 '`z`'가 0부터 25를 나타내고, 숫자의 '`0`'부터 '`9`'가 26부터 35를 나타낸다.
10진수 | 0 | 1 | 2 | 3 | … | 24 | 25 | 26 | … | 34 | 35 |
---|---|---|---|---|---|---|---|---|---|---|---|
일반화 가변 길이 정수 | a | b | c | d | … | y | z | 0 | … | 8 | 9 |
RFC 3492에 명시된 퓨니코드 인코딩 절차는 다음과 같다. 퓨니코드는 ASCII 문자 집합에 포함되는 문자만 문자열에 남긴 후, 일반화된 가변 길이 기수법을 사용하여 ASCII에 포함되지 않는 문자들이 원래 문자열에 어떻게 삽입될지를 부호화한다. 예를 들어 독일어 문자열 "bücher" (영어: ''books'')는 "bcher-kva"라는 레이블로 변환된다.
퓨니코드를 사용하면 도메인 이름에 모든 유니코드 문자를 쓸 수 있기 때문에, 국제화 도메인 이름(IDNA)를 사용하여 피싱 공격을 할 수 있다. 예를 들어 "wikipedia.org"라는 도메인을 스푸핑하기 위해 "wikip'''е'''di'''а'''.org" (IDNA에서
[1]
간행물
Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDN)
https://datatracker.[...]
The Internet Society
2003-03
예를 들어 "kva"는 십진수 문자열 "10 21 0"에 해당한다. 여기서 임계값은 (1, 1, 26)이다.[2] 첫 번째 자리 ('k' 즉 10)의 가중치는 1이다. 두 번째 자리 ('v' 즉 21)의 가중치는 첫 번째 임계값에 따라 달라지는데, 일반적으로 (n+1)번째 숫자의 가중치는 w × (36 - t)이며, 여기서 w는 이전 가중치이고 t는 n번째 숫자의 임계값이다. 따라서 두 번째 기호는 이전 임계값 1을 뺀 36의 자리값을 가지며, 이는 35와 같다. 그러므로 처음 두 기호 'k' (=10)와 'v' (=21)의 합은 10 × 1 + 21 × 35이다. 세 번째 자리 ('a' 즉 0)의 가중치는 352 = 1225이다. 또한, 3자리의 값 0은 3자리의 임계값 26보다 작으므로, 여기서 첫 번째 숫자열이 종료되었음을 알 수 있다. 따라서 "kva"는 10 × 1 + 21 × 35 + 0 × 1225 = 745를 나타낸다.
각 자리의 가중치 ''w''(''j'') 및 임계값 ''t''(''j'')의 값은 다음 식으로 계산된다[8]:
:
:
:
:: (단, ''t''(''j'')는 상기 식을 ''tmin'' 이하인 경우 ''tmin'', ''tmax'' 이상인 경우 ''tmax''로 클램프한 것이다. ''bias''는 상태 변수이다.)
: ''base'' = 36, ''tmin'' = 1, ''tmax'' = 26
3. 인코딩 절차
인코딩 절차는 크게 네 단계로 나뉜다.
1. ASCII 문자 분리: 문자열에서 모든 ASCII 문자를 순서대로 출력에 복사하고, ASCII가 아닌 문자는 건너뛴다. ASCII 문자가 하나라도 복사되었다면, 출력에 ASCII 하이픈('-')을 추가한다. 입력 문자열에 ASCII 문자가 아닌 문자가 있는 경우, 마지막에 하이픈을 추가하여 ASCII 문자와 비ASCII 문자의 영역을 구분한다.
2. 비ASCII 문자 인코딩: 유니코드 값에 따라 오름차순으로 정렬된 비ASCII 문자는 각각 삽입 위치와 삽입할 문자를 정의하는 숫자로 인코딩된다. 이 숫자는 가변 길이 정수로 표현된다.
3. 가변 길이 숫자 인코딩: 숫자는 36진법(a-z는 0-25, 0-9는 26-35)을 사용하여 표현되며, 리틀 엔디안 숫자 시스템을 사용하여 가변 길이 코드를 허용한다.
4. ACE 접두어: 퓨니코드 시퀀스 앞에는 `xn--`라는 ACE(ASCII Compatible Encoding) 접두어가 붙는다.[5] 예를 들어, "bücher.tld"는 "xn--bcher-kva.tld"로 표시된다.
퓨니코드는 모든 스크립트에서 작동하도록 설계되었으며, 문자열 내의 문자 집합 범위에 적응하여 자체 최적화된다.
3. 1. ASCII 문자 분리
먼저, 문자열의 모든 아스키 문자는 다른 문자를 건너뛰고 입력에서 출력으로 복사된다. 예를 들어, "bücher"는 "bcher"로 복사된다. 만약 어떤 문자가 복사되었다면, 즉 입력에 적어도 하나의 아스키 문자가 있었다면, 출력에 아스키 하이픈이 추가된다(예: "bücher" → "bcher-", 그러나 "ü" → "").
하이픈 자체도 아스키 문자이므로 입력에 존재할 수 있으며, 그렇다면 출력으로 복사된다. 이는 모호성을 야기하지 않는다. 출력이 하이픈을 포함하는 경우, 추가된 하이픈은 항상 마지막 하이픈이며, 이는 아스키 문자의 끝을 나타낸다.
입력 문자열에 있는 모든 ASCII 문자를 남기고, ASCII 문자가 아닌 문자를 제거한다. 또한, ASCII 문자가 아닌 문자가 있는 경우에는 마지막에 구분 문자(하이픈, -
)를 추가한다.입력 문자열 처리 후 bücher
bcher-
日本Japan
Japan-
MajiでKoiする5秒前
MajiKoi5-
3. 2. 비ASCII 문자 인코딩
비ASCII 문자는 유니코드 값에 따라 오름차순으로 정렬되며(문자가 여러 번 나타나는 경우 위치별로 정렬), 각 문자는 단일 숫자로 인코딩된다. 이 숫자는 문자를 삽입할 위치와 삽입할 문자를 모두 정의한다.
인코딩된 숫자는 이다. 으로 나누고 나머지를 구하면 디코더는 와 를 결정할 수 있다.
예를 들어 "bcher" 문자열에는 문자를 삽입할 수 있는 6개의 위치가 있다(첫 번째 문자 앞과 마지막 문자 뒤 포함). 마지막 ASCII 코드 포인트(127 = , ASCII의 끝)와 (코드 포인트 252 = , 라틴-1 보충 참조) 사이에는 124개의 코드 포인트가 있다. 는 다음에 위치 1에 삽입되므로, 인코더는 숫자 를 더하고, 디코더는 및 을 통해 이를 검색할 수 있다.
이러한 숫자는 엄격하게 증가한다. 두 번째 및 그 이후에 삽입된 문자의 경우, 숫자와 이전 숫자 간의 차이가 기록된다.
이 숫자는 부터 까지의 문자와 부터 까지의 숫자를 사용하여 인코딩된다.
디코더는 두 개의 상태 변수 ''i'' 와 ''n'' 을 갖는 오토마톤이다. ''i''는 분리된 후의 ASCII 문자열에 대한 삽입 위치를 나타내며, 그 범위는 0 (문자열의 맨 앞에 삽입을 나타냄)부터 ASCII 문자열의 길이 (문자열의 맨 뒤에 삽입을 나타냄)이다. ''n''은 삽입할 문자의 코드 포인트이다.분리 후 문자열 b c h e r 삽입 위치 i 0 1 2 3 4 5
''i''는 0부터 시작하고, ''n''은 128 (비ASCII 문자의 첫 번째 코드 포인트)부터 시작한다. 상태 전이는 단조이며, 전이하면 ''i''가 1만큼 증가한다. 그러나 ''i''가 이미 최대값인 경우에는 ''n''이 1 증가하고, ''i''는 0으로 돌아간다. 즉, 삽입할 위치가 없어지면, 삽입할 문자가 하나 뒤의 것이 된다. 각 상태 전이 시, ''n''으로 표시되는 코드 포인트를 문자열에 삽입할지, 삽입을 건너뛸지가 결정된다.
코드 번호는 인코더에 의해 생성되는 수치이며, 디코더가 문자를 삽입하기 전에 건너뛰어야 할 삽입 가능 위치가 몇 개인지 수치화한 것이다. "ü"의 유니코드 코드 포인트는 U+00FC, 10진수로 나타내면 252이다. 따라서, ü 글자를 문자열의 첫 번째 문자 뒤에 삽입하려면, ü보다 앞에 있는 124 (251 - 127 = 124) 종류의 비ASCII 문자가, "bcher" 안의 6곳의 삽입 지점에 삽입되는 것을 건너뛰고, 0번째 문자 (즉 문자열의 맨 앞)에 ü가 삽입되는 것을 건너뛸 필요가 있다. 따라서, 디코더에는 필요한 1개의 문자를 삽입하기 위해, (124 × 6) + 1 = 745번의 비ASCII 문자 삽입을 건너뛰도록 전달해야 한다.
3. 3. 가변 길이 숫자 인코딩
퓨니코드는 숫자를 일반화된 가변 길이 정수를 사용하여 표현한다.[2] 예를 들어 "kva"가 코드 번호 745를 나타내는 방식은 다음과 같다.
리틀 엔디안 숫자 시스템이 사용되어 별도의 구분자 없이 가변 길이 코드를 허용한다. 임계값보다 낮은 숫자는 그것이 가장 중요한 숫자, 즉 숫자의 끝임을 나타낸다. 임계값은 숫자 내 위치와 이전 삽입에 따라 달라지며, 효율성을 높이기 위해 사용된다. 이에 따라 숫자의 가중치도 달라진다.
36개의 기호가 있는 숫자 시스템이 사용되며, 대소문자를 구분하지 않는 'a'부터 'z'까지는 십진수 0부터 25에 해당하고, '0'부터 '9'까지는 십진수 26부터 35에 해당한다. 따라서 "kva"는 십진수 문자열 "10 21 0"에 해당한다.
이 기호 문자열을 디코딩하려면 일련의 임계값 (1, 1, 26, 26, ...)이 필요하다.[2] 가장 낮은 자리의 가중치 (또는 자리값)는 항상 1이다. 가중치가 1인 'k' (=10)는 10과 같다. 그 다음, 다음 숫자의 가중치는 첫 번째 임계값에 따라 달라진다. 일반적으로, 모든 ''n''에 대해, (''n''+1)번째 숫자의 가중치는 ''w'' × (36 − ''t'')이며, 여기서 ''w''는 이전 가중치이고 ''t''는 ''n''번째 숫자의 임계값이다. 따라서 이 경우, 두 번째 기호는 이전 임계값 1을 뺀 36의 자리값을 가지며, 이는 35와 같다. 그러므로, 처음 두 기호 'k' (=10)와 'v' (=21)의 합은 10 × 1 + 21 × 35이다. 두 번째 기호가 해당 임계값 1보다 크지 않으므로, 더 계산할 것이 있다. 그러나 이 예제의 세 번째 기호가 'a' (=0)이므로, 가중치 계산을 무시할 수 있다. 그러므로 "kva"는 십진수 (10 × 1) + (21 × 35) = 745를 나타낸다.
숫자 745는 10 + 21 × 35 + 0 (두 번째 숫자에 사용되는 기수 35, 종료 기호로 필요한 가장 중요한 숫자 0)으로 인코딩되며, 10 → 'k', 21 → 'v', 0 → 'a'이므로 "bücher" → "bcher-kva"가 된다.
각 자리의 가중치 ''w''(''j'') 및 임계값 ''t''(''j'')의 값은 다음 식으로 계산된다[8]:
:
:
:
::(단, ''t''(''j'')는 상기 식을 ''tmin'' 이하인 경우 ''tmin'', ''tmax'' 이상인 경우 ''tmax''로 클램프한 것이다. ''bias''는 상태 변수이다.)
:''base'' = 36, ''tmin'' = 1, ''tmax'' = 26
3. 4. ACE 접두어
국제화 도메인 이름에서 퓨니코드 시퀀스 앞에 `xn--` 문자열이 추가된다. 이것을 ACE(ASCII 호환 인코딩)라고 한다.[5]
따라서 도메인 이름 "bücher.tld"는 URL에서 "xn--bcher-kva.tld"로 표시된다. 도메인 이름으로 Punycode영어를 사용할 때는 마침표(`.`)로 구분된 도메인 이름의 각 계층마다 접두사로 "`xn--`"를 사용하고, 인코딩된 문자열을 덧붙인다. 대소문자는 구별하지 않는다.읽을 수 있는 도메인 이름 Punycode영어로 된 도메인 이름 도메인명예.jp xn--eckwd4c7cu47r2wf.jp 위키백과.도메인명예.jp xn--cckbak0byl6e.xn--eckwd4c7cu47r2wf.jp 귀엽네.그렇지도않아 xn--n8j5d625jn9k.xn--n8jd2ewbp7lub
4. 퓨니코드를 사용한 피싱
xn--wikipdi-8fg6b.org
) 도메인을 사용할 수 있다. 굵게 표시한 키릴 문자는 보통 로마자와 비슷하거나 같게 보이기 때문에 사용자가 같은 도메인으로 착각할 가능성이 높아진다. 이러한 공격을 동형이의어 공격이라고 부른다.
4. 1. 웹 브라우저의 대응
사파리, 파이어폭스, 오페라 웹 브라우저는 국제화된 웹사이트에 접속하는 것을 제한하는 대신, 신뢰할 수 있는 도메인만 원래 의도된 유니코드 이름으로 보여 주고 그렇지 않은 도메인은 "xn--"으로 시작하는 퓨니코드 이름으로 보여 주는 방법으로 피싱 공격 문제를 해결한다. 단, ISO 8859-1에 있는 문자들은 섞여 쓰여도 이 취약점을 쓸 수 있는 가능성이 적기 때문에 명시적으로 허용하지 않아도 유니코드 이름으로 표시된다. 사파리도 보안 업데이트 2005-003 이후로 특히 피싱에 잘 사용되는 그리스 문자, 키릴 문자, 체로키어가 들어 있는 도메인을 이와 비슷한 방법으로 표시하는 방법을 사용하고 있다.
4. 2. 대한민국의 대응 현황
대한민국은 .kr 도메인 외에도 .한국 도메인을 운영하며, 한글 도메인 사용이 늘어나면서 퓨니코드 관련 보안 위협에 노출될 가능성이 높아지고 있다. 한국인터넷진흥원(KISA)에서는 IDN 관련 보안 취약점 분석 및 대응 방안 연구를 진행하고 있다.
5. 예시
입력 퓨니코드 설명 빈 문자열. a a- ASCII 문자만, 하나, 소문자. A A- ASCII 문자만, 하나, 대문자. 3 3- ASCII 문자만, 하나, 숫자. - -- ASCII 문자만, 하나, 하이픈. -- --- ASCII 문자만, 두 개의 하이픈. London London- ASCII 문자만, 하나 이상, 하이픈 없음. Lloyd-Atkinson Lloyd-Atkinson- ASCII 문자만, 하이픈 하나. This has spaces This has spaces- ASCII 문자만, 공백 포함. -> $1.00 <- -> $1.00 <-- ASCII 문자만, 혼합된 기호. Б d0a ASCII 문자 없음, 키릴 문자 하나. ü tda ASCII 문자 없음, Latin-1 Supplement 문자 하나. α mxa ASCII 문자 없음, 그리스 문자 하나. 例 fsq ASCII 문자 없음, CJK 문자 하나. 😉 n28h ASCII 문자 없음, 이모지 문자 하나. αβγ mxacd ASCII 문자 없음, 문자 여러 개. München Mnchen-3ya 혼합된 문자열, ASCII 문자가 아닌 문자 하나. Mnchen-3ya Mnchen-3ya- "München"의 이중 인코딩된 퓨니코드. München-Ost Mnchen-Ost-9db 혼합된 문자열, ASCII 문자가 아닌 문자 하나, 하이픈. Bahnhof München-Ost Bahnhof Mnchen-Ost-u6b 혼합된 문자열, 공백 하나, 하이픈 하나, ASCII 문자가 아닌 문자 하나. abæcdöef abcdef-qua4k 혼합된 문자열, ASCII 문자가 아닌 문자 두 개. правда 80aafi6cg 러시아어, ASCII 문자 없음. ยจฆฟคฏข 22cdfh1b8fsa 태국어, ASCII 문자 없음. 도메인 hq1bm8jm9l 한국어, ASCII 문자 없음. ドメイン名例 eckwd4c7cu47r2wf 일본어, ASCII 문자 없음. MajiでKoiする5秒前 MajiKoi5-783gue6qz075azm5e ASCII 문자가 포함된 일본어. 「bücher」 bcher-kva8445foa 혼합된 ASCII가 아닌 스크립트 (Latin-1 Supplement 및 CJK). 6. 외부 사이트
참조
[2]
간행물
RFC 3492, Sec. 6
[3]
간행물
RFC 3492, Secs. 3.4, 5
[4]
간행물
RFC 3492, App. A
[5]
웹사이트
Completion of IANA Selection of IDNA Prefix
http://www.atm.tut.f[...]
2003-02-14
[6]
문서
The Punycode in this table was created using the builtin codec "punycode" of the [[Python (programming language)|Python programming language]] version 3.8 (s.encode("punycode")
). See [[Talk:Punycode#More examples are needed, especially pure ASCII examples and corner cases|talk page]]
[7]
문서
[[ドイツ語]]で「書籍」 (複数形) を意味する
[8]
간행물
IDNA Punycode
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com