inblog logo
|
DailyCoding
    Spring Boot

    10-1. RSA

    박은서's avatar
    박은서
    Feb 06, 2026
    10-1. RSA
    Contents
    1. RSA 암호0️⃣ 필기1️⃣ 보안의 3요소 (CIA)2️⃣ 기존 통신 환경의 문제3️⃣ 대칭키 암호의 한계4️⃣ 디피-헬만(Diffie-Hellman) 키 교환5️⃣ RSA의 등장 배경6️⃣ RSA 기본 개념7️⃣ RSA 통신 시나리오 (예시)8️⃣ RSA 핵심 요약9️⃣ 한 줄 요약🔟 실습

    1. RSA 암호

    0️⃣ 필기

    notion image
    notion image
    💡
    상민이가 a공개키라고 하고 자신의 공개키를 공개하면 이게 누구의 공개키인지 알 수 없음! 그래서 RSA로 대칭키를 전달해서 대칭키 전달의 문제 해결하고 정말 보내고자 하는 내용은 대칭키로 잠궈서 보냄!

    1️⃣ 보안의 3요소 (CIA)

    • 기밀성 (Confidentiality)
      • → 허가된 사람만 메시지를 볼 수 있어야 함
    • 무결성 (Integrity)
      • → 메시지가 중간에 위·변조되지 않았음을 보장
    • 가용성 (Availability)
      • → 필요할 때 정상적으로 사용 가능

    2️⃣ 기존 통신 환경의 문제

    1) 상황

    • 송신자 홍군 A (50명) ↔ 수신자 홍군 B (50명)
    • 중간 공격자(청군) 약 70명
    • 공격 방식
      • 도청: 평문(Plaintext) 그대로 탈취
      • 위조: 메시지를 바꿔치기 (무결성 깨짐)

    2) 문제점

    • 암호화를 안 하면 → 기밀성 X
    • 암호화를 해도:
      • “누가 보냈는지” 확인 불가 → 무결성 X
      • 열쇠를 안전하게 전달할 방법이 없음

    3️⃣ 대칭키 암호의 한계

    • 암호화(C)와 복호화에 같은 키 사용
    • 장점: 빠름
    • 치명적 단점:
      • 🔑 키를 안전하게 전달할 방법이 없음
      • 키가 탈취되면 모든 보안 붕괴

    4️⃣ 디피-헬만(Diffie-Hellman) 키 교환

    1) 목적

    • 기밀성 확보
    • 공개된 채널에서도 공통 비밀키 생성

    2) 개념 흐름

    1. 공개 정보
        • 공통 소수 ggg
        • 공통 모듈러 ppp
    1. 개인 비밀
        • A의 비밀값 aaa
        • B의 비밀값 bbb
    1. 계산
        • A → gamod  pg^a \mod pgamodp
        • B → gbmod  pg^b \mod pgbmodp
    1. 최종 공유 비밀
        • (gb)a=(ga)b(g^b)^a = (g^a)^b(gb)a=(ga)b

    3) 핵심

    • 공개키 값은 커질수록 경우의 수 폭증
    • 역으로 비밀값을 구하는 것이 매우 어려움

    4) ⚠️ 한계

    • 누가 보냈는지 증명 불가 → 무결성 해결 안 됨

    5️⃣ RSA의 등장 배경

    • Diffie-Hellman: 기밀성 O / 무결성 X
    • RSA 목표:
      • ✅ 기밀성
      • ✅ 무결성
      • 공개키 환경에서 안전한 통신

    6️⃣ RSA 기본 개념

    1) 키 구조 (2개)

    • 공개키 (Public Key) → open
    • 개인키 (Private Key) → close

    2) 특징

    • 공개키로 암호화한 메시지는
      • → 오직 대응되는 개인키로만 복호화 가능
    • 개인키는 절대 공개 ❌

    7️⃣ RSA 통신 시나리오 (예시)

    상황

    • 길동 → 꺽정에게 메시지 전송
    • 중간에 상민(공격자) 존재

    ① A의 개인키만 사용 (서명 X)

    • A 개인키로 암호화 → 누구나 공개키로 열 수 있음
    • ❌ 기밀성 없음
    • ✔️ 무결성은 어느 정도 확보

    ② B의 공개키만 사용

    • 기밀성 O
    • ❌ 누가 보냈는지 알 수 없음
    • 상민이 메시지 위조 가능

    ③ RSA 핵심 방식 (정답)

    1. B의 공개키로 암호화
      1. → 기밀성 확보
    1. A의 개인키로 서명
      1. → 무결성 확보
    수신자 B는:
    1. A의 공개키로 서명 검증 (누가 보냈는지 확인)
    1. B의 개인키로 메시지 복호화
    ➡️ 기밀성 + 무결성 모두 충족

    8️⃣ RSA 핵심 요약

    • 🔐 공개키 암호 방식
    • 🔑 키 전달 문제 해결
    • ✍️ 전자서명으로 무결성 확보
    • 📌 Diffie-Hellman의 단점을 보완

    9️⃣ 한 줄 요약

    RSA는 “공개키 암호 + 전자서명”을 통해 기밀성과 무결성을 동시에 만족시키는 암호 방식이다.

    🔟 실습

    implementation "com.nimbusds:nimbus-jose-jwt:9.37.3"
    import com.nimbusds.jose.*; import com.nimbusds.jose.crypto.RSADecrypter; import com.nimbusds.jose.crypto.RSAEncrypter; import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; import java.nio.charset.StandardCharsets; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; public class RSAUtil { // RSA 키 생성 (개인키, 공개키) public static RSAKey generateRSAKey(String keyId) throws JOSEException { return new RSAKeyGenerator(2048).keyID(keyId).generate(); } // 공개키로 암호화 public static String encrypt(String message, RSAPublicKey publicKey) throws JOSEException { JWEObject encryptObject = new JWEObject( new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM), new Payload(message.getBytes(StandardCharsets.UTF_8)) ); encryptObject.encrypt(new RSAEncrypter(publicKey)); return encryptObject.serialize(); } // 개인키로 서명 public static String sign(String payload, RSAPrivateKey privateKey) throws JOSEException { JWSObject signObject = new JWSObject( new JWSHeader(JWSAlgorithm.RS256), new Payload(payload) ); signObject.sign(new RSASSASigner(privateKey)); return signObject.serialize(); } // 공개키로 서명검증 public static String verifySignature(String signedToken, RSAPublicKey publicKey) throws Exception { JWSObject signObject = JWSObject.parse(signedToken); if (signObject.verify(new RSASSAVerifier(publicKey))) { return signObject.getPayload().toString(); }else{ throw new RuntimeException("공개키 서명 검증 실패"); } } // 개인키로 복호화 public static String decrypt(String encryptedToken, RSAPrivateKey privateKey) throws Exception { JWEObject encryptObject = JWEObject.parse(encryptedToken); encryptObject.decrypt(new RSADecrypter(privateKey)); return encryptObject.getPayload().toString(); } }
    import com.nimbusds.jose.*; import com.nimbusds.jose.crypto.*; import com.nimbusds.jose.jwk.RSAKey; public class RSADemo { public static void main(String[] args) throws Exception { String msg = "나는 오늘 백운포에 송원 왕갈비를 먹으러 간다 비밀이다!!"; // 0. A(송신자), B(수신자) RSA 키 생성 RSAKey aKey = RSAUtil.generateRSAKey("A"); RSAKey bKey = RSAUtil.generateRSAKey("B"); RSAKey cKey = RSAUtil.generateRSAKey("C"); // ===== 송신 과정 ===== // 1. 수신자(B)의 공개키로 암호화 String encrypted = RSAUtil.encrypt(msg, bKey.toRSAPublicKey()); System.out.println("1. 암호화: " + encrypted.substring(0, 50) + "..."); // 2. 송신자(A)의 개인키로 서명 String signed = RSAUtil.sign(encrypted, aKey.toRSAPrivateKey()); System.out.println("2. 서명: " + signed.substring(0, 50) + "..."); System.out.println(); // ===== 수신 과정 ===== // 3. 송신자(A)의 공개키로 서명 검증 String verify = RSAUtil.verifySignature(signed, aKey.toRSAPublicKey()); System.out.println("3. 서명 검증: " + verify); // 4. 수신자(B)의 개인키로 복호화 String decrypted = RSAUtil.decrypt(verify, bKey.toRSAPrivateKey()); System.out.println("4. 복호화: " + decrypted); } }
    Share article
    Contents
    1. RSA 암호0️⃣ 필기1️⃣ 보안의 3요소 (CIA)2️⃣ 기존 통신 환경의 문제3️⃣ 대칭키 암호의 한계4️⃣ 디피-헬만(Diffie-Hellman) 키 교환5️⃣ RSA의 등장 배경6️⃣ RSA 기본 개념7️⃣ RSA 통신 시나리오 (예시)8️⃣ RSA 핵심 요약9️⃣ 한 줄 요약🔟 실습

    DailyCoding

    RSS·Powered by Inblog