import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Example {
public static void main(String[] args) {
String input = "hello";
String md5Hash = getMD5Hash(input);
System.out.println("MD5 Hash: " + md5Hash);
}
public static String getMD5Hash(String input) {
try {
// MessageDigest 객체 생성
MessageDigest md = MessageDigest.getInstance("MD5");
// 입력 문자열을 바이트 배열로 변환 후 해시 계산
byte[] hashBytes = md.digest(input.getBytes());
// 바이트 배열을 16진수 문자열로 변환
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
// 0xff로 마스킹 후 16진수로 변환
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0'); // 한 자리일 경우 앞에 0 추가
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MD5 알고리즘이 존재하지 않습니다.", e);
}
}
}
Padding
Initialization
Block Processing
Main Loop
A = B + ((A+F(B,C,D) + M[k] +T[i]) <<< s)
| Round | F(B,C,D) |
|---|---|
| 1 | `(B & C) |
| 2 | `(B & D) |
| 3 | B ^ C ^ D |
| 4 | `C ^ B |
Result Add
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
public class SHA1Example {
public static String toHexString(byte[] hash) {
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
// 각 바이트를 두 자리의 16진수로 변환
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0'); // 한 자리면 앞에 0 붙임
hexString.append(hex);
}
return hexString.toString();
}
public static String sha1Hash(String input) {
try {
// SHA-1 해시 인스턴스 생성
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] hashBytes = md.digest(input.getBytes());
return toHexString(hashBytes);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e); // 예외 던지기
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("입력할 문자열: ");
String input = scanner.nextLine();
String hash = sha1Hash(input);
System.out.println("SHA-1 해시값: " + hash);
scanner.close();
}
}
Padding
Initialize Hash Value
Block Processing
Main Loop
TEMP = (A <<< 5) + f(i,B,C,D) + E + W[i] + K[i]
E = D
D = C
C = B <<< 30
B = A
A = TEMP
| i 범위 | f(B,C,D) | K[i] 값 |
|---|---|---|
| 0 ≤ i ≤ 19 | B & D | (~B) & D |
| 20 ≤ i ≤ 39 | B ^ C ^ D | 0x6ED9EBA1 |
| 40 ≤ i ≤ 59 | B & C | B & D |
| 60 ≤ i ≤ 79 | B ^ C ^ D | 0XCA62C1D6 |
Hash Value Update
H0 = H0 + A
H1 = H1 + B
H2 = H2 + C
H3 = H3 + D
H4 = H4 + E
Hash Value Return
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
public class SHA256Example {
public static String toHexString(byte[] hash) {
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
public static String sha256Hash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256"); //SHA-512
byte[] hashBytes = md.digest(input.getBytes());
return toHexString(hashBytes);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("입력할 문자열: ");
String input = scanner.nextLine();
String hash = sha256Hash(input);
System.out.println("SHA-256 해시값: " + hash);
scanner.close();
}
}
| 이름 | 출력 크기 | block 크기 | 연산 bit |
|---|---|---|---|
| SHA-224 | 224bit | 512bit | 32bit |
| SHA-226 | 256bit | 512bit | 32bit |
| SHA-384 | 384bit | 1024bit | 64bit |
| SHA-512 | 512bit | 1024bit | 64bit |
| SHA-512/224 | 224bit | 1024bit | 64bit |
| SHA-512/256 | 256bit | 1024bit | 64bit |
Padding & Parsing
Inital Hash Values
메시지 스케줄 배열 W 생성
Wₜ = σ₁(Wₜ₋₂) + Wₜ₋₇ + σ₀(Wₜ₋₁₅) + Wₜ₋₁₆σ₀, σ₁ : bit 회전, shift 조합 함수Main Compress Loop
T1 = h + Σ₁(e) + Ch(e, f, g) + K[t] + W[t];
T2 = Σ₀(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
Σ₀, Σ₁ : bit 회전 함수 조합Hash Value Return
import com.password4j.*;
public class Argon2HashingExample {
public static void main(String[] args) {
String password = "mySecretPassword";
// Argon2 파라미터 설정
Argon2Function argon2 = Argon2Function.getInstance(
16 * 1024, // memory cost in KB (예: 16MB)
3, // iterations (time cost)
1, // parallelism (number of threads)
Argon2.ID, // Argon2 type (ID가 일반적인 추천값)
32, // hash length
64 // salt length
);
// 비밀번호 해싱
Hash hash = Password.hash(password)
.addRandomSalt()
.with(argon2);
System.out.println("Hash: " + hash.getResult());
System.out.println("Salt: " + hash.getSalt());
System.out.println("Algorithm: " + hash.getAlgorithm());
// 해시 검증
boolean verified = Password.check(password, hash.getResult())
.addSalt(hash.getSalt())
.with(argon2);
System.out.println("비밀번호 일치 여부: " + verified);
}
}
| Version | 용도 | 특징 |
|---|---|---|
| Argon2d | 암호화 키 생성 등 | GPU 공격에 강함 |
| 메모리 접근 패턴이 데이터 의존적 | ||
| Argon2i | 비밀번호 저장 | 메모리 접근이 랜덤 → 사이드 채널 공격 방어 |
| Argon2id | 다목적 | d와 i의 하이브리드 |
| i→d로 변화 ⇒ 균형잡힌 보안 |
Parameters (Hash 강도 설정)
| password | Message |
|---|---|
| salt | 무작위 문자열 |
| timeCost | 연산 반복 횟수 |
| memoryCost | 사용할 메모리 크기 (KB 단위) |
| parallelism | 병렬 처리 Thread 개수 |
| outputLength | 출력 hash 길이 |
| type | Argon2i, Argon2d, Argon2id |
Initialize Hash Value
H0 = Hash(password, salt, timeCost, memoryCost, parallelism, ...)
Memory Block 구조 생성
Fill Memory
Block[0] = Hash(H0 || 0)
Block[1] = Hash(H0 || 1)
Block[i] = G(Block[i-1], Block[ref])
// G() : Block *2 -> Block (BLAKE2 기반)
// 1. B' = BlockA XOR BlockB
// 2. B'' = BLAKE2-like compression on B'
// 3. Output Block = B''
Return Hash Value