텍스트안에 비밀 메세지 숨기기 - 스테가노그래피 StegCloak

텍스트 파일 속 비밀스러운 메시지를 숨기는 방법

Stegcloak는 웹페이지 상에서 텍스트 안에 데이터를 숨기고 추출하기 위한 JavaScript 도구입니다. 이 도구를 사용하여 데이터를 숨기는 것을 스테가노그래피(Steganography)라고 합니다. 
 
스테가노그래피는 암호화와는 달리 데이터를 감추는 것입니다. 일반적으로 많이 알고 있는 게 사진에 데이터를 숨기는 방법인데, 이러한 기술을 사용하여 데이터를 안전하게 전송하고 저장할 수 있습니다. 스테가노그래피를 사용하면 일반적으로 파일을 직접 확인해보지 않으면 암호화를 하여 파일이 숨겨진 건지 확인하기 어렵습니다. base64등 암호화로 이루어진 텍스트의 경우에는 일반적인 문자열과 생김새부터 많이 다르기 때문에 암호문으로 인식하고 복호화를 시도할 수 있지만 스테가노그래피를 사용하여 텍스트를 숨길경우 원본 텍스트만 봤을 때 암호문으로 생각하기 어렵습니다.
 
이번에는 Stegcloak를 사용할건데 숨겨진 데이터는 일반적인 문자열처럼 보이며, 암호화 시 사용하였던 패스워드를 통해 복호화할 수 있습니다.  이를 통해, 웹 페이지에서 민감한 데이터를 안전하게 전송하고 저장할 수 있습니다. 
 
 
 

Stegcloak 문자를 숨기는 알고리즘에 대한 설명

Sujin Kingslen 미디엄 기사

전체적인 암호화 복호화과정을 표로 보면 이렇습니다. 아래에서 단계별로 자세히 설명해드리겠습니다.
 
 
 

유니코드를 통한 텍스트 숨기기

Stegcloak는 특별한 알고리즘을 사용하여 문자열을 수정하여 텍스트를 숨기는 방법입니다. 예를 들어, 스페이스, 탭, 개행 등의 특수 문자를 사용하여 텍스트를 수정할 수 있습니다. 이러한 문자들은 우리가 보기에는 불필요한 문자로 보이지만, 컴퓨터는 이러한 문자들을 구분할 수 있습니다.
 
 

Sujin Kingslen 미디엄 기사

더 구체적으로, 이 도구에서 사용된 방법은 문자열을 수정하여 숨기는 방법 중 하나입니다. 새로운 문자열은 원래 텍스트와 유사하지만, 특정 규칙에 따라 수정됩니다. 이러한 규칙은 문자열을 숨기고 추출할 때 사용됩니다. 이 방법은 텍스트에서 공백을 제거하고 이어진 문자열로 만든 뒤, 이를 반복하여 숨기는 방법입니다. 이때, 특별한 규칙을 사용하여 숨겨진 데이터를 추출할 수 있습니다. 이러한 방식은 간단하면서도 효과적인 숨기기 방법 중 하나입니다.
 
 

Sujin Kingslen 미디엄 기사

가장 많이 사용되는 보이지 않는 문자에 대한 유니코드들입니다.
Stegcloak에서 이들을 사용하려 했으나 Gmail이나 Twitter 등 SNS에서는 보이지 않는 불필요한 문자들을 첨부할수 없도록 막아놓은경우가 많았습니다. U+180e는 IOS기기에서 이상하게 렌더링이되어 제외하고 추가적으로 Unicode 테이블을 조사한 결과 총 6개의 보이지않는 문자에대한 유니코드들을 얻었습니다.
 
 

암호화 과정 1단계

StegCloak는 보이지않는 문자들을 사용해서 단순히 텍스트를 보이지 않도록 숨기는 것뿐만 아니라 암호문을 알고리즘을 통해서 암호화하여 보호합니다.
해당 암호화는 커크호프(Kerckhoff)의 원칙(키를 제외한 시스템의 다른 모든 내용이 알려지더라도 암호체계는 안전해야 한다는 것이다.)에 따라 작동하도록 설계되었습니다.
대칭암호화를 사용하여 암호문을 생성할 때, 공격자가 동일한 키로 생성된 여러 암호문들을 분석할 수 있습니다. 이를 방지하고자 키의 임의성이 필요합니다. 
 
