commit 2cdce77f4de5f36a48f0dfd0d560b8d131da8a1c Author: BIOCaT Date: Tue Oct 14 11:27:09 2025 +0900 최초등록 diff --git a/java/.vscode/settings.json b/java/.vscode/settings.json new file mode 100644 index 0000000..e112a70 --- /dev/null +++ b/java/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "java.project.sourcePaths": ["src"], + "java.project.outputPath": "bin", + "java.project.referencedLibraries": [ + "lib/**/*.jar" + ] +} diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000..7c03a53 --- /dev/null +++ b/java/README.md @@ -0,0 +1,18 @@ +## Getting Started + +Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code. + +## Folder Structure + +The workspace contains two folders by default, where: + +- `src`: the folder to maintain sources +- `lib`: the folder to maintain dependencies + +Meanwhile, the compiled output files will be generated in the `bin` folder by default. + +> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there. + +## Dependency Management + +The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies). diff --git a/java/src/Encryypt.java b/java/src/Encryypt.java new file mode 100644 index 0000000..6da21c8 --- /dev/null +++ b/java/src/Encryypt.java @@ -0,0 +1,151 @@ +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;���a.�%�;�D���k-�N�-��<�K~�� + * + * 비밀번호는 단방향 암호화 알고리즘인 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; + } + + 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("----------------------------------------------"); + + } +} \ No newline at end of file