Network/L4

암호화 방식과 암호화 알고리즘

junoshon 2024. 9. 9. 20:46

 

안녕하세요.

저번 글에서는 TLS의 연결 과정에 대해 알아봤습니다.

이번 글에서는 암호화의 방식과 암호화 알고리즘에 대해서 알아보겠습니다.

 

암호화란?

암호화(暗號化) 또는 엔크립션(encryption)은 특별한 지식을 소유한 사람들을 제외하고는 누구든지 읽어볼 수 없도록 알고리즘을 이용하여 정보(평문을 가리킴)를 전달하는 과정이다.

- 출처 : 위키백과

 

위키백과에서 확인할 수 있듯이, 알고리즘을 거쳐 정보를 읽기 힘들게 만드는 과정을 암호화 라고 합니다.

그럼 여기서 말하는 알고리즘은 어떤 걸 의미할까요?

 

암호화 알고리즘은 거창한게 아닙니다. 암호화를 하기 위한 일련의 과정이지요.

간단한 암호화 알고리즘을 살펴볼까요?

 

카이사르 암호 체계

고대 로마의 황제인 율리우스 카이사르 때에 제정된 카이사르 암호를 예로 들어보겠습니다.

카이사르 암호는 간단합니다. 평문의 알파벳을 뒤로 3 글자씩 밀어 사용합니다.

HELLO WORLD 라는 평문의 각 알파벳을 3 글자씩 뒤로 미루면, KHOOR ZRUOG 가 되는 방식이지요.

 

이렇게 평문을 읽기 힘들게 바꾸는 과정을 암호화라 하고, 암호화 하는 방법을 암호화 알고리즘 이라 합니다. 

 

 

암호화의 분류

암호화는 비문의 복호화 가능 여부에 따라 크게 두 가지로 분류할 수 있습니다.

  • 단방향 암호화
  • 양방향 암호화

먼저, 단방향 암호화에 대해 알아보겠습니다.

 

단방향 암호화

단방향 암호화, 출처 : https://auth0.com/blog/hashing-passwords-one-way-road-to-security/

 

단방향 암호화는 암호화한 비문을 다시 복호화 할 수 없습니다.

이상합니다.

누군가는 봐야하니까 암호화를 하는 건데, 복호화할 수 없으면 무슨 의미가 있을까요?

 

단방향 암호화는 데이터의 무결성을 보장하기 위해 사용됩니다.

무결성이란 이 데이터가 변조되지 않은 정도입니다.

감이 잘 안잡힙니다. 단방향 암호화에는 어떤 예시가 있을까요?

 

출처 : https://www.huffingtonpost.kr/news/articleView.html?idxno=21358

 

웹 서비스를 사용할 때, 사용자의 비밀번호를 데이터베이스에 저장한다고 생각해 봅시다.

말 그대로 비밀번호인데, 이를 그대로 저장하면 더 이상 비밀번호가 아니게 됩니다. 따라서 비밀번호를 저장할 때는 암호화하여 저장합니다. 

 

그런데, 만약 이 비밀번호가 유출된다면 어떻게 될까요? 

 

양방향 암호화 방식으로 비밀번호를 저장했다면, 해커가 유출된 비밀번호를 복호화해 사용자의 아이디로 로그인할 수 있습니다.

하지만 단방향 함호화를 했다면, 복호화할 수 없겠죠.

 

하지만 그렇게 되면 진짜 사용자도 문제가 생기게 됩니다. 비밀번호를 변경하거나 회원 탈퇴를 하려고 하는데 본인임을 증명할 수 없게 되죠. 사용자가 비밀번호를 입력해도, 복호화 할 수 없으니 이게 맞는 비밀번호인지 확인할 수가 없습니다.

 

Hash

 

그래서 단방향 암호화에서는 Hash라는 방법을 사용합니다.

사용자가 입력한 평문을 해쉬 함수를 사용해 고정된 크기의 고유한 값(해시 값)으로 암호화합니다.

같은 입력에 대해서는 항상 같은 값으로 암호화하기 때문에, 사용자가 입력한 값을 암호화 한 값과 데이터베이스에 저장된 암호화된 값이 같으면 사용자를 인증할 수 있습니다.

 

대표적인 단방향 암호화 알고리즘 중에는 인증서, 디지털 서명등에 사용되는 SHA-256(평문을 256비트의 암호화 된 해시 문자로 변환) 알고리즘과 비밀번호 저장에 사용되는 bcrypt 알고리즘이 있습니다.

 

 

