← 목록

TLS

작성: 2024년 02월 06일읽기: 약 7분

개요

TLS(Transport Layer Security)는 컴퓨터간 통신에서 서버와 클라이언트간의 보안된 프라이빗(private) 통신을 도와주는 암호화 프로토콜입니다. "대칭형 암호키"를 사용하여 서버와 클라이언트간의 통신을 암호화하고, 이메일, 메신저, voIP 등에 사용되지만 HTTPS로서 가장 널리 사용됩니다.

용어

SSL(Secure Sockets Layer)는 넷스케이프에서 94~96년에 네비게이터 브라우저의 HTTPS 보안 프로토콜을 추가하면서 개발된 사양입니다. 1999년부터는 IETF(국제 인터넷 표준화 기구)에서 개발된 TLS가 표준이되었고 현재는 2018년 8월에 지정된 TLS 1.3 버전이 표준입니다.

HTTPS는 TLS위에서 HTTP통신을 하는 프로토콜입니다. HTTP는 80번 포트를 사용하지만, HTTPS는 443번 포트를 사용합니다.

HTTP vs HTTPS 예시

Wireshark는 오픈소스 패킷 분석 툴입니다. 네트워크간의 패킷을 캡쳐하여 분석할 수 있는 툴로, 이를 사용하여 HTTP와 HTTPS의 차이를 비교해보겠습니다.

대칭형 키 알고리즘과 TLS 인증서

Node.js 대칭형 키 암호화 예제

실제 인증서와는 다르지만, 개념적으로 TLS 암호화 방식을 이해하기 쉽도록 Node.js에서 대칭형 키 알고리즘을 사용한 코드입니다

다음 커맨드를 통하여 각각 privkey.pem 그리고 fullchain.pem이라는 Private, Public 키를 생성합니다.

# Private 키 생성
openssl genpkey -algorithm RSA -out privkey.pem

# Private 키로부터 Public 키 생성
openssl rsa -pubout -in privkey.pem --out fullchain.pem

다음과 같은 index.js 자바스크립트 파일을 생성합니다.

const fs = require("fs");
const crypto = require("crypto");

// 원본 메세지
const originalMessage = JSON.stringify({ id: "test", password: "test123!" });
// 원본 메세지 버퍼로 변환
const message = Buffer.from(originalMessage, "utf8");

// Public 키 불러오기
const publicKeyPEM = fs.readFileSync("fullchain.pem", "utf8");

// 원본 메세지 암호화
const encryptedMessage = crypto.publicEncrypt(
  { key: publicKeyPEM, padding: crypto.constants.RSA_PKCS1_PADDING },
  message
);

console.log("-----원본 메세지-----");
console.log(originalMessage);
console.log("---------------------\n");
console.log("----암호화 메세지----");
console.log(encryptedMessage.toString("base64"));
console.log("---------------------\n");

// Private 키 불러오기
const privateKeyPEM = fs.readFileSync("privkey.pem", "utf8");
// 암호화 메세지 (base64) 버퍼로 변환
const base64Message = Buffer.from(
  encryptedMessage.toString("base64"),
  "base64"
);
// 복호화
const decryptedMessage = crypto.privateDecrypt(
  { key: privateKeyPEM, padding: crypto.constants.RSA_PKCS1_PADDING },
  base64Message
);
// 복호화 메세지 출력
console.log("----복호화 메세지----");
console.log(decryptedMessage.toString("utf8"));
console.log("---------------------");

위 코드를 node index.js로 실행하게되면 다음과 같이 로그가 콘솔에 기록됩니다:

-----원본 메세지-----
{"id":"test","password":"test123!"}
---------------------

----암호화 메세지----
Fa9BOuQN2Lt+aolzvWk6gzigQONTmRDWxXowZ6eQpGz7W3YKBHokAQ7dNU9BpTxHhEH38AFGp4+VSduNlGqCEtXAdlt4maaDKcxJD4JCEyDsegNwzs2Ps8f8iMqblCwsW8ZV8bgfB6XNP3NXAJX7mtz1GLMBCyZJsaYIe8m/GeSthBLW8pjUb/GG4YIZspeXqvw2aZ4OILxtQSiYptPPKIXsi1PTP0tKKs7cNr8C9lA0TntOTg645TU526MnEIf62ecm4xcKNgMI7JXhdfcguHvmajbbdniBidusNFoQDr/IhhYTZP+XuNuRWHfmjGpGKucQ0mhKOGKwzH/2thvx+w==
---------------------

----복호화 메세지----
{"id":"test","password":"test123!"}
---------------------

서버와 클라이언트는 symmetricKey 라는 키(인증서)를 공유하여 암호화하고 복호화하고, 중간에 패킷은 암호화되어 키(인증서)가 없으면 정보를 해독할 수 없게됩니다.

TLS 인증서 제공방식

도메인 구매를 도와주는 업체(GoDaddy, AWS, 호스팅 KR 등)들에서 일반적으로 인증서도 함께 판매하거나 제공합니다. 또는, Let's Encrypt와 같은 비영리 인증서 기관의 certbot와 같은 툴로 직접 인증서를 발급하고 관리할 수 도 있습니다.

TLS 인증서 특성상 만료일이 있기때문에 정기적으로 재발급을 해야합니다. 업체를 통해 유료 인증서를 제공받는 경우 대부분의 경우 자동으로 재발급을 관리해줍니다. Let's Encrypt Certbot을 사용한 경우 Linux 계열의 운영체제 같은 경우 Crontab, 윈도우 계열은 Task Scheduler 등을 사용하여 재발급하도록 권장합니다.

TLS 인증서 관리 방법