달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2017. 2. 27. 18:15

이곳의 용도는... C#/Java 개발자를 위한 C#2017. 2. 27. 18:15

  업무에서는 2002년부터, 학교에서 공부했던 기간까지 치면 1997년부터 Java를 사용해 왔으니 벌써 20년이나 되었습니다.

물론 자바만 사용한 것은 아니지만 그래도 가장 메인 언어였기 때문에 Java에 대해서는 어느 정도 잘 알고 있다고 생각했고 사용하기도 편했는데 2015년에 회사 내부 사정으로 팀이 이동되면서 갑자기 MS Solution 기반, 특히나 C#을 주로 사용하는 쪽으로 가게 되었습니다.


  다들 자바나 C#이나 그게 그거니까 금방 하겠네, 그러는데 솔직히 전 그 말이 상당히 싫었습니다.

문법이 많이 비슷하긴 하지만 그것이 처음에 익숙해지는데는 도움이 될 망정 초보 단계를 넘어가면 오히려 Java에서의 익숙함 때문에 C처럼 Java를 짜거나(물론 둘다 OOP Language로서 그정도 까지는 안되겠지만) 비슷하지만 다른 점 때문에 오히려 고생할 수도 있을거라는 생각이 들었기 때문입니다.


  이제 벌써 C#을 써온지 1년 반 정도 되어가는 시점에 보니 역시나 예상대로 처음 접근은 익숙했지만 여러가지 비슷하면서도 다른 문법과 구조들 때문에 여러 삽질들이 있어왔습니다.

이 Section은 제목 그대로, 저처럼 Java 는 최소한 초중급 이상 할 줄 알지만 C#을 처음 하시는 분들을 대상으로 비슷하지만 다른 점들을 정리해서 저같은 분들이 헤매지 않았으면 하는 생각에서 정리하려고 합니다.


개구리 올챙이적 생각 못 한다고 벌써 많이들 까먹었지만 생각나는 대로 업데이트를 할 예정이며 아직 Java에 비해 C# 사용능력이 일천한지라 잘 못 적거나 불필요하게 돌아가는 방식으로 풀었을 수도 있으니 그런 부분들은 고수님들께서 지적해 주시면 고쳐놓도록 하겠습니다.

:
Posted by hanavy
2015. 4. 29. 23:03

Java에서 SHA 기반 해시암호화 Java2015. 4. 29. 23:03

  원래부터 중요하긴 하지만 요 몇 년새에 각종 보안사고(포털/금융기관 등에서의 개인정보 유출 등)가 많이 발생하면서 보안에 대해서 많이 깐깐해지고 있습니다.
그래도 외부에 공개되는 사이트의 경우는 좀 신경쓰고 있지만 내부 시스템의 경우는 비교적 최근까지 BASE64 기반 "인코딩"을 하고 나서 암호화라고 하는 곳도 봤고 심하면 아예 패스워드를 눈에 보이게 그대로 저장하는 케이스까지 있었습니다.


  그런데 이제는 구체적으로 암호화의 방법에 대해서 최소 256bit 이상으로 해야 하네, 패스워드는 복호화가 불가능하게 해시 암호화를 해야 하네 등등 가이드가 나오고 있습니다.  좋은 방향이죠...


  원래 암호화라는게 수학, 특히 정수론 등의 상당히 복잡한 이론에 기반한 내용이라 아무나 쉽게 접근할 수 없는 내용이지만 그래도 요즘에는 효율적인 암호화 알고리즘들이 라이브러리화되어 쉽게 사용할 수 있도록 제공되고 있어 내부적인 알고리즘까지는 알지 못하더라도 사용하기는 쉽게 제공되고 있습니다.


  이번에는 그 중에서 먼저 복호화가 불가능한 방식인 해시암호화, 그 중 대표적인 SHA 기반 암호화에 대해서 적어보려고 하는데 구체적인 내용까지는 모르더라도 해시암호화가 뭔지, 복호화가 가능한 암호화와 무엇이 다른지 등등 기본적인 내용은 알아야 상황에 따라서 잘 사용할 수 있겠죠..