양방향 암호화

양방향 암호화, 출처 : https://auth0.com/blog/hashing-passwords-one-way-road-to-security/

 

단방향 암호화와 달리 양방향 암호화는 암호화 된 비문을 다시 평문으로 복호화할 수 있습니다.

암호화의 목적은 특정 인물만 데이터를 읽을 수 있게 하는 것입니다.

암호화를 하는데도 Key 가 필요하고,  암호를 읽으려고 하는 쪽에서도 비문을 복호화 할 수 있는 Key 가 필요합니다.

 

암호화화 복호화를 같은 키로 하면 대칭 키 암호화 방식이고, 다른 키로 하면 비대칭 키 암호화 방식입니다.

 

이해하기 쉽게 예시를 들어보겠습니다.

출처 : Chat GPT

군대에서는 탄약을 보관하기 위해 자물쇠를 2개 사용합니다. 그래서 탄약통을 개봉할 때는 항상 키를 2개씩 가지고 다녀야 하고, 자물쇠도 2번 열어야 합니다.

 

만약 이 자물쇠가 1개라면 어떻게 될까요? 

탄약통을 개봉할 때는 편하고 빠를 겁니다. 자물쇠를 한 개만 열면 되니까요.

 

하지만 탄약통을 여는 키를 아군에게 전달하는 과정에서 적군에게 키를 빼앗긴다면, 적군은 탄약통을 열어 탄약을 탈취할 수 있습니다. 총알이 없으면 전쟁에서도 패배하겠지요.

자물쇠가 2개였다면 한 개는 적군에게 뺏기더라도 나머지 한개는 있기 때문에 적군은 탄약을 가질 수 없겠죠. 

 

프로그래밍 세계에서도 마찬가지입니다.

키를 1개만 사용하는 대칭키 암호화와 키를 2개 사용하는 비대칭키 암호화가 있습니다.

군대에서와 마찬가지로 키가 1개면 더 빠르지만 키를 전달하는 과정에서 탈취의 위험이 있고, 키가 2개면 1개가 탈취되어도 공격자가 데이터를 볼 수 없기 때문에 안전하지만, 느리지요.

 

대칭키 암호화와 비대칭키 암호화에 대해 알아보겠습니다.

 

대칭키 암호화

대칭키 암호화

암호화와 복호화에 같은 키를 사용하는 방식입니다.  

대칭키 암호화는 계산이 비교적 단순하기 때문에 빠르고 효율적입니다. 따라서 대용량 데이터 암호화 등 빠른 속도를 필요로 하는 경우에 사용됩니다.

 

대표적인 대칭키 암호화 알고리즘은 아래와 같습니다.

 

  • AES-XXX(Advanced Encryption Standard)
    • 가장 대표적인 대칭키 암호화 알고리즘입니다. 키의 길이가 몇 bit인지에 따라 AES-128, AES-192, AES-256 등으로 구분됩니다.
    • 이전 글에서 살펴봤듯이, SSL/TLS 프로토콜에서 데이터를 주고받을 때 AES-256 알고리즘으로 암호화합니다.
  • DES(Data Encryption Standard)
    • 과거 많이 사용되던 암호화 알고리즘으로, 키의 길이가 64비트입니다. 이 중 8비트는 검사용이므로, 실제 키 길이는 56비트입니다.

출처 : https://2jinishappy.tistory.com/338

하지만 대칭키 암호화 알고리즘은 키 관리에 유의해야 합니다.

암복호화에 같은 키를 사용하기 때문에 송신자와 수신자 간 키를 전달해야 하는데, 키를 전달하는 사이에 키를 공격자에게 탈취당하면 공격자가 복호화할 수 있기 때문입니다.

 

따라서 대칭키 암호화에서는 Diffie-Hellman 알고리즘으로 키를 교환하기도 합니다.

TLS 프로토콜의 패킷을 캡처해 Diffie-Hellman 키 교환 방식에 대해 알아보겠습니다.

TLS 프로토콜의 Diffie-Hellman 키 교환, 출처 : https://se-juno.tistory.com/7

위 패킷은 TLS 프로토콜의 연결 단계입니다. Diffie-Hellman 알고리즘에 의해 공개된 키(Pubkey)를 공유하고 있습니다.

 

