반응형
서론
https 를 사용함에도 반드시 암호화 해달라는 고객의 요청으로 처리하면서
클라이언트- 서버 통신에서 비밀번호 평문을 막기위해 사용하였다.
회원가입 / 비밀번호 변경 / 비밀번호 인증 등에서 사용하고 있다.
당연하겠지만, DB 저장용이 아닌 구간 암호화용으로만 써야한다.
DB 암호화용은 SHA 와 같은 단방향 해싱 암호화를 하자.
자바 암-복호화
클라이언트가 JS를 사용하는 경우 CryptJS를 사용하고
서버가 Java 인 경우는 아래 코드를 활용하면 된다.
다만, salt 와 iv 는 동적으로 변경해야 더 안전하다.
해싱 암호화 횟수를 늘리면 늘릴 수록 안전하다만, 횟수에 비례해 암호화 속도가 느려지는 단점이있다.
자바는 아래와 같이 암호화하면 된다.
Base64 인-디코딩을 위해 apache common 라이브러리가 필요하다.
import java.security.spec.KeySpec;
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.binary.Base64;
import org.apache.commons.codec.binary.Hex;
public class AesCryptUtil {
public static final String ENC_KEY = "e534cf179007db7e6360ebf95fa5d51c";
public static final String salt = "deafa8b6802cebcc0bcceaaa5f3461a9";
public static final String iv = "e9d3712c4d5c35093d340733b8c26b92";
public static String decrypt(String data) {
try {
return decrypt(salt, iv, ENC_KEY, data, 1000, 128);
} catch(Exception e) {
return "";
}
}
private static String decrypt(String salt, String iv, String passphrase, String ciphertext, int iterationCount, int keySize) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), Hex.decodeHex(salt.toCharArray()), iterationCount, keySize);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(Hex.decodeHex(iv.toCharArray())));
byte[] decrypted = cipher.doFinal(Base64.decodeBase64(ciphertext));
return new String(decrypted, "UTF-8");
}
public static String encrypt(String data) {
try {
return encrypt(salt, iv, ENC_KEY, data, 1000, 128);
} catch(Exception e) {
return "";
}
}
private static String encrypt(String salt, String iv, String passphrase, String ciphertext, int iterationCount, int keySize) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), Hex.decodeHex(salt.toCharArray()), iterationCount, keySize);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(Hex.decodeHex(iv.toCharArray())));
byte[] encrypted = cipher.doFinal(ciphertext.getBytes("UTF-8"));
return new String(Base64.encodeBase64(encrypted));
}
public static void main(String[] args) {
String enc = encrypt("test001");
System.out.println(enc);
System.out.println(decrypt(enc));
}
}
JavaScript 암호화
다운로드
- node js 나 React와 같이 npm을 사용할 수 있는 환경이라면 아래링크를 확인
- https://www.npmjs.com/package/crypto-js
- 바닐라 JavaScript를 사용중이라면 아래링크를 확인
- https://code.google.com/archive/p/crypto-js/downloads
- 사용할 JS 는 Crypto-js 와 Crypto-js AES 이다.
코드
var iv = 'e9d3712c4d5c35093d340733b8c26b92';
var salt = 'deafa8b6802cebcc0bcceaaa5f3461a9';
var passPhrase = 'e534cf179007db7e6360ebf95fa5d51c';
var keySize = 128;
var iterationCount = 1000;
var key128Bits = CryptoJS.PBKDF2(passPhrase,
CryptoJS.enc.Hex.parse(salt),
{ keySize: keySize / 32, iterations: iterationCount }
);
iv 와 salt 는 새로 hashing 해서 만들기를 권장한다.
JavaScript 변수명 또한 읽었을 때 이해가 안되도록 전혀 엉뚱한 변수명으로 하는 것도 좋다.
반응형
'Java & Spring > 도움이 되는' 카테고리의 다른 글
자바로 랜덤 문자열 가져오기 / 랜덤 휴대폰번호 가져오기 / 랜덤 알파벳 가져오기 / 랜덤 이름 / 랜덤 생년월일 만들기 (0) | 2021.03.29 |
---|---|
2019년 6월 이클립스 개발필수 Plug-in (0) | 2019.07.02 |
[JAVA] PDF 만들기, 라이브러리 Apache PDFBox 사용예제 (0) | 2019.05.19 |
마크다운 Markdown 렌더링Rendering / 컨버터Converter 라이브러리 추천 (0) | 2019.02.14 |
네티 관련 좋은 git URL (0) | 2018.04.11 |
WRITTEN BY
,