0.
로그인 시에 암/복호화를 처음으로 적용해보았다.
1. 프로세스
1) 암복호화 키 생성: byte[] 키 생성
2) 암호화(AES256) - password
(1) byte[] 키를 MD5해시 -> 키값의 명세 객체 생성 (AES256) && AlgorithmParameterSpec 객체 생성
(2) Cipher를 이용해 암호화 진행
3) RequestUser 로 서버와 통신
생각보다 간단하다!
2. 코드
1) 암복호화 키 생성: byte[] 키 생성
- 나의 경우에는 "서버와 약속한 키"에 "timeStamp"를 조합해 암복호화 키를 생성했다.
public void init(String timeStamp) throws UnsupportedEncodingException {
this.timeStamp = timeStamp;
StringBuilder seedKeyBuilder = new StringBuilder("서버와 약속 한 키");
seedKeyBuilder.append(timeStamp);
seedKey = seedKeyBuilder.toString().getBytes("UTF-8");
}
2) 암호화(AES256) - password
public String encrypt(String originPassword) throws Exception {
AES256 aes256 = new AES256(seedKey); //(1)키를 이용해 AES256 관련 객체 초기화
byte[] encPassword = aes256.encrypt(originPassword.getBytes("UTF-8")); //(2) 암호화
return encodeToString(encPassword);
}
AES256 객체를 자세히 살펴보자!
AES256.java
import java.nio.ByteBuffer;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES256 {
private static final String KEY_SPEC = "AES"; //암호화 방식
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";//암호화방식/??/패딩방식
private Key mKey; //암호화키
private AlgorithmParameterSpec mAlgorithmParameterSpec; //알고리즘스펙
//1. AES 객체 생성
public AES256(byte[]... seeds) {
//(1) 키를 MD5방식으로 해시한다.
byte[] key = KeyGenerator.generateKey(seeds);
//(2) 키값의 명세 객체 생성 (AES256)
this.mKey = new SecretKeySpec(key, KEY_SPEC);
//(3) AlgorithmParameterSpec 객체 생성
this.mAlgorithmParameterSpec = new IvParameterSpec(key);
}
//2. 암호화
public byte[] encrypt(byte[] plainData) throws Exception {
if (mKey != null && mAlgorithmParameterSpec != null) {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, mKey, mAlgorithmParameterSpec);
return cipher.doFinal(plainData);
}
return null;
}
//3. 복호화
public byte[] decrypt(byte[] encData) throws Exception {
if (mKey != null && mAlgorithmParameterSpec != null) {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, mKey, mAlgorithmParameterSpec);
return cipher.doFinal(encData);
}
return null;
}
public void destroy() {
mKey = null;
mAlgorithmParameterSpec = null;
}
private static class KeyGenerator {
public static byte[] generateKey(byte[]... seeds) {
ByteBuffer byteBuffer = toByteBuffer(seeds);
byte[] key = getMD5Hash(byteBuffer.array());
clearByteBuffer(byteBuffer);
return key;
}
private static byte[] getMD5Hash(byte[] input) {
byte[] result = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
result = md.digest(input);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
private static ByteBuffer toByteBuffer(byte[]... bytesArray) {
int capacity = 0;
for (byte[] bytes : bytesArray) {
capacity += bytes.length;
}
ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
for (byte[] bytes : bytesArray) {
byteBuffer.put(bytes);
}
return byteBuffer;
}
private static void clearByteBuffer(ByteBuffer byteBuffer) {
Arrays.fill(byteBuffer.array(), (byte) 0);
byteBuffer.clear();
}
}
/*
* AES256 암호화/base64 암호화
*/
public static String encryptBase64(byte [] key, String data) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,
BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
Key secureKey = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secureKey, ivParameterSpec);
return Base64.encodeBase64String(cipher.doFinal(data.getBytes("UTF-8")));
}
/*
* base64 복호화/AES256 복호화
*/
public static String decryptBase64(byte [] key, String data) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,
BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
Key secureKey = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secureKey, ivParameterSpec);
return new String(cipher.doFinal(Base64.decodeBase64(data)));
}
반응형
'Language > JAVA' 카테고리의 다른 글
[java.lang.annotation] (0) | 2020.07.09 |
---|---|
[SimpleDateFormat] 날짜 유효성 체크 (0) | 2020.06.24 |
[javadoc] javadoc 만들기 (0) | 2020.06.10 |
[Hex] byteArrayToHexString(byte[] bytes) (0) | 2020.06.02 |
Java Garbage Collection (0) | 2019.09.11 |