TLS 연결 수립 과정 중 Client Hello 단계와 Server Hello 단계에서 생성한 랜덤 값과 공개된 키를 통해 암호화에 필요한 비밀키를 도출해 냅니다. (TLS 연결 수립 과정에 대한 내용은 이전 글을 참고해 주세요.)

 

즉, 중간에 공개키가 탈취되더라도 클라이언트의 랜덤 값을 모르면 복호화할 수 없습니다.

 

 

 

비대칭키 암호화

비대칭키 암호화

대칭키 암호화와는 달리, 암호화와 복호화에 서로 다른 키를 사용하는 암호화 방식입니다.

데이터를 암호화하는 데 사용되는 공개키와 복호화하는 데 사용되는 비밀키가 서로 다릅니다. 따라서 공개키 암호화라고도 불립니다.

 

대칭키 암호화의 단점이었던 키 교환 문제는 해결할 수 있지만, 계산이 복잡해 속도가 상대적으로 느립니다.

따라서 키 교환이나 디지털 서명에만 비대칭키 암호화를 사용하고, 데이터 전송 자체는 대칭키 암호화 방식으로 처리하는 경우가 많습니다.

 

대표적인 비대칭키 암호화 알고리즘은 아래와 같습니다.

 

  • RSA(Rivest Shamir Adleman)
    • 가장 널리 사용되는 비대칭키 암호화 알고리즘이며, 개발한 개발자들의 이름을 따 RSA라 이름 지어졌습니다.
    • 소인수분해의 난해성을 기반으로 하는 알고리즘입니다.
      • 예를 들어 3223이라는 소수가 어떤 두 소수의 곱인지를 나타내려면, 3233을 가장 작은 소수부터 하나씩 나눠보면서 나누어 떨어지는 숫자를 찾아야 합니다. 숫자가 작은 경우라면 금방 계산할 수 있지만, RSA 알고리즘에서는 수백 자리의 소수를 사용하므로 많은 계산이 필요합니다.
    • 키의 길이는 1024비트부터 4096비트까지 될 수 있으며, 키의 길이가 길수록 보안성이 강화됩니다.
  • ECC(Elliptic curve cryptography)
    • 아래 그림과 같은 타원 곡선의 수학적 구조를 기반으로 한 비대칭키 암호화 알고리즘입니다.

타원곡선 y^2=x^3+ax+b 의 그래프

위 그림에서 타원 위의 임의의 기준점을 P라 가정해 봅시다. 그리고 암호화에 사용할 공개키는 Q, 복호화에 사용할 비밀키는 d입니다.

타원 곡선에서는 d*P = Q의 관계를 가집니다.

만약 d를 알고 있다면 기준점 P에서 d번의 연산을 통해 공개키인 Q를 얻는 건 쉬운 계산입니다.

 

하지만 공개키 Q만 알고 비밀키 d는 모르는 상태에서 기준점 P가 어떻게 나왔는지를 찾는 과정은 매우 어려운 계산입니다. 

 

 

선형 그래프와 비선형 그래프

 

y=2x 의 그래프

y=2x와 같은 직선의 그래프는 한쪽의 미지수만 알면 나머지 미지수를 계산하는데 어렵지 않습니다. x가 3이면 y를 모르더라도 6이고, y가 6이면 x를 몰라도 x가 3 임을 유추하는 게 어렵지 않지요. 이처럼 변화가 규칙적이며, 이를 선형적이라 합니다.

 

y=x^2 의 그래프

하지만 y=x^2와 같은 그래프는 x값의 증가에 따른 y값의 증가가 규칙적이지 않습니다. x가 2면 y는 4지만, x가 10이면 y는 100이지요.

이처럼 곡선의 그래프는 변화가 불규칙적이기 때문에 역으로 계산하려면 비교적 많은 연산이 필요합니다.

 

 y^2=x^3+ax+b의 식을 가지는 타원 곡선 방정식은 그래프의 변화가 매우 불규칙합니다. 즉, 비선형적 변화를 가지지요.

비밀키인 d는 일반적으로 256비트의 숫자로 표현되는데, d를 알아내기 위한 경우의 수는 2^256 이 됩니다. 이는 1157 해 9208 경 9237 조 3161 억 9542 만 3570이며, 이를 계산해서 알아내기엔 불가능에 가깝습니다.

 