암호화 알고리즘을 검토할 때 상당히 도움이 되었던 사이트가 있어서 소개드리니 기본적인 내용은 아시는 분들이라도 먼저 간단하게 내용을 한 번 보고 오기 바랍니다.  해시 암호화 위주의 설명이긴 하지만


안전한 패스워드 저장


  위 사이트에서 나온 부분 중 대표적인 해시 암호화 함수인 SHA- 계열을 Java에서 구현하는 방법을 기술한다.  Oracle(구 Sun)의 1.6 이상 JVM이면 다 지원됩니다(IBM의 JVM에서도 확인).



  SHA(위키피디아)는 Secure Hash Algorithm의 약자로 기존에 많이 사용되던 MD5(Message-Digest algorithm 5, 위키피디아)가 암호화로 쓰이기는 부적합하여 해시 암호화를 위해 개발되었고 Java의 암호화 알고리즘에서는 SHA-1, SHA-256, SHA-384, SHA-512 를 지원합니다.


서론이 길었으니 일단 그 중 SHA-512 방식의 암호화 함수 예제를 한 번 보겠습니다.

 private static String getSha512(String plainText) {
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-512");
			byte[] bytes = plainText.getBytes(Charset.forName("UTF-8"));
			md.update(bytes);
			return Base64.encode(md.digest());
		} catch (Exception e) {
			System.out.println("Sha512 error.");
			e.printStackTrace();
			return null;
		}
	}



  의외로 위와 같이 간단합니다.  SHA-1, SHA-256, SHA-384 등은 3번째 라인의 "SHA-512" 부분만 해당 값으로 변경하면 됩니다.  물론 간단한 코드라 Base64 인코딩이나 NullPointerException 방지를 위한 체크 등은 더 필요하구요.  


  다만 많은 구현에서 String <=> byte[] 간의 변환시에 별도의 인코딩을 지정을 안하는 경우가 많던데 그럴 경우 환경이 달라지면(예를들어 MS949 기반의 윈도우에서 구동하는 프로그램과 UTF-8 기반의 Unix에서 구동하는 프로그램이 동시에 서로 암복호화를 할 경우) 한글 등을 처리할 때 문제가 발생할 수 있으니 인코딩은 꼭 지정하시길 바랍니다.


  담번에는 대표적인 복호화 가능한 대칭키 암호화 알고리즘인 AES와 참고 사이트에서 나왔던 bCrypt에 대해서 간단히 포스팅할 예정입니다.
(일단 테스트는 다 된 상황이라.. 정리만 하면...)

'Java' 카테고리의 다른 글

"\ub4f1" 와 같은 unicode 문자열 읽어오기  (0) 2014.01.28
JDK 1.7.21에서 Runtime.exec의 변경사항  (0) 2013.04.26
:
Posted by hanavy
2014. 1. 28. 12:56

"\ub4f1" 와 같은 unicode 문자열 읽어오기 Java2014. 1. 28. 12:56

컴퓨터가 7bit면 자신들의 모든 문자를 표현 가능한 문화권에서 개발되다 보니 아무래도 우리나라처럼 2-byte 문자열을 쓰는 나라들에서는 아직까지도 문제가 생기는 경우가 많습니다.  우리나라 같은 경우는 한글문제라고 흔히들 통칭하는데..


그나마 현대의 언어들은 상당수 다국어 지원(유니코드를 비롯)을 기본적으로 가져가기 때문에 일반적인 환경에서는 문제가 잘 생기지 않는 경우들이 많지만 그렇기 때문에 가끔 문제가 생기면 더더욱 힘든 케이스들도 많이 보입니다.
자바의 경우는 처음부터 내부적으로 유니코드만을 사용하는 등 언어 자체적으로 국제화를 고려해서 만들었지만 초기 API 설계의 miss로 지금은 deprecated된 함수들도 많이 있죠...(국제화쪽 관련해서는 주로 I/O쪽.. LineNumberInputStream 등등..)


