티스토리 뷰
1. AWS IAM 생성하기
KMS는 AWS IAM user나 role을 통해서 권한을 가질 수 있으니 우선 local에서 사용할 IAM user 또는 role을 만들어 줍니다. 저는 user를 만들어서 진행을 해보겠습니다.
2. KMS Key 생성하기
KMS Key를 생성합니다. 이때 키 관리 권한과 키 사용 권한은 위에서 만들어둔 user를 지정합니다.
3. credential 설정하기
먼저 aws cli를 사용하여 암복호화가 되는지 확인하기 위해 설정을 진행합니다.
(1) aws cli 설치
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
(2) aws configure로 credential 설정하기
4. AWS CLI로 암복호화 해보기
아래 명령을 통해 "Hello World"를 암호화해보겠습니다. 알고리즘은 RSAES_OAEP_SHA_256를 사용하였습니다.
aws kms encrypt --key-id YOUR_KEY_ID --plaintext fileb://<(echo -n 'Hello World') --encryption-algorithm RSAES_OAEP_SHA_256
위 명령을 통해 암호화된 문자열을 얻을 수 있습니다. 해당 문자열을 복사해 뒀다가 아래 명령을 통해 복호화할 수 있습니다.
aws kms decrypt --key-id YOUR_KEY_ID --ciphertext-blob fileb://<(echo -n '암호화된_문자열' | base64 --decode) --output text --encryption-algorithm RSAES_OAEP_SHA_256 --query Plaintext | base64 --decode
5. 프로젝트 생성하기
Spring Boot 프로젝트를 생성하고 아래와 같이 dependency를 추가합니다.
implementation("org.zalando:spring-cloud-config-aws-kms:5.1.2")
implementation("com.amazonaws:aws-java-sdk-core:1.11.1019")
implementation("com.amazonaws:aws-java-sdk-kms:1.11.1019")
implementation("com.amazonaws:jmespath-java:1.11.1019")
application.yml 파일에 kms key 와 알고리즘 방식 등의 설정을 해줍니다.
spring:
profiles:
active: default
server:
port: 9090
tomcat:
threads:
max: 512
servlet:
context-path: /v1/kms
encoding:
charset: UTF-8
enabled: true
force: true
aws:
kms:
keyId: 키 아이디
encryptionAlgorithm: "RSAES_OAEP_SHA_256"
이후 service와 controller를 차례로 만들어 줍니다.
package com.example.kms_test.service;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.AWSKMSClientBuilder;
import com.amazonaws.services.kms.model.DecryptRequest;
import com.amazonaws.services.kms.model.EncryptRequest;
import com.amazonaws.services.kms.model.EncryptResult;
import com.amazonaws.services.kms.model.EncryptionAlgorithmSpec;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@Slf4j
@Service
public class KmsService {
@Value("${aws.kms.keyId}")
private String KEY_ID;
public String encrypt(String plainText) {
try {
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.build();
EncryptRequest request = new EncryptRequest();
request.withKeyId(KEY_ID);
request.withPlaintext(ByteBuffer.wrap(plainText.getBytes(StandardCharsets.UTF_8)));
request.withEncryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256);
EncryptResult result = kmsClient.encrypt(request);
ByteBuffer ciphertextBlob = result.getCiphertextBlob();
return new String(Base64.encodeBase64(ciphertextBlob.array()));
} catch (Exception e) {
log.error(e.getMessage());
return null;
}
}
public String decrypt(String encryptedText) {
try {
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.build();
DecryptRequest request = new DecryptRequest();
request.withCiphertextBlob(ByteBuffer.wrap(Base64.decodeBase64(encryptedText)));
request.withKeyId(KEY_ID);
request.withEncryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256);
ByteBuffer plainText = kmsClient.decrypt(request).getPlaintext();
return new String(plainText.array());
} catch (Exception e) {
log.error(e.getMessage());
return null;
}
}
}
package com.example.kms_test.controller;
import com.example.kms_test.service.KmsService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class KmsController {
private final KmsService kmsService;
@GetMapping("/encrypt")
public String encrypt(@RequestParam String plainText) {
return kmsService.encrypt(plainText);
}
@GetMapping("/decrypt")
public String decrypt(@RequestParam String encryptedText) {
return kmsService.decrypt(encryptedText);
}
}
6. 포스트맨으로 확인
이제 프로젝트를 실행하고 아래 사진과 같이 HTTP Request를 날려 결과를 확인합니다.
❗️에러
(1) ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
해당 에러는 Spring Boot 버전과 Cloud 버전이 맞지 않아 발생하는 에러로 아래와 같이 설정을 해주면 해결됩니다!
plugins {
id 'org.springframework.boot' version '2.3.8.RELEASE' // 요기!!!
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
ext {
set('springCloudVersion', "Hoxton.SR9") // 요기!!!
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation("org.zalando:spring-cloud-config-aws-kms:5.1.2")
implementation("com.amazonaws:aws-java-sdk-core:1.11.1019")
implementation("com.amazonaws:aws-java-sdk-kms:1.11.1019")
implementation("com.amazonaws:jmespath-java:1.11.1019")
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
(2) InvalidCiphertextException
복호화를 진행하려고 할 때 다음과 같은 에러가 발생합니다...
null (Service: AWSKMS; Status Code: 400; Error Code: InvalidCiphertextException; Request ID: b42394cd-709b-40e0-b071-1ab763f7dab8; Proxy: null)
이 부분은 아직 해결을 하지 못했습니다...😥 혹시 해결 방법을 알고 계시다면 공유해주시면 감사하겠습니당!
대신 테스트 코드를 작성하여 암복호화를 확인해 보았습니다! 테스트 코드는 잘 작동합니다! (왜일까요...?)
package com.example.kms_test.service;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.AWSKMSClientBuilder;
import com.amazonaws.services.kms.model.DecryptRequest;
import com.amazonaws.services.kms.model.EncryptRequest;
import com.amazonaws.services.kms.model.EncryptResult;
import com.amazonaws.services.kms.model.EncryptionAlgorithmSpec;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
class KmsServiceTest {
private static final String KEY_ID = "KEY_ID";
@Test
void encrypt() {
final String plaintext = "Hello, KMS";
try {
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.build();
EncryptRequest request = new EncryptRequest();
request.withKeyId(KEY_ID);
request.withPlaintext(ByteBuffer.wrap(plaintext.getBytes(StandardCharsets.UTF_8)));
request.withEncryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256);
EncryptResult result = kmsClient.encrypt(request);
ByteBuffer ciphertextBlob = result.getCiphertextBlob();
System.out.println("ciphertextBlob: " + new String(Base64.encodeBase64(ciphertextBlob.array())));
} catch (Exception e) {
System.out.println("encrypt fail: " + e.getMessage());
}
}
@Test
void decrypt() {
final String encriptedText = "XkJcKtmn60fT...nmTEJnw48yjjQy8+A=";
try {
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.build();
DecryptRequest request = new DecryptRequest();
request.withCiphertextBlob(ByteBuffer.wrap(Base64.decodeBase64(encriptedText)));
request.withKeyId(KEY_ID);
request.withEncryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256);
ByteBuffer plainText = kmsClient.decrypt(request).getPlaintext();
System.out.println("plainText: " + new String(plainText.array()));
} catch (Exception e) {
System.out.println("decrypt fail: " + e.getMessage());
}
}
}
[참고]
'AWS' 카테고리의 다른 글
[AWS APIGateway] APIGateway WebSocket API 사용하기 1 (1) | 2023.12.06 |
---|---|
[AWS PreSignedUrl] PreSignedUrl로 S3 Bucket에 파일 업로드 (0) | 2023.11.07 |
[Terraform] Terraform 사용하기 (사전 준비) (0) | 2022.01.04 |
[AWS CloudFront] CloudFront에서 API Gateway로 요청 전달 (0) | 2021.12.16 |
[AWS APIGateway] API Gateway에서 private subnet의 NLB와 통신 (0) | 2021.12.16 |
- Total
- Today
- Yesterday
- 조합
- map
- 소수
- 순열
- permutation
- BFS
- Algorithm
- sort
- CodeDeploy
- cloudfront
- Dynamic Programming
- string
- DFS
- 에라토스테네스의 체
- Baekjoon
- ECR
- EC2
- java
- 프로그래머스
- CodeCommit
- AWS
- spring
- array
- ionic
- search
- CodePipeline
- SWIFT
- programmers
- Combination
- 수학
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |