Spring/초기 setting

9) 비밀번호 암/복호화(Encrypt/Decrypt) 설정

쿠카이든 2023. 4. 20. 12:37
728x90

아래 내용은 https://github.com/beaver84/setting-test 에서 실제 소스를 확인할 수 있습니다.

  • 비밀번호를 암호화할 때, RSA → Base64 인코딩 알고리즘을 사용한다(복호화는 반대).
    private final AuthEncrypter authEncrypter;

    @Transactional
    public Member login(LoginFormDto loginForm, HttpServletRequest request, HttpServletResponse response) {
        ...

        //클라이언트에서 온 암호를 복호화하여 DB에 저장된 암호를 복호화 한것과 비교한다.
        if (StringUtils.equals(authEncrypter.decrypt(member.getPassword()), authEncrypter.decrypt(loginForm.getPassword()))) {

 

  • 실제 암/복호화가 이루어 지는 곳
@Component
public class AuthEncrypter {

	private Logger log = LogManager.getLogger(this.getClass());

    private AuthEncryptKeyFactory keyFactory;

    @Autowired
    @Qualifier("authEncryptKeyFactory")
    private void setKeyFactory(AuthEncryptKeyFactory encryptKeyFactory) {
        this.keyFactory = encryptKeyFactory;
    }

    public String encrypt(String targetString) {
        String encryptString = "";
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keyFactory.getPublicKey());
            byte[] encrypted = cipher.doFinal(targetString.getBytes(StandardCharsets.UTF_8));
            encryptString = Base64.getEncoder().encodeToString(encrypted);

        } catch (Exception e) {
        	log.error("Tartget String -> {}", targetString);
        	log.error("암호화중 오류가 발생했습니다 : {}", e.getMessage());
            throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR, "암호화중 오류가 발생하였습니다.");
        }

        return encryptString;
    }

    public String decrypt(String targetString) {
        String decryptString = "";
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, keyFactory.getPrivateKey());
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(targetString));
            decryptString = new String(decrypted, StandardCharsets.UTF_8);

        } catch (Exception e) {
        	log.error("Tartget String -> {}", targetString);
        	log.error("암호화중 오류가 발생했습니다 : {}", e.getMessage());
            throw new ApiException(HttpStatus.INTERNAL_SERVER_ERROR, "복호화중 오류가 발생하였습니다.");
        }

        return decryptString;
    }
}
728x90
  • AuthEncryptKeyFactory - RSA 알고리즘은 공개키 비밀키가 필요한데, 이 키들은 이곳에서 얻어온다.
@Component
public class AuthEncryptKeyFactory {

	private Logger log = LogManager.getLogger(this.getClass());

    @Value("${test.pubkey}")
    private String rawPublicKey;

    @Value("${test.prikey}")
    private String rawPrivateKey;

    private PublicKey publicKey;
    private PrivateKey privateKey;

    @Autowired
    private void loadPublicKey() {
        try {
            byte[] publicKeyDER = Base64.getDecoder().decode(rawPublicKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));
        } catch (Exception e) {
        	log.error("암호화키 생성 중에 오류가 발생했습니다 : {}", e.getMessage());
            publicKey = null;
        }
    }

    @Autowired
    private void loadPrivateKey() {
        try {
            byte[] privateKeyDER = Base64.getDecoder().decode(rawPrivateKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));
        } catch (Exception e) {
        	log.error("암호화키 생성 중에 오류가 발생했습니다 : {}", e.getMessage());
            publicKey = null;
        }
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public PrivateKey getPrivateKey() {
        return privateKey;
    }

}

 

  • Test 코드
import com.example.settingtest.config.security.AuthEncrypter;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class AuthEncrypterTest {
    private final AuthEncrypter authEncrypter;
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthEncrypterTest.class);

    @Autowired
    public AuthEncrypterTest(AuthEncrypter authEncrypter) {
        this.authEncrypter = authEncrypter;
    }

    @Test
    void encrypt() {
        LOGGER.debug("{}",authEncrypter.encrypt("abc"));
    }

    @Test
    void decrypt() {
        LOGGER.debug("{}", authEncrypter.decrypt("QvsAejnixKcQnxsehM888KKyUcuAFaXJI/FpunPCPCs7fNvVUOXTv34DcCZFS3jHeTi4LjiHc4qW6FH2bnpvSjMhLtBDfZN3d17PFsOWvlPiggUsOa5iBQCb5FfmreJ+uzqG/IvKoO3MA2Lds/CIBuztsmDw//iKPSkG4k+zJVs="));
    }
}

 

  • 실행 결과(암호화)

 

  • 실행 결과(복호화)

 

728x90

'Spring > 초기 setting' 카테고리의 다른 글

11) Logback 설정  (0) 2023.04.20
10) Spring Data Redis 셋팅  (0) 2023.04.20
8) API Response(@ControllerAdvice) 설정  (0) 2023.04.20
mapStruct 소개 및 활용  (0) 2023.04.10
6) 스프링 시큐리티(spring-security) 적용  (0) 2023.04.05