여튼 서론은 이정도고..
이번에 하는 프로젝트에서 property 파일(key=value 형태로 텍스트로 저장하는)에서 값을 읽어와야 할 일이 있는데 Eclipse 기반의 개발환경에서 property 파일 편집을 위해 일본에서 만든 플러그인인 PropertiesEditor라는걸 사용하더군요..
그런데 문제(?)는 이 플러그인이 파일을 저장하면 한글이 다음과 같이 저장됩니다.


# \uc2dc\uc2a4\ud15c \uacf5\ud1b5


저 문자열은 원래 다음과 같은 글자입니다.


# 시스템 공통


유니코드를 저장할 때 ASCII 영역 외의 2-byte 문자열의 경우 \uXXXX 형태로 저장하는 걸로 보입니다.
그런데 문제는 저 내용을 다음과 같이 소스코드상에 넣으면 잘 나오는데

public static void main(String[] args) {
    System.out.println("# \uc2dc\uc2a4\ud15c \uacf5\ud1b5");
}

저걸 파일에서 읽어오면 저 문자열 그대로 읽어오더군요..
처음에는 다음과 같은 방법을 사용해 봤습니다.

public static void main(String[] args) throws IOException {
    LineNumberReader in = new LineNumberReader(new InputStreamReader(new FileInputStream("c:\\a.properties"), "UTF-8"));
    System.out.println(in.readLine());
    in.close();

음.. UTF-8이긴 하지만 헥사값의 내용이 아닌 헥사값의 표현인 영문값이 저장된 형태이기 때문에 효용이 없었습니다.
그래서 이런때를 위한 구글신에게 검색이 들어갔습니다.


찾아보다 보니 다음과 같은 내용이 보이더군요..
Unicode Escape Formats 라는 내용인데 유니코드를 Escape Sequence를 이용해서 표기하는 여러가지 방법을 나열했는데 그 중에 위의 내용이 보입니다.
Java나 Ruby에서 쓰이는 포맷이라고 합니다.  언어별로 표기하는 법들이 다들 천차만별이라..


여튼 검색하다 보니 반대의 경우, 즉 한글을 넣으면 저렇게 unicode sequence를 기반으로 만들어 주는 프로그램은 JDK에 기본적으로 같이 제공이 되고 있습니다.
native2ascii 라는 프로그램인데 실행 후 console에서 입력하면 다음과 같이 만들어 줍니다.


실행하면 그냥 커서만 깜빡이는데 여기에 문자열을 아무거나 입력하면 "\u" 를 이용한 Escape Sequence 문자열로 만들어줍니다.(종료시에는 그냥 Ctrl-C 사용)
그런데 일단 다른 별도의 프로그램을 쓰는 방식은 프로그래머들에게는 별 도움 안되고 일단 지금 필요한 건 반대의 케이스라..
무언가가 있을거 같긴 한데 결국 찾지는 못했고 그냥 만들었습니다.(몇 개 찾는 솔루션들도 다들 직접 구현했더군요..)


원리는 간단합니다.\uXXXXX 형태로 저장된 문자열을 찾으면 \u를 제거하고 XXXX 로 표현된 32bit 문자열을 읽어서 해당 char 형태로 바꿔주면 됩니다.(자바는 내부적으로 유니코드를 사용하므로 char는 2 byte 입니다.)
일단 최적화는 크게 고민은 안했고 기능상으로 다음과 같이 만들었습니다.

	private String unicodeConvert(String str) {
		StringBuilder sb = new StringBuilder();
		char ch;
		int len = str.length();
		for (int i = 0; i < len; i++) {
			ch = str.charAt(i);
			if (ch == '\\' && str.charAt(i+1) == 'u') {
				sb.append((char) Integer.parseInt(str.substring(i+2, i+6), 16));
				i+=5;
				continue;
			}
			sb.append(ch);
		}
		return sb.toString();
	}

일단 개념 정도고 제대로 사용하려면 예외상황(\u 뒤에 4byte의 16진수 데이터가 올바로 나오지 않을때는? 등등)에 대한 처리가 좀 더 필요합니다.

'Java' 카테고리의 다른 글

Java에서 SHA 기반 해시암호화  (1) 2015.04.29
JDK 1.7.21에서 Runtime.exec의 변경사항  (0) 2013.04.26
:
Posted by hanavy