From f7846425b450eed8192b3e0a598246cc0f21b688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=83=88=EB=A1=AC?= Date: Tue, 9 Sep 2025 16:54:30 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20answerNumber=20,=20answer=20?= =?UTF-8?q?=EA=B0=92=20AES=20=EB=8C=80=EC=B9=AD=ED=82=A4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/quiz/service/QuizPageService.java | 12 ++-- .../cs25service/domain/quiz/util/AesUtil.java | 72 +++++++++++++++++++ .../src/main/resources/application.properties | 4 +- 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java index 948077c7..4491a7f1 100644 --- a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/service/QuizPageService.java @@ -8,6 +8,8 @@ import com.example.cs25service.domain.quiz.dto.TodayQuizResponseDto; import java.util.Arrays; import java.util.List; + +import com.example.cs25service.domain.quiz.util.AesUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,7 +20,7 @@ public class QuizPageService { private final QuizRepository quizRepository; - + private final AesUtil aesUtil; /** * 오늘의 문제를 반환해주는 메서드 * @param quizId 문제 id @@ -56,8 +58,8 @@ private TodayQuizResponseDto getMultipleQuiz(Quiz quiz) { .choice2(choices.get(1)) .choice3(choices.get(2)) .choice4(choices.get(3)) - .answerNumber(answerNumber) - .commentary(quiz.getCommentary()) + .answerNumber(aesUtil.encrypt(answerNumber)) + .commentary(aesUtil.encrypt(quiz.getCommentary())) .quizType(quiz.getType().name()) .quizLevel(quiz.getLevel().name()) .category(getQuizCategory(quiz)) @@ -74,8 +76,8 @@ private TodayQuizResponseDto getDescriptiveQuiz(Quiz quiz) { return TodayQuizResponseDto.builder() .question(quiz.getQuestion()) .quizType(quiz.getQuestion()) - .answer(quiz.getAnswer()) - .commentary(quiz.getCommentary()) + .answer(aesUtil.encrypt(quiz.getAnswer())) + .commentary(aesUtil.encrypt(quiz.getCommentary())) .quizType(quiz.getType().name()) .quizLevel(quiz.getLevel().name()) .category(getQuizCategory(quiz)) diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java new file mode 100644 index 00000000..911cc953 --- /dev/null +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/util/AesUtil.java @@ -0,0 +1,72 @@ +package com.example.cs25service.domain.quiz.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.util.Base64; + +@Component +public class AesUtil { + + private final String secretKey; + + public AesUtil(@Value("${aes.secret.key}") String secretKey) { + this.secretKey = secretKey; + } + + private final String ALGORITHM = "AES/CBC/PKCS5Padding"; + + private SecretKey getKey() { + return new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"); + } + + /** 암호화 */ + public String encrypt(String plainText) { + if (plainText == null) return null; + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + byte[] iv = new byte[16]; + new SecureRandom().nextBytes(iv); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + + cipher.init(Cipher.ENCRYPT_MODE, getKey(), ivSpec); + byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); + + // IV와 암호문을 Base64로 함께 인코딩 + byte[] combined = new byte[iv.length + encrypted.length]; + System.arraycopy(iv, 0, combined, 0, iv.length); + System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length); + + return Base64.getEncoder().encodeToString(combined); + } catch (Exception e) { + throw new RuntimeException("AES encryption error", e); + } + } + + /** 복호화 */ + public String decrypt(String cipherText) { + if (cipherText == null) return null; + try { + byte[] decoded = Base64.getDecoder().decode(cipherText); + + byte[] iv = new byte[16]; + byte[] encrypted = new byte[decoded.length - 16]; + System.arraycopy(decoded, 0, iv, 0, iv.length); + System.arraycopy(decoded, iv.length, encrypted, 0, encrypted.length); + + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv)); + byte[] original = cipher.doFinal(encrypted); + + return new String(original, StandardCharsets.UTF_8); + } catch (Exception e) { + throw new RuntimeException("AES decryption error", e); + } + } +} diff --git a/cs25-service/src/main/resources/application.properties b/cs25-service/src/main/resources/application.properties index 39649f39..95d3c42d 100644 --- a/cs25-service/src/main/resources/application.properties +++ b/cs25-service/src/main/resources/application.properties @@ -137,4 +137,6 @@ server.servlet.session.cookie.secure=true FRONT_END_URI=https://cs25.co.kr ## JSESSIONID Secure - ?? #server.servlet.session.cookie.secure=true -#FRONT_END_URI=http://localhost:5173 \ No newline at end of file +#FRONT_END_URI=http://localhost:5173 +#AES SECRET KEY +aes.secret.key="123456789123456" \ No newline at end of file From ffcc1486b9c967aec828011bb110b1e03f42a8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=83=88=EB=A1=AC?= Date: Fri, 26 Sep 2025 14:21:13 +0900 Subject: [PATCH 2/3] =?UTF-8?q?test:=20=EB=A1=9C=EC=BB=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9A=A9=20api=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=A0=20aes=20=EB=8C=80=EC=B9=AD=20?= =?UTF-8?q?=ED=82=A4=EA=B0=92=EB=8F=84=20=EC=9E=84=EC=8B=9C=EB=A1=9C=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20(=EB=82=98=EC=A4=91=EC=97=90=20.env?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EC=97=90=20=EB=93=B1=EB=A1=9D=20=ED=95=84?= =?UTF-8?q?=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quiz/controller/QuizTestController.java | 16 ++++++++++++++++ .../src/main/resources/application.properties | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java index 570d216c..8e6fbb44 100644 --- a/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java +++ b/cs25-service/src/main/java/com/example/cs25service/domain/quiz/controller/QuizTestController.java @@ -1,9 +1,13 @@ package com.example.cs25service.domain.quiz.controller; import com.example.cs25common.global.dto.ApiResponse; +import com.example.cs25service.domain.quiz.dto.TodayQuizResponseDto; import com.example.cs25service.domain.quiz.service.QuizAccuracyCalculateService; +import com.example.cs25service.domain.quiz.service.QuizPageService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -11,6 +15,7 @@ public class QuizTestController { private final QuizAccuracyCalculateService accuracyService; + private final QuizPageService quizPageService; @GetMapping("/accuracyTest") public ApiResponse accuracyTest() { @@ -27,6 +32,17 @@ public ApiResponse accuracyTest() { // return new ApiResponse<>(200); // } +// @GetMapping("/test/todayQuiz") +// public ApiResponse showTodayQuizPage( +// @RequestParam("quizId") String quizId +// ) { +// +// return new ApiResponse<>( +// 200, +// quizPageService.showTodayQuizPage(quizId) +// ); +// } + // @GetMapping("/test/sse") // public void testSse(HttpServletResponse response) throws IOException { // response.setContentType("text/event-stream"); diff --git a/cs25-service/src/main/resources/application.properties b/cs25-service/src/main/resources/application.properties index 95d3c42d..845fb29f 100644 --- a/cs25-service/src/main/resources/application.properties +++ b/cs25-service/src/main/resources/application.properties @@ -139,4 +139,4 @@ FRONT_END_URI=https://cs25.co.kr #server.servlet.session.cookie.secure=true #FRONT_END_URI=http://localhost:5173 #AES SECRET KEY -aes.secret.key="123456789123456" \ No newline at end of file +aes.secret.key=1234567890123456 \ No newline at end of file From e697bc1380b4807a580bb27a14f1bb9d51e36eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=EC=83=88=EB=A1=AC?= Date: Fri, 26 Sep 2025 15:29:59 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20api=20key=20.env=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99(1234567890123456)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cs25-service/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cs25-service/src/main/resources/application.properties b/cs25-service/src/main/resources/application.properties index 845fb29f..12d8568c 100644 --- a/cs25-service/src/main/resources/application.properties +++ b/cs25-service/src/main/resources/application.properties @@ -139,4 +139,4 @@ FRONT_END_URI=https://cs25.co.kr #server.servlet.session.cookie.secure=true #FRONT_END_URI=http://localhost:5173 #AES SECRET KEY -aes.secret.key=1234567890123456 \ No newline at end of file +aes.secret.key=${AES_KEY} \ No newline at end of file