CBC모드를 사용하면 암호화된 결과가 16바이트 블록단위로 생성되게 되는데 예를 들면 "Hello"라는 문자열을 CBC모드로 암호화하면 메시지가 16바이트 블록이 아닐 때 부족한 길이만큼 0으로 채워져야 합니다.(이것을 패딩(padding)이라고 함) 만약 같은 비밀키를 사용하여 동일한 "Hello"라는 문자열을 암호화하면, 항상 동일한 암호문 블록이 생성됩니다. 이러한 특성을 이용해서 암호문 블록의 패턴을 분석하고 암호문을 복호화할 수 있는 공격이 있습니다.
또한 0으로 패딩이 채워지게 되면 추가된 0들의 패턴을 알 수 있어서 보안에 취약합니다.
 

CBC모드 공격과정 자세히 보기

더보기
  1. 평문 "hello" 를 16바이트 블록으로 나눕니다. 여기서는 "hello" 라는 단어 하나만 있으므로, 이 단어를 16바이트 블록으로 변환합니다. 예를 들어, "hello00000000000" 과 같이 0으로 채워진 블록이 됩니다.
  2. 초기화 벡터(IV)를 선택합니다. 이는 랜덤하게 선택되어야 합니다.
  3. 첫 번째 블록은 초기화 벡터와 XOR 연산을 통해 암호화됩니다. 즉, IV XOR "hello00000000000" 이라는 계산을 수행합니다. 이 결과가 첫 번째 블록의 암호문이 됩니다.
  4. 두 번째 블록부터는 이전 블록의 암호문과 XOR 연산을 통해 암호화됩니다. 따라서 첫 번째 블록의 암호문과 XOR 연산을 수행한 후에 암호화를 진행합니다. 이 과정을 모든 블록에 대해 수행합니다.

만약, 공격자가 같은 비밀키를 사용하여 동일한 평문 "hello"를 암호화한 결과를 수집했다면, 이 암호문 블록의 패턴을 분석하여 평문을 추측할 수 있습니다. 이는 같은 평문 "hello"가 같은 패턴의 암호문 블록을 생성하기 때문입니다. 따라서, CBC 모드에서는 같은 평문을 암호화할 때마다 다른 초기화 벡터를 사용하여 암호화를 수행해야 합니다.

 

반면, CTR 모드에서는 스트림 암호화 방식을 사용하므로 같은 평문을 암호화해도 항상 다른 암호문이 생성됩니다. 이는 랜덤 한 nonce와 키를 결합하여 스트림을 생성하고 평문과 XOR 연산을 수행하기 때문입니다. 따라서, CTR 모드는 CBC 모드보다 같은 평문을 암호화할 때 더욱 안전한 방식입니다.

 
그래서 CBC대신에 CTR(Padding less cipher) 모드의 스트림 암호모드를 사용하여 암호문을 생성하도록 채택하였습니다. CTR모드는 패딩이 필요하지 않으며 블록단위 암호화 대신, 스트림 암호화 방식을 사용합니다.
키와 nonce(랜덤 한 숫자)를 결합하여 스트림을 생성하고 이 스트림을 평문과 XOR연산하여 암호화를 수행합니다. 이러한 방식을 사용하여 암호화하면 메시지의 길이가 16의 배수가 아니더라도 패딩이 필요하지 않으므로 보안에 더욱 강력합니다.
또한 같은 비밀키를 사용하여 동일한 문자열을 암호화하더라도 항상 다른 암호문 블록이 생성됩니다.
 
 
 

Sujin Kingslen 미디엄 기사

이후에 LZ와 Lempel-Ziv 데이터 압축알고리즘을 사용하여 평문을 2진수 형태로 변환합니다.
 
 

암호화 과정 2단계

Sujin Kingslen 미디엄기사

이후에 2진수 형태의 문자를 보이지 않는 문자 유니코드 6개를 사용하여 변환해 줍니다. 
Hi의 2진수를 사용할 경우 각 표에 대응하여 BCCAABBB라는 결과가 나오게 됩니다.
 

Sujin Kingslen 미디엄기사

중복을 줄이는 압축과정을 한 번 더 거치게 되는데 가장 많이 반복되는 두 개의 보이지 않는 유니코드 문자열을 선택한 뒤 여분의 유니코드문자로 대체합니다.
예를 들어서 Hello의 경우 BCCAABBB라는 결과가 나오게 되었는데 여기에서 가장 많이 반복되는 보이지 않는 문자 코드 두 개를 선택하여 (U+200D, U+200C) 두 번 연속적으로 나올 경우 하나의 U+2063 또는 U+2064로 대체되어 나오게 됩니다.
이때 가장 많이 사용된 게 B이고 두 번째로 가장 많이 사용된게 CC와 AA가 있는데 이 둘중에서는 우선순위 큐에 따라서 먼저 큐에 들어간 문자(먼저 입력된 문자)가 우선순위를 가지게 됩니다. 
 
때문에 BCC는 그대로 출력되고 기존 AA가 연속 두 번 출력되는 대신 F(U+2064)로 대체되며 BCCF가 되고 이후 BB또한 연속 두번 출력되는 대신에 E(U+2063)으로 대체되어 BCCFEB로 출력됩니다.
 
이렇게 압축할 경우 더 많은 데이터를 작은 문자열에 숨길 수 있으므로, 더 효율적으로 데이터를 숨길 수 있게 됩니다. 하지만 만약 BCCAABBB를 사용한다고 해서 데이터를 숨길 수 없는 것은 아닙니다. 단지, 보안이나 압축률이 더 낮아서 더 많은 데이터를 숨기기에는 어려울 수 있을 뿐입니다.
 
 

암호화 과정 3단계

Sujin Kingslen 미디엄기사

평문으로 사용했던 "Hi"라는 문자열은 위의 암호화 과정을 거치게 되면 BCCFEB라는 결과를 가지게 되고 일반 평문 Hello World 사이에 보이지 않는 문자를 사용하여 암호문을 삽입할 수 있습니다.
실제로 텍스트 (10자) + 암호문 (6자) = 16자이지만 우리 눈에는 10자로 보이게 됩니다.
 
 
 

Stegcloaks 사용방법

깃허브 페이지를 확인해 보면 Nods.js의 npm패키지를 사용하여 설치하여 로컬환경에서 사용하는 방법과 CLI환경에서 사용할 수 있는 방법이 안내되어 있습니다. 그리고 웹 인터페이스를 통한 웹페이지를 통한 사용 방법이 있는데 저는 따로 설치는 하지 않고 배포 중인 웹페이지를 통해 사용해 보겠습니다.

728x90
실제 웹페이지

홈페이지에 접속하면 필요한 기능만 사용할 수 있도록 불필요한 광고 없이 깔끔하게 나와있습니다.
 
 

암호화 시도

1. 숨겨질 텍스트와 2. 비밀번호를 입력한 뒤에 3. 최종적으로 보일 텍스트를 입력해 준 뒤 Hide 버튼을 눌러주세요.
 

암호화 메세지 작성

저는 이렇게 내용을 작성한 뒤 숨겨보겠습니다.
 
 

암호화 결과

텍스트가 완성되었습니다. 이제 저 텍스트 안에는 저의 비밀메시지가 숨겨져 있습니다.
텍스트를 복사하기 위해서는 오른쪽상단 복사 아이콘을 클릭하여 복사할 수 있습니다.
웹페이지에 게시할 수 있으며 이제 해당 메시지를 복호화해보겠습니다.
 
 

복호화

홈페이지 하단에 REVEAL탭에서 암호화할 때 사용한 Password를 넣은 뒤 암호화된 메시지를 넣고 Get Secret버튼을 누르고 숨겨진 SECRET메시지가 등장하게 됩니다.
 
이렇게 텍스트 안에 스테가노그래피기술을 사용하여 암호화인지 눈치채지 못하도록 내용을 숨겨서 SNS나 웹사이트등에 게시할 수 있습니다. 암호문인 게 노출되더라도 복호화 시에는 개인 고유 패스워드가 필요하게 됩니다.
 
 
 

숨겨진 메시지를 복호화해보세요.

아래는 제가 암호화한 내용입니다. 비밀번호 1234를 사용하여 복호화해보세요!

이 텍스트 안에는 ⁣‍‌⁢‌⁢‍‌⁢‍‌⁤‍⁡⁤⁣‌‌⁡⁣‍‌⁡⁢‌⁣⁣⁣‍‌⁤‍⁡⁡‌‌⁡⁢⁡⁤⁢‌‌⁡⁡⁣⁡‍⁡⁡‍⁢‍⁡‌⁣‌⁢⁡⁡⁡⁢‌⁢‌⁣‍⁡‍⁢‌‌‍⁡⁡⁤⁤‍‌⁢‌‍⁡⁢‌‍⁢⁡⁢⁡⁣⁢‌⁡‌‍⁡⁡⁡‍‌‌‌‌‌‍‌⁡‌⁢⁡‍⁢⁡⁢⁡⁣⁤⁡⁡⁢⁣‌‍⁤⁢⁡⁢‌‌‍⁤⁡⁢‌⁢‍⁢‌‍‌‌‌⁤‍‌⁡‌‌‌⁡⁡⁡⁣⁡⁡뭐가 숨겨져 있을까요?

 

참고자료

Sujin Kingslen미디엄 기사, Stegcloak 깃허브페이지, symbl.cc

Top