출처 : https://cheapsslsecurity.com/p/ecc-vs-rsa-comparing-ssl-tls-algorithms/

ECC 알고리즘은 RSA 알고리즘에 비해 작은 비밀키의 크기로 더 많은 경우의 수를 만들어낼 수 있습니다.

RSA 알고리즘의 비밀키 길이로 3072 비트를 사용해야 ECC 알고리즘에서 256 비트로 비밀키를 만들 때와 비슷한 보안의 수준을 제공한다고 알려져 있습니다.

 

 

Curve 25519 그래프

ECC 알고리즘은 여러 종류가 있지만, 그중 Ed25519 방식이 많이 사용됩니다. 

Ed25519 알고리즘은 위와 같은 Curve 25519라는 타원 곡선 위에서 동작하며, 128비트의 비밀키 길이로도 충분한 보안 수준을 제공합니다.  따라서 아래와 같은 사례에서 광범위하게 사용되고 있습니다.

 

  • SSH 키 교환
  • TLS 통신 시 디지털 서명
  • 암호화폐
  • GPG 서명
  • 컨테이너 이미지

 

대칭키 암호화와 비대칭키 암호화 시간 비교

대칭키 암호화 알고리즘 중 AES-256과 비대칭키 암호화 알고리즘 중 RSA 알고리즘으로 데이터를 복호화할 때 소요되는 시간을 비교해 보겠습니다.

 

JavaScript의 crypto 라이브러리를 사용했습니다. 

const crypto = require("crypto");

// 원본 데이터
const data = "Secret data to encrypt";

// ---------------- AES-256 암호화 및 복호화 ---------------- //

// AES-256 키와 IV 생성
const aesKey = crypto.randomBytes(32); // 256비트 키 (32바이트)
const aesIv = crypto.randomBytes(16); // IV (초기화 벡터)

// AES-256 암호화
const aesCipher = crypto.createCipheriv("aes-256-cbc", aesKey, aesIv);
let aesEncrypted = aesCipher.update(data, "utf8", "hex");
aesEncrypted += aesCipher.final("hex");

console.log("AES-256 암호화된 데이터:", aesEncrypted);

// AES-256 복호화 시간 측정
const aesDecipher = crypto.createDecipheriv("aes-256-cbc", aesKey, aesIv);

console.time("AES-256 복호화에 걸린 시간");
let aesDecrypted = aesDecipher.update(aesEncrypted, "hex", "utf8");
aesDecrypted += aesDecipher.final("utf8");
console.timeEnd("AES-256 복호화에 걸린 시간");

console.log("AES-256 복호화된 데이터:", aesDecrypted);

// ---------------- RSA 암호화 및 복호화 ---------------- //

// RSA 2048비트 키 생성
const { generateKeyPairSync } = crypto;
const { publicKey, privateKey } = generateKeyPairSync("rsa", {
  modulusLength: 2048,
});

// RSA 암호화 (공개 키 사용)
const rsaEncrypted = crypto.publicEncrypt(publicKey, Buffer.from(data, "utf8"));

console.log("RSA 암호화된 데이터:", rsaEncrypted.toString("hex"));

// RSA 복호화 시간 측정 (개인 키 사용)
console.time("RSA 복호화에 걸린 시간");
const rsaDecrypted = crypto.privateDecrypt(privateKey, rsaEncrypted);
console.timeEnd("RSA 복호화에 걸린 시간");

console.log("RSA 복호화된 데이터:", rsaDecrypted.toString("utf8"));

대칭키 암호화 알고리즘인 AES-256 은 복호화에 0.057 ms 가 소요되는 반면, 비대칭키 암호화 알고리즘인 RSA는 0.873 ms 가 소요되었습니다. 데모에서는 별 차이 없어 보이지만, 데이터의 크기가 커지면 이를 암복호화 하는데 두 알고리즘 간 차이가 극명해질 것입니다.

 

마치며

이번 문서에서는 암호화의 방식과 암호화 알고리즘에 대해 알아봤습니다.

지적 및 질문은 댓글로 부탁드립니다.긴 글 읽어주셔서 감사합니다.

 

'Network > L4' 카테고리의 다른 글

Load Balancer 종류 소개  (2) 2025.05.01
TCP와 TLS의 동작 원리 #2  (2) 2024.09.07
TCP 와 TLS의 동작 원리 #1  (0) 2024.09.06