> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/dev-start/integrations/undefined-3.md).

# 데이터 암호화

다음은 CryptoUtil 데이터 암호화 정의입니다.

암호화의 경우 기존 프로젝트에 사용하던 AwsCrypto 패키지를 삭제하면서 AwsCryptoUtil Class 파일을 삭제하고, 스프링에서 기본적으로 제공하는 **BCrypt 해싱함수**와 **AES256 Encode, Decode** 모듈을 제공하는 CryptoUtil Class 파일로 대체 하였습니다.

***

## 의존성 주입(DI, Dependency Injection) 사용 방법

AES256에서 사용할 32자리 Secret Key를 application.yml 파일에 `crypto.secret.key`에 설정함.

설정 하지 않을 경우 내부적으로 `defaultSecretKey` 값으로 `X2BEE_Application_DATA_SecretKey`을 사용함. ⚠️ 운영 환경에서는 반드시 application.yml(또는 Jasypt·보안 설정)에서 crypto.secret.key 를 배포 환경별 고유한 32자 키로 재정의해야 합니다. 기본키를 그대로 사용하면 암호화된 데이터가 노출될 위험이 있습니다.

**application.yml 예시:**

```yaml
crypto:
  secret:
    key: X2BEE_Application_DATA_SecretKey
```

사용할 Class 파일에서 생성자를 통해 Bean을 주입한 후 `encodeBcrypt`, `matchesBcrypt`, `encodeAes`, `decodeAes` 4개의 함수를 사용함.

**CryptoUtilTest1.java**

{% code title="CryptoUtilTest1.java" %}

```java
package com.x2bee.api.display;

import com.x2bee.common.base.util.CryptoUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Assert;

@SpringBootTest
@AutoConfigureMockMvc
@Slf4j
class CryptoUtilTest1 {

    private CryptoUtil cryptoUtil;

    @Autowired
    public ApiTest(final CryptoUtil cryptoUtil) {
        Assert.notNull(cryptoUtil, "CryptoUtil can't be null");
        this.cryptoUtil = cryptoUtil;
    }

    @Test
    public void test1() throws Exception {
        log.info("------------------------------------- test1 START ----------------------------------------------------------");

        String value = cryptoUtil.encodeBcrypt("가나다");
        log.info(value);

        Boolean value2 = cryptoUtil.matchesBcrypt("가나다1", value);
        log.info("value2 : " + value2);

        Boolean value3 = cryptoUtil.matchesBcrypt("가나다", value);
        log.info("value3 : " + value3);

        String value4 = cryptoUtil.encodeAes("가나다");
        log.info(value4);

        String value5 = cryptoUtil.decodeAes(value4);
        log.info(value5);

        log.info("------------------------------------- test1 END ----------------------------------------------------------");
    }
}
```

{% endcode %}

***

## 싱글톤 패턴 사용 방법

싱글톤 인스턴스를 가져와서 위와 동일하게 함수 사용함.

**CryptoUtilTest2.java**

{% code title="CryptoUtilTest2.java" %}

```java
package com.x2bee.api.display;

import com.x2bee.common.base.util.CryptoUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@AutoConfigureMockMvc
@Slf4j
class CryptoUtilTest2 {

    @Test
    public void test1() throws Exception {
        log.info("------------------------------------- test1 START ----------------------------------------------------------");

        CryptoUtil.getInstance().setSecretKey("X2BEE_Application_DATA_SecretKey");

        String value = CryptoUtil.getInstance().encodeBcrypt("가나다");
        log.info(value);

        Boolean value2 = CryptoUtil.getInstance().matchesBcrypt("가나다1", value);
        log.info("value2 : " + value2);

        Boolean value3 = CryptoUtil.getInstance().matchesBcrypt("가나다", value);
        log.info("value3 : " + value3);

        String value4 = CryptoUtil.getInstance().encodeAes("가나다");
        log.info(value4);

        String value5 = CryptoUtil.getInstance().decodeAes(value4);
        log.info(value5);

        log.info("------------------------------------- test1 END ----------------------------------------------------------");
    }
}
```

{% endcode %}

***

## @Encrypt 커스텀 어노테이션 사용

`@Encrypt` 커스텀 어노테이션을 사용하여 MyBatis에서 저장 및 조회 시 자동으로 AES256 encode/decode 적용.

Common의 MyBatis AOP 모듈에서 `@Encrypt` 어노테이션이 있는 필드의 경우 저장 전에 `encodeAes` 함수를 실행하여 값을 encode하여 저장하고, 조회 시에는 DB 조회 후 `decodeAes` 함수를 실행하여 decode된 값을 모델에 설정함.

**TestLog.java**

{% code title="TestLog.java" %}

```java
package com.x2bee.api.display.app.dto.sample;

import com.x2bee.common.base.encrypt.Encrypt;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.ibatis.type.Alias;

@Alias("testLog")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class TestLog {
    private Integer seq;
    private String log;

    @Encrypt
    private String testValue;
}
```

{% endcode %}

***

## @Convert(converter = JpaEncryptor.class) 어노테이션 사용

`@Convert` 어노테이션은 JPA에서 제공하는 Convert 모듈로서, Convert 설정값에는 Common에 있는 `JpaEncryptor.class`를 설정함.

위 MyBatis AOP와 동일하게 JPA로 저장 및 조회 시 동일하게 자동으로 AES256 encode/decode 함수를 적용함.

**TestLogEntity.java**

{% code title="TestLogEntity.java" %}

```java
package com.x2bee.api.display.app.entity;

import com.x2bee.api.display.app.dto.sample.TestLog;
import com.x2bee.common.base.encrypt.JpaEncryptor;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

@Getter
@Setter
@Table(schema="public", name = "test_log")
@Entity
@NoArgsConstructor
@DynamicUpdate
public class TestLogEntity {

    @Id
    @Column(name = "seq", nullable = false)
    private Integer seq;

    @Column(name = "log", nullable = false)
    private String log;

    @Convert(converter = JpaEncryptor.class)
    @Column(name = "test_value", nullable = false)
    private String testValue;
}
```

{% endcode %}

***

## 사용 예시 (EncryptUtils)

다음은 EncryptUtils를 사용한 예시입니다.

**Sample.java**

{% code title="Sample usage" %}

```java
/* 암호화 Value */
EncryptUtils.getEncryptValue("Sample");
// 예상 결과값 : MW5NMo6yro63GMEalqAI0A==

/* 복호화 Value */
EncryptUtils.getDecryptValue("MW5NMo6yro63GMEalqAI0A==");
// 예상 결과값 : Sample
```

{% endcode %}
