MD5 암호화

2020. 12. 23. 14:322021/JOB DA STUDY

특정 데이터를 암호화 하여 DB에 보관해야하는 경우가 있다.

이때 암호화 및 파일 무결성 검사의 용도로 MD5와 SHA-256를 이용한다.

1. java.security.MessageDigest Class

이 클래스에는 MD5, SHA-1, SHA-256 등이 있다.

MessageDigest.getInstance(String 알고리즘)

-> 해당 알고리즘에서 해시값을 계산하는 MessageDigest를 구할 수 있다.

2. MD5(Massage -Diget 알고리즘 5

  • 메시지 축약 알고리즘으로 보안보다 어떤 공백, 점 하나만 들어와도 해시값이 달라져 파일 무결성이 위배 되었음을 찾는데 더 많이 이용
  • 128bit의 해쉬를 제공하며, 암호화/복호화를 통해 보안용으로도 많이 사용하지만 암호화 결함의 발견으로 보안의 용도로는 SHA와 같은 다른 알고리즘을 많이 이용
 private String getMD5HashString(String inputTxt) {

		String MD5 = "";

		try {
			MessageDigest md = MessageDigest.getInstance("MD5");  <- (1)
		
			md.update(inputTxt.getBytes()); <- (2)
			byte byteData[] = md.digest(); <- (3)
			StringBuffer sb = new StringBuffer(); <- (4)
			for (int i = 0; i < byteData.length; i++) {
				sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); <- (5)
			}
			MD5 = sb.toString(); <- (6)
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			MD5 = null;
		}

		return MD5;
	}

}
 

 

(1). MessageDigest md = MessageDigest.getInstance("MD5");

  • Singleton

자바 프로그램이 동작 할 때 최초의 한번만 메모리를 할당하고, 할당된 메모리에서만 사용하는 방식

고정된 메모리 영역을 사용함으로써 메모리의 낭비를 줄이고, 공통된 객체를 사용하는 경우에는 객체를 더 이상 새롭게 만들지 않아도 된다.

 

  • getInstance()

싱글톤패턴으로 단 한번만 인스턴스를 생성한 후에 그 객체로 계속 공유

(파라미터로 MD5, SHA-256, SHA512 등이 들어가면, 이에 대한 다이제스트 오브젝트 생성)

 

(2). md.update(inputTxt.getBytes));

  • .update

MessageDIgest 클래스의 update() 메소드는 호출 될 때마다 객체 내에 저장된 digest 값이 계속해서 갱신된다.

  • .getBytes

사람들이 알아 볼 수 있는 String 타입을 1 과 0으로 이루어진 Bytes타입으로 변환한다.

(보통은 DB가 한글을 지원하지 않는 경우 한글로 된 문자를 숫자로 인코딩하여 DB에 저장하기 위해 사용한다.)

 

(3). byte byteDate[] = md.digest();

  • .digest

바이트 배열로 해쉬를 반환하는데 padding등의 최종 처리로 해시 계산을 완료한다.

따라서 update한 값을 digest를 호출함으로써 가져올 수 있다.

 

(4). StringBuffer sb = new StringBuffer();

  • StringBuffer

StringBuffer는 문자열을 추가하거나 변경하는 경우에 주로 사용하는 자료형이다.

public class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("hello");
        sb.append(" ");
        sb.append("jump to java");
        System.out.println(sb.toString());
    }
}
public class Test {
    public static void main(String[] args) {
        String temp = "";
        temp += "hello";
        temp += " ";
        temp += "jump to java";
        System.out.println(temp);
    }
}
  • StringBuffer의 경우에는 객체가 단 한번만 생성되면 그뒤에 문자열은 계속 그 객체에 append된다. 하지만 String 자료형은 +연산이 있을때 마다 새로운 Stirng 객체가 생성된다.

->첫번째 예제의 경우에는 sb라는 객체 1개만 생성이 되지만, 두번째 예제의 경우에는 총 4개의 객체가 생성된다.

 

  • String 자료형은 한번 값을 생성하면 변경할 수 없다. (immutable)  trim, toUpperCase등의 메소드의 경우 문자열이 변경된것 처럼 보이지만, 이는 다른 String객체를 생성해 리턴한 것이다. 하지만 StringBuffer의 경우에는 값의 변경이 가능하다. (mutable) 

 

  • StringBuffer는 String 자료형보다 무거운 편이어서 new StringBuffer()를 생성하는 것은 일단 String을 사용하는 것 보다 메모리 사용량이 많고, 속도도 느리다. 따라서 문자열의 추가, 변경 등의 작업이 많은 경우에는 StringBuffer를 사용하며, 변경이 잦지 않은 경우에는 String을 이용한다.

(5). sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));

바이트 배열을 16진수(HEX) 문자열로 변환

  • (byteData[i] & 0xff) + 0x100

1. byteData[i] & 0xff

byte는 8bit의 공간을, int는 32bit의 공간을 차지하는데 비트연산자 &를 수행하는 경우 비트수가 낮은 byte가 비트수가 높은 int형에 맞춰 강제 형변환하게 된다. (byte: 8bit -> 32bit)

이때, byteDate[i]의 가장 앞의 비트가 0인 경우에는 0으로 채우지만, 1인 경우에는 비트 확장시 모든 비트를 1로 채운다.

1로 채우게 되면 원본의 값과는 완전 다른 값이 되기 때문에 이를 0을 바꾸어 주기 위해 "& 0xff" 연산을 수행한다.

(0xff: 00000000 00000000 00000000 11111111)

 

2. + 0x100

 

결론적으로는 이 연산을 하든지 하지 않든지 같은 값으로 나온다.

하지만 이를 하게 되면, Integer.toString(n, 15) 메소드의 결과값을 강제로 3자리로 만들어 준다.

10진수 16진수 16진수 ( +0x100 연산 NO) 16진수 ( +0x100 연산 OK)
1 1 1 101
2 2 2 102
3 3 3 103
4 4 4 104
5 5 5 105
10 a a 10a
11 b b 10b
12 c c 10c
16 10 10 110

 

  • ((byteData[i] & 0xff) + 0x100, 16).substring(1))

1. .substring(1)

3자리 중에서 1이 들어오는 맨 앞자리는 제거된 01, 02, 03, 04, 05, 0a, 0b, 0c, 10 2자리 수만 추출이 된다.

3. SHA(Secure Hash Standard)

  • 서로 관련된 암호학적 해시 함수들의 모임
  • SHA-1이 가장 많이 사용되며, TLS, SSL, PGP, SSH, IPSec 등 많은 보안 프로토콜과 프로그램에서 사용
  • MD5대신 SHA-1을 많이 사용하며, 좀 더 중요한 기술에는 SHA-256이나 그 이상의 알고리즘을 사용하는 것을 권장

'2021 > JOB DA STUDY' 카테고리의 다른 글

InputStream and OutputStream  (0) 2020.12.28
3주차 과제: 연산자  (0) 2020.12.27
Public과 Private  (0) 2020.12.22
Instanceof  (0) 2020.12.21
Argument 와 Parameter  (0) 2020.12.21