Diffie-Hellman (DH) 키 교환 비대칭키 알고리즘 이해하기
오늘은 비대칭키 암호화 알고리즘 중 하나인 Diffie-Hellman (DH) 키 교환에 대해 이야기해 보겠습니다. Diffie-Hellman 키 교환 알고리즘은 안전한 방식으로 비밀키를 교환할 수 있도록 해 주는 알고리즘으로, 네트워크 상에서 중요한 정보를 주고받을 때 많이 사용됩니다. 이 글에서는 DH 알고리즘의 기본 개념부터, Java 언어와 Linux C 언어로 구현하는 예제를 함께 살펴보겠습니다.
Diffie-Hellman 키 교환 알고리즘의 개념
Diffie-Hellman 키 교환 알고리즘은 1976년 Whitfield Diffie와 Martin Hellman이 개발한 공개키 암호화 기법입니다. 이 알고리즘의 목적은 네트워크를 통해 두 사용자가 서로 통신하며 공유할 비밀 키를 안전하게 생성하는 것입니다. 이 과정에서 주고받는 정보는 공개된 값이지만, 최종적으로 생성되는 비밀 키는 외부에서 유추할 수 없습니다.
주요 원리
- 공개 소수와 원시 원소 공유:
- 통신을 하는 두 사용자 A와 B는 먼저 공개된 큰 소수 ( p )와 원시 원소 ( g )를 선택합니다. ( p )와 ( g )는 누구나 알 수 있는 값입니다.
- 개인 키 선택:
- 사용자 A와 B는 각각 비밀 키 ( a )와 ( b )를 선택합니다. 이 비밀 키는 절대 공개되지 않습니다.
- 공개 키 계산 및 교환:
- A는 자신의 공개 키 ( A = g^a \mod p )를 계산하고, B는 자신의 공개 키 ( B = g^b \mod p )를 계산합니다. 이후 A와 B는 서로 자신의 공개 키를 교환합니다.
- 공유 비밀 키 계산:
- A는 B의 공개 키를 이용해 공유 비밀 키를 ( S = B^a \mod p )로 계산하고, B는 A의 공개 키를 이용해 공유 비밀 키를 ( S = A^b \mod p )로 계산합니다. 이 두 값은 동일하며, 이를 통해 안전한 통신을 위한 비밀 키로 사용할 수 있습니다.
이 알고리즘은 공개된 정보만으로는 최종 비밀 키를 계산하기가 어렵다는 수학적 어려움에 기반합니다. 이를 통해 두 사용자는 안전하게 비밀 키를 교환할 수 있습니다.
Java로 Diffie-Hellman 키 교환 구현하기
Java에서는 기본적으로 제공되는 암호화 라이브러리를 이용해 Diffie-Hellman 키 교환 알고리즘을 구현할 수 있습니다. 아래는 Java로 DH 키 교환을 구현한 예제입니다.
import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class DiffieHellmanExample {
public static void main(String[] args) throws Exception {
// 1. 파라미터 생성 (p와 g)
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
paramGen.init(512);
AlgorithmParameters params = paramGen.generateParameters();
DHParameterSpec dhSpec = params.getParameterSpec(DHParameterSpec.class);
// 2. A의 키 쌍 생성
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
keyPairGen.initialize(dhSpec);
KeyPair keyPairA = keyPairGen.generateKeyPair();
// 3. B의 키 쌍 생성
KeyPairGenerator keyPairGenB = KeyPairGenerator.getInstance("DH");
keyPairGenB.initialize(dhSpec);
KeyPair keyPairB = keyPairGenB.generateKeyPair();
// 4. 공개 키 교환
byte[] publicKeyA = keyPairA.getPublic().getEncoded();
byte[] publicKeyB = keyPairB.getPublic().getEncoded();
// 5. 공유 비밀 키 계산 (A 측)
KeyFactory keyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(publicKeyB);
PublicKey publicB = keyFactory.generatePublic(x509Spec);
KeyAgreement keyAgreeA = KeyAgreement.getInstance("DH");
keyAgreeA.init(keyPairA.getPrivate());
keyAgreeA.doPhase(publicB, true);
byte[] sharedSecretA = keyAgreeA.generateSecret();
// 6. 공유 비밀 키 계산 (B 측)
X509EncodedKeySpec x509SpecB = new X509EncodedKeySpec(publicKeyA);
PublicKey publicA = keyFactory.generatePublic(x509SpecB);
KeyAgreement keyAgreeB = KeyAgreement.getInstance("DH");
keyAgreeB.init(keyPairB.getPrivate());
keyAgreeB.doPhase(publicA, true);
byte[] sharedSecretB = keyAgreeB.generateSecret();
// 7. 결과 출력
System.out.println("A의 공유 비밀 키: " + Base64.getEncoder().encodeToString(sharedSecretA));
System.out.println("B의 공유 비밀 키: " + Base64.getEncoder().encodeToString(sharedSecretB));
}
}
이 코드에서는 Java의 표준 암호화 라이브러리를 사용해 DH 키 교환을 수행합니다. 키 쌍 생성, 공개 키 교환, 공유 비밀 키 계산의 단계를 거치며, 최종적으로 동일한 공유 비밀 키가 양측에서 계산됩니다.
Linux C 언어로 Diffie-Hellman 키 교환 구현하기
Linux 환경에서는 OpenSSL 라이브러리를 이용해 Diffie-Hellman 키 교환을 구현할 수 있습니다. 다음은 C 언어로 작성한 예제입니다.
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
// 1. DH 객체 생성
DH *dh = DH_new();
if (dh == NULL) {
fprintf(stderr, "DH 객체 생성 실패\n");
return 1;
}
// 2. 기본 파라미터 생성 (p와 g)
if (1 != DH_generate_parameters_ex(dh, 512, DH_GENERATOR_2, NULL)) {
fprintf(stderr, "DH 파라미터 생성 실패\n");
DH_free(dh);
return 1;
}
// 3. 키 쌍 생성
if (1 != DH_generate_key(dh)) {
fprintf(stderr, "키 쌍 생성 실패\n");
DH_free(dh);
return 1;
}
// 4. 공개 키 가져오기
const BIGNUM *pub_key = DH_get0_pub_key(dh);
if (pub_key == NULL) {
fprintf(stderr, "공개 키 가져오기 실패\n");
DH_free(dh);
return 1;
}
// 공개 키 출력
char *pub_key_hex = BN_bn2hex(pub_key);
printf("공개 키: %s\n", pub_key_hex);
OPENSSL_free(pub_key_hex);
// 5. DH 객체 해제
DH_free(dh);
return 0;
}
이 예제에서는 OpenSSL 라이브러리를 이용하여 Diffie-Hellman 키 교환을 수행합니다. DH_generate_parameters_ex()
함수를 이용해 p와 g를 생성하고, DH_generate_key()
로 키 쌍을 생성한 뒤 공개 키를 출력합니다.
Linux 환경에서 이 코드를 컴파일하려면 OpenSSL 라이브러리를 링크해야 합니다. 예를 들어, 다음과 같이 컴파일할 수 있습니다:
gcc -o dh_example dh_example.c -lssl -lcrypto
결론
Diffie-Hellman 키 교환 알고리즘은 안전하게 비밀 키를 공유하기 위한 효율적인 방법을 제공합니다. 이 글에서는 Diffie-Hellman 알고리즘의 기본 원리를 설명하고, Java와 Linux C 언어로 구현하는 방법을 예제로 다뤄 보았습니다. 이 과정을 통해 비대칭키 암호화가 실제로 어떻게 동작하는지 조금 더 깊이 이해할 수 있기를 바랍니다.
이제 여러분도 Java와 C 언어를 이용해 직접 Diffie-Hellman 키 교환을 구현해 보세요. 암호화의 기본 원리를 체험해 보면 보안의 중요성을 한층 더 잘 이해하게 될 것입니다.
'Encryption Algorithm' 카테고리의 다른 글
DSA(Digital Signature Algorithm) 비대칭키 암호화 알고리즘 (0) | 2024.11.26 |
---|---|
ElGamal 비대칭키 암호화 알고리즘 (0) | 2024.11.25 |
ECC (Elliptic Curve Cryptography) 비대칭키 암호화 알고리즘 (0) | 2024.11.23 |
RSA 비대칭키 암호화 알고리즘 (0) | 2024.11.22 |
ChaCha20 대칭키 암호화 알고리즘 (0) | 2024.11.21 |