diff --git a/src/main/java/today/seasoning/seasoning/common/cipher/CipherProperties.java b/src/main/java/today/seasoning/seasoning/common/cipher/CipherProperties.java new file mode 100644 index 0000000..a9cc628 --- /dev/null +++ b/src/main/java/today/seasoning/seasoning/common/cipher/CipherProperties.java @@ -0,0 +1,18 @@ +package today.seasoning.seasoning.common.cipher; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "cipher") +public class CipherProperties { + + private String secretKey; + private String algorithm; + private String transformation; + private String iv; +} diff --git a/src/main/java/today/seasoning/seasoning/common/cipher/CipherUtil.java b/src/main/java/today/seasoning/seasoning/common/cipher/CipherUtil.java new file mode 100644 index 0000000..40bb04e --- /dev/null +++ b/src/main/java/today/seasoning/seasoning/common/cipher/CipherUtil.java @@ -0,0 +1,58 @@ +package today.seasoning.seasoning.common.cipher; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class CipherUtil { + + private final Cipher cipher; + private final SecretKeySpec secretKeySpec; + private final IvParameterSpec ivParameterSpec; + + @Autowired + public CipherUtil(CipherProperties properties) throws NoSuchPaddingException, NoSuchAlgorithmException { + this.secretKeySpec = new SecretKeySpec(properties.getSecretKey().getBytes(UTF_8), properties.getAlgorithm()); + this.ivParameterSpec = new IvParameterSpec(properties.getIv().getBytes()); + this.cipher = Cipher.getInstance(properties.getTransformation()); + } + + public String encode(String plainText) { + if (plainText == null) { + return null; + } + + try { + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] encrypted = cipher.doFinal(plainText.getBytes(UTF_8)); + return Base64.encodeBase64String(encrypted); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String decode(String encodedText) { + if (encodedText == null) { + return null; + } + + try { + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] decoded = cipher.doFinal(Base64.decodeBase64(encodedText)); + return new String(decoded, UTF_8); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/today/seasoning/seasoning/common/cipher/CryptoConverter.java b/src/main/java/today/seasoning/seasoning/common/cipher/CryptoConverter.java new file mode 100644 index 0000000..f28347a --- /dev/null +++ b/src/main/java/today/seasoning/seasoning/common/cipher/CryptoConverter.java @@ -0,0 +1,22 @@ +package today.seasoning.seasoning.common.cipher; + +import javax.persistence.AttributeConverter; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class CryptoConverter implements AttributeConverter { + + private final CipherUtil cipherUtil; + + @Override + public String convertToDatabaseColumn(String attribute) { + return cipherUtil.encode(attribute); + } + + @Override + public String convertToEntityAttribute(String dbData) { + return cipherUtil.decode(dbData); + } +}