Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix] AES256Util iv, key application.yml 값으로 변경 및 salt 추가 #254

Merged
merged 9 commits into from
Aug 14, 2023
59 changes: 51 additions & 8 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ on:
push:
branches:
- main
- test
pull_request:
branches:
- main
- test

workflow_dispatch:
inputs:
Expand All @@ -20,6 +22,7 @@ on:

env:
S3_BUCKET_NAME: wingle-ci-bucket
TEST_S3_BUCKET_NAME: wingle-test-ci-bucket
CODE_DEPLOY_APPLICATION_NAME: wingle-codedeploy-app
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: wingle-codedeploy-group

Expand All @@ -46,13 +49,24 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-

- name: make main application.yml
- name: 🚀 PROD - make main application.yml
if: github.ref == 'refs/heads/main'
run: |
sudo mkdir -p ./wingle/src/main/resources
sudo chmod 777 ./wingle/src/main/resources
cd ./wingle/src/main/resources
touch ./application.yml
echo "${{ secrets.MAIN_YML }}" > ./application.yml

- name: 👀 TEST - make stage application.yml
if: github.ref == 'refs/heads/test'
run: |
sudo mkdir -p ./wingle/src/main/resources
sudo chmod 777 ./wingle/src/main/resources
cd ./wingle/src/main/resources
touch ./application.yml
echo "${{ secrets.STAGE_YML }}" > ./application.yml

# 파일 없으면 빌드 에러
- uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -104,20 +118,20 @@ jobs:
shell: bash

- name: Make zip file
if: contains(github.ref, 'main')
# if: contains(github.ref, 'main')
run: zip -r ./$GITHUB_SHA.zip .
shell: bash

- name: Configure AWS credentials
if: contains(github.ref, 'main')
- name: 🚀 PROD - Configure AWS credentials
if: github.ref == 'refs/heads/main'
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Upload to AWS S3
if: contains(github.ref, 'main')
- name: 🚀 PROD - Upload to AWS S3
if: github.ref == 'refs/heads/main'
run: |
cd ./wingle
aws deploy push \
Expand All @@ -127,11 +141,40 @@ jobs:
--source .

# S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: Deploy to AWS EC2 from S3
if: contains(github.ref, 'main')
- name: 🚀 PROD - Deploy to AWS EC2 from S3
if: github.ref == 'refs/heads/main'
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip


- name: 👀 TEST - Configure AWS credentials
if: github.ref == 'refs/heads/test'
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.TEST_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: 👀 TEST - Upload to AWS S3
if: github.ref == 'refs/heads/test'
run: |
cd ./wingle
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$TEST_S3_BUCKET_NAME/build/$GITHUB_SHA.zip \
--source .

# S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: 👀 TEST - Deploy to AWS EC2 from S3
if: github.ref == 'refs/heads/test'
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$TEST_S3_BUCKET_NAME,key=build/$GITHUB_SHA.zip,bundleType=zip
130 changes: 97 additions & 33 deletions wingle/src/main/java/kr/co/wingle/common/util/AES256Util.java
Original file line number Diff line number Diff line change
@@ -1,64 +1,128 @@
package kr.co.wingle.common.util;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import kr.co.wingle.common.constants.ErrorCode;
import kr.co.wingle.common.exception.InternalServerErrorException;

@Component
public class AES256Util {
//initial vector 설정
private static String iv = "0000000000000001";
private static Key keySpec;

public AES256Util() throws UnsupportedEncodingException {
iv = iv.substring(0, 16);
byte[] keyBytes = new byte[16];
byte[] b = iv.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length) {
len = keyBytes.length;
}
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec _keySpec = new SecretKeySpec(keyBytes, "AES");
keySpec = _keySpec;

private static String KEY;
private static byte[] SALT;
private static String IV;

@Value("${aes256.key}")
public void setKEY(String KEY) {
AES256Util.KEY = KEY;
}

@Value("${aes256.salt}")
public void setSALT(String SALT) throws DecoderException {
AES256Util.SALT = Hex.decodeHex(SALT.toCharArray());
}

@Value("${aes256.iv}")
public void setIV(String IV) {
AES256Util.IV = IV;
}

//암호화
public static String encrypt(String str) {
try {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec((iv.getBytes())));
byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
// String enStr = new String(Base64.encodeBase64(encrypted));
return new java.math.BigInteger(encrypted).toString(16);
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
SecretKey key = generateKey(KEY);
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8"));
return encodeHex(encrypted);
} catch (Exception e) {
throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL);
}
}

public static String encrypt(String str, String salt) {
try {
SecretKey key = generateKey(KEY, salt);
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, IV, str.getBytes("UTF-8"));
return encodeHex(encrypted);
} catch (Exception e) {
throw new InternalServerErrorException(ErrorCode.ENCRYPT_FAIL);
}
}

//복호화
public static String decrypt(String str) {
try {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));
// byte[] byteStr = Base64.decodeBase64(str.getBytes());
byte[] byteStr = new java.math.BigInteger(str, 16).toByteArray();
return new String(c.doFinal(byteStr), "UTF-8");
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
SecretKey key = generateKey(KEY);
byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL);
}
}

public static String decrypt(String str, String salt) {
try {
SecretKey key = generateKey(KEY, salt);
byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, IV, decodeBase64(str));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
throw new InternalServerErrorException(ErrorCode.DECRYPT_FAIL);
}
}

public static Long userIdDecrypt(String userId) {
return Long.parseLong(decrypt(userId));
}

private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(encryptMode, key, new IvParameterSpec(decodeHex(iv)));
return cipher.doFinal(bytes);
}

private static SecretKey generateKey(String passPhrase) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

// generate key with salt
PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, 3000, 256);
SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES");

return key;
}

private static SecretKey generateKey(String passPhrase, String salt) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

// generate custom salt
PBEKeySpec saltSpec = new PBEKeySpec(salt.toCharArray(), SALT, 3000, 128);
SecretKey saltKey = new SecretKeySpec(factory.generateSecret(saltSpec).getEncoded(), "AES");

// generate key with custom salt
PBEKeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), saltKey.toString().getBytes(), 3000, 256);
SecretKey key = new SecretKeySpec(factory.generateSecret(keySpec).getEncoded(), "AES");

return key;
}

private static String encodeHex(byte[] bytes) {
return Hex.encodeHexString(bytes);
}

private static byte[] decodeHex(String str) throws Exception {
return Hex.decodeHex(str.toCharArray());
}

private static byte[] decodeBase64(String str) {
byte[] decodeByte = Base64.decodeBase64(str);
return Base64.decodeBase64(decodeByte);
}

}