RSA + AES 하이브리드 암호화

GEONNY·2024년 9월 10일
0

Building-API

목록 보기
27/28
post-thumbnail

📌하이브리드 암호화(Hybrid Encryption)

이전에 알아보았던 RSAAES 암호화를 혼합해서 사용하는 하이브리드 암호화 방식에 대해 알아보도록 하겠습니다. 이 방식은 대칭키 암호화(AES)와 비대칭키 암호화(RSA)를 함께 사용하여, 보안성과 성능을 모두 최적화하는 것이 목표입니다. 주로 RSA로 AES의 대칭키를 안전하게 전달하고, AES는 실제 데이터를 빠르고 효율적으로 암호화하는 방식으로 동작합니다.

📌하이브리드 암호화의 동작 방식

1.AES, RSA 키 생성

서버는 대칭키인 AES 키와 비대칭 키인 RSA 키를 생성합니다. 대칭 키는 동일한 키로 암복호화가 가능하고, 비대칭 키는 Private key 로 암호화, Public key 로 복호화가 가능합니다.

2. 키 전송

데이터를 암호화 하기 위한 AES 비대칭 키를 전송합니다. 이 때, AES 키는 RSA Private key 로 암호화 하여 전송합니다. 결론적으로 RSA Private key로 암호화된 AES key 와 RSA 복호화를 위한 Public 키를 같이 전송합니다.

3.데이터 암호화(AES)

클라이언트는 받은 RSA Public key로 암호화된 AES key를 복호화 하고, AES key를 사용하여 데이터를 암호화 합니다. AES는 대용량 데이터를 암호화할 때 빠르게 처리할 수 있기 때문에, 대량의 데이터를 효율적으로 보호할 수 있습니다.

4. 전송

클라이언트는 AES로 암호화된 데이터를 전송하고, 서버는 받은 데이터를 AES 키로 복호화 합니다.

결론적으로 AES key로는 데이터를 암/복호화하고 RSA로는 AES의 키만 암/복호화 하는 방식입니다.

📌Hybrid 암호화의 장점

보안성
RSA의 비대칭키 암호화를 사용해 AES 대칭키를 안전하게 전송할 수 있으므로, AES 키 유출 위험을 줄일 수 있습니다.

성능
AES는 대칭키 암호화로 성능이 뛰어나 대량의 데이터를 효율적으로 처리할 수 있습니다.

확장성
AES 대칭키 암호화는 확장성이 좋으며, RSA로 AES 키만 전송하므로 키 관리가 간편합니다.

📌Example

기존에 작성했던 RsaCryptoServiceAesCryptoService 를 활용하겠습니다. Hybrid 방식만 사용하겠다면 기존 코드를 잘 조합해서 활용하세요.

📍HybridCryptoService

common.encryption.hybrid.HybridCryptoService

@Slf4j
@Configuration
@RequiredArgsConstructor
public class HybridCryptoService implements CryptoService {

    private final RsaCryptoService rsaCryptoService;
    private final AesCryptoService aesCryptoService;

    @Override
    @Deprecated
    public void createKey() throws NoSuchAlgorithmException {

    }

    @Override
    public Key getPublicKey() {
        return this.rsaCryptoService.getPublicKey();
    }

    @Override
    public String decrypt(String encryptedText) {
        return this.aesCryptoService.decrypt(encryptedText);
    }

    @Override
    public String encrypt(String plainText) {
        return this.aesCryptoService.encrypt(plainText);
    }

    public String getEncryptedAesKey() {
        SecretKey secretKey = this.aesCryptoService.getPublicKey();
        String secretKeyString = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        return this.rsaCryptoService.encrypt(secretKeyString);
    }
}

위에서 설명한 것과 같이 RSA Public key 로 AES key 를 암호화하는 getEncryptedAesKey method 가 추가되었고, public key는 RSA의 Public key를, 암/복호화는 AES로 동작하고 있습니다.

📍CryptoController

기존 CryptoController 에 Hybrid key를 요청하는 method 를 추가하겠습니다.
domain.crypto.CryptoController

@RestController
@RequiredArgsConstructor
@Tag(name = "암호화 관련 정보 요청", description = "보안이 필요한 정보를 암호화 하기 위한 키 요청")
@RequestMapping("v1")
public class CryptoController {
    private final CryptoService rsaCryptoService;
    private final CryptoService aesCryptoService;
    private final HybridCryptoService hybridCryptoService; //추가
    private final MessageConfig messageConfig;
    
    //생략..
    @Operation(summary = "Hybrid Key 요청", description = """
            Hybrid key<br />
            RSA public key 와 RSA public key 로 암호화된 AES key 를 전달. (Base64 encoded)<br />
            
            전달받은 RSA Public key 로 암호화된 AES 키를 복호화 하고,<br />
            복호화된 AES key 로 데이터를 암호화 하여 전송
            """, operationId = "API-999-03")
    @PostMapping(value = "/key/hybrid", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<ItemResponse<HybridKeyResponse>> getHybridKey() {
        PublicKey publicKey = (PublicKey) this.hybridCryptoService.getPublicKey();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String encryptedAesKey = this.hybridCryptoService.getEncryptedAesKey();
        HybridKeyResponse hybridKeyResponse = HybridKeyResponse.builder()
                .publicKey(publicKeyString)
                .encryptedKey(encryptedAesKey)
                .build();
        return ResponseEntity.ok()
                .body(ItemResponse.<HybridKeyResponse>builder()
                        .status(messageConfig.getCode(NormalCode.SEARCH_SUCCESS))
                        .message(messageConfig.getMessage(NormalCode.SEARCH_SUCCESS))
                        .item(hybridKeyResponse)
                        .build());
    

domain.crypto.record.HybridKeyResponse

@Builder
public record HybridKeyResponse(
        String publicKey,
        String encryptedKey
) {
}

클라이언트는 받은 public key 로 encryptedKey를 복호화 하여 AES key를 추출하고 AES key로 데이터를 암호화 하여 전송합니다. 서버는 암호화된 데이터는 AES key로 복호화 하여 처리합니다.

📌Conclusion

하이브리드 암호화는 RSA의 강력한 보안과 AES의 효율적인 성능을 동시에 충족하는 방식으로, 대규모 데이터 전송 및 보호가 중요한 다양한 시스템에서 필수적으로 사용되는 암호화 기법입니다. RSA와 AES의 장점을 결합한 이 방식은 데이터 기밀성과 전송 안전성을 극대화하며, 안정적이고 신뢰할 수 있는 보안 솔루션을 제공합니다.
단순히 몇몇 데이만 암호화 하는 경우에는 오버스펙이 될 수 있으니, 암호화 레벨, 주어진 환경에 따라 적절한 암호화 방식을 사용하도록 합시다.

profile
Back-end developer

0개의 댓글