Files
BIOCaT/java/src/Encryypt.java
2025-10-14 12:39:32 +09:00

158 lines
7.0 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryypt {
/*
* Getnerate key
* ASE128 방식으로 secret key 발급
* - generateKey 메서드에 algorithm에는 암호화의 방식, keySize는 키의 크기가 들어간다.
* - algorithm은 AES, keySize는 128로 한다.
* - javax.crypto의 KeyGenerator를 사용해 알고리즘 종류와 키의 크기로 초기화 해준다.
* - KeyGenerator의 generateKey()를 이용해 키를 생성한 후 getEncoded()로 키를 반환한다.
*/
public static byte[] generateKey(String algorithm, int keySize) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
keyGenerator.init(keySize);
SecretKey key = keyGenerator.generateKey();
return key.getEncoded();
}
/**     
* hex to byte[] : 16진수 문자열을 바이트 배열로 변환한다.     
*
*/
public static byte[] hexToByteArray(String hex) {
if (hex == null || hex.length() == 0) {
return null;
}
byte[] ba = new byte[hex.length() / 2];
for (int i = 0; i < ba.length; i++) {
ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return ba;
}
/*
* generateKey()메서드에서 얻어진 byte 배열을 16진수의 문자열로 변환
*/
public static String byteArrayToHex(byte[] ba) {
if (ba == null || ba.length == 0) {
return null;
}
StringBuffer sb = new StringBuffer(ba.length * 2);
String hexNumber;
for (int x = 0; x < ba.length; x++) {
hexNumber = "0" + Integer.toHexString(0xff & ba[x]);
sb.append(hexNumber.substring(hexNumber.length() - 2));
}
return sb.toString();
}
/*
* 사용자 이름 암호화
* - 평문: lee
* - encrypt: 91f0742622d1defa32ca78f399cd62e7
*
* 데이터베이스에 저장되는 사용자의 정보는 마스킹한 후 저장되어야 한다.
* 키를 사용해 암호화와 복호화가 가능한 Cipher 클래스를 사용해 인스턴스를 생성하고,
* Cipher mode, secret key, 복호화에 사용할 키를 넣어 초기화해 준다.
* 초기화한 Cipher에 평문을 byte로 넣어 암호화 한 후 16진수로 변환해 반환한다.
* 반환된 16진수 문자열은 데이터베이스에 저장된다.
*/
public static String aesEncrypt(String msg, byte[] key) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String iv = "AAAAAAAAAAAAAAAA";
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv.getBytes()));
byte[] encrypted = cipher.doFinal(msg.getBytes());
return byteArrayToHex(encrypted);
}
/*
* 사용자 정보 복호화 하기 (마스킹되어 저장된 사용자 이름을 복호화)
*
* 데이터베이스에 있는 사용자 정보를 복호화 하기 위해서 암호화에 사용된
* secret key와 ivParameter가 필요하다.
* Cipher 초기화 부분에 mode 만 DECRYPT_MODE로 변경해 주면 된다.
* 암호화된 msg를 다시 byte 배열로 변환해 준 후 복호화를 진행한다.
* 복호화를 하게 되면 암호화 시 넣었던 평문이 반환된다.
*/
public static String aesDecrypt(String msg, byte[] key) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String iv = "AAAAAAAAAAAAAAAA";
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv.getBytes()));
byte[] encrypted = hexToByteArray(msg);
byte[] original = cipher.doFinal(encrypted);
return new String(original);
}
/*
* 사용자 비밀번호 암호화
* - 원문: 1234
* - SHA-256: 4b3bed8af7b7612e8c1e25f63ba24496f5b16b2df44efb2db7ce3cb24b7e96f7
* - pw encrypt: K;<3B><><EFBFBD>a.<2E>%<25>;<3B>D<EFBFBD><44><EFBFBD>k-<2D>N<EFBFBD>-<2D><><<3C>K~<7E><>
*
* 비밀번호는 단방향 암호화 알고리즘인 SHA256 방식으로 암호화 되어 저장된다.
* 복호화 가능한 키가 없는 해시 알고리즘이다.
* getSHA256메서드의 두 번째 인자인 salt는 위에서 security VO 모델에 저장한
* salt를 사용하게 된다.
* MessageDigest 클래스를 사용하여 인스턴스를 생성해 준다.
* 평문과 salt를 byte로 변환해 추가한다.
* 데이터베이스에 암호화된 byte 데이터가 저장된다.
*
* 암호화된 비밀번호는 어떻게 사용할까?
* - 데이터베이스에 사용자 비밀번호는 해시 함수를 사용하여 암호화 되어 있다.
* - 사용자가 정보를 변경하거나 어떤 동작에서 비밀번호를 입력하는 행위가 필요한 경우
* 사용자가 입력한 비밀번호를 동일한 방식으로 해시화 해서 데이터베이스에 저장된 값과 비교한다.
*/
public static byte[] getSHA256(String source, String salt) {
byte byteData[] = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(source.getBytes());
md.update(salt.getBytes());
byteData = md.digest();
System.out.println("원문: " + source + " SHA-256: " + byteData.length + "," + byteArrayToHex(byteData));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return byteData;
}
/**
*
* 개인정보 암호화 메인함수
* @param args
* @throws Exception
*
*/
public static void main(String[] args) throws Exception {
byte[] key = generateKey("AES", 128);
String hexKey = byteArrayToHex(key); //generateKey의 16진수 문자열로 변환
System.out.println("----------------------------------------------");
System.out.println("Key length : " + key.length);
System.out.println("hexKey : " + hexKey);
String useName = "Lee";
String aesEncryptStr = aesEncrypt(useName, key);
System.out.println("----------------------------------------------");
System.out.println("사용자명 평문 : " + useName);
System.out.println("----------------------------------------------");
System.out.println("사용자명 암호화 : " + aesEncryptStr);
String aesDecryptStr = aesDecrypt(aesEncryptStr, key);
System.out.println("사용자명 평문 : " + aesDecryptStr);
System.out.println("----------------------------------------------");
}
}