-
MessageDigest 클래스를 사용한 해시값 생성java/jca 2019. 6. 11. 14:34
package jce; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MessageDigestExample { public static void main(String[] args) throws NoSuchAlgorithmException { Charset charset = Charset.forName("UTF-8"); String plainText = "오"; MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(plainText.getBytes()); byte[] hash = md.digest(); System.out.println(SecureRandom.bytesToHexString(hash)); } }
결과
B9C663CA8C1622B3AC665E093E039C9679CE2D745BC6C5AD25480191FC2F05C1
128비트
64개의 16진수로 표현가능
체크섬- 일반적인 해시함수는 데이터의 체크섬을 생성하기 위해서 사용한다.
아파치톰캣에서서 파일의 유효성을 체크하기 위해 MD5같은 체크섬 정보를 제공한다
파일 정보를 체크해 보자
package jce; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class ChecksumExample { public static void main(String[] args) throws NoSuchAlgorithmException, FileNotFoundException { File file = new File("D:"+File.separator+"install"+File.separator+"apache-tomcat-8.5.42.zip"); String sha512 = "1c00f5fcbfc3d9ce1125cd698fc3fc8b4a61b2782b8753033ceb19da04b64d1d64a42e083ca8d7433a8fdcd2bf12ac5d98405c8fdfa369b27d925b5c4f9ccc4a"; MessageDigest md = MessageDigest.getInstance("sha-512"); InputStream in = new BufferedInputStream(new FileInputStream(file)); try { byte[] buffer = new byte[1024]; int read = -1; while((read = in.read(buffer)) != -1) { md.update(buffer,0,read); } } catch (Exception e) { }finally { try { in.close();} catch (IOException e2) { } } byte[] hash = md.digest(); System.out.println("SHA-512 방식의 pache-tomcat-8.5.42.zip 파일의 해시값 : " + sha512); System.out.println("실제 pache-tomcat-8.5.42.zip 파일에 SHA-512 해시 알고리즘을 취한 값 : " + SecureRandom.bytesToHexString(hash)); System.out.println("해시값 비교 : "+sha512.equalsIgnoreCase(SecureRandom.bytesToHexString(hash))); } }
MessageDigestInputStream을 이용하면 더 짧아진다.
package jce; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.bouncycastle.crypto.io.DigestInputStream; public class Checksum2Example { public static void main(String[] args) throws NoSuchAlgorithmException, FileNotFoundException { File file = new File("D:"+File.separator+"install"+File.separator+"apache-tomcat-8.5.42.zip"); String sha512 = "1c00f5fcbfc3d9ce1125cd698fc3fc8b4a61b2782b8753033ceb19da04b64d1d64a42e083ca8d7433a8fdcd2bf12ac5d98405c8fdfa369b27d925b5c4f9ccc4a"; MessageDigest md = MessageDigest.getInstance("sha-512"); InputStream in = new java.security.DigestInputStream(new BufferedInputStream(new FileInputStream(file)), md); try { while(in.read() != -1); } catch (Exception e) { }finally { try { in.close();} catch (IOException e2) { } } byte[] hash = md.digest(); System.out.println("SHA-512 방식의 pache-tomcat-8.5.42.zip 파일의 해시값 : " + sha512); System.out.println("실제 pache-tomcat-8.5.42.zip 파일에 SHA-512 해시 알고리즘을 취한 값 : " + SecureRandom.bytesToHexString(hash)); System.out.println("해시값 비교 : "+sha512.equalsIgnoreCase(SecureRandom.bytesToHexString(hash))); } }
패스워드 저장
해시 함수는 단방향 함수여서 해시값에서 원본 복원이 불가능
패스워드 저장을 위해 해시 함수를 사용하기도 한다.
SHA-1 알고리즘을 이용한 패스워드 함수 예제
보통 MySQL에서 패스워드를 저장하기 위해서 사용하는 방법으로 SHA-1 해시 함수를 두번 호출하고 생성된 해시 값을 16진수의 문자열로 만든다.
package jce; import java.security.MessageDigest; public class MySqlPasswordEx { public static void main(String[] args) { String password = "helloworld"; String digest = password(password); System.out.println("Mysql Password = "+digest); } /** * 입력한 데이터를 SHA-1 알고리즘으로 처리하여 해시값을 계산한다. * @param input 입력 데이터(<code>null</code>이면 안 된다.) * @return 해시값 * */ public static byte[] getHash(byte[] input){ try { MessageDigest md = MessageDigest.getInstance("SHA-1"); return md.digest(input); } catch (Exception e) { throw new RuntimeException("SHA1"+"Algorithm Not Found",e); } } /** * MySQL의 PASSWORD() 함수 * *@param input 입력 데이터 *@return */ public static String password(byte[] input){ byte[] digest = null; //Stage 1 digest = getHash(input); //Stage 2 digest = getHash(digest); StringBuilder sb = new StringBuilder(1 + digest.length); sb.append("*"); sb.append(SecureRandom.bytesToHexString(digest).toUpperCase()); return sb.toString(); } /** * @author dream * @param input * @return * @throws NoSuchAlgorithmException */ public static String password(String input){ if(input == null){ return null; } return password(input.getBytes()); } }
사전 공격등 위험이 존재하므로 Salt 와 반복횟수를 사용하는것이 안전하다.
점더 안전한 방법은 PBKDF2,bcrypt,scrypt 등을 사용할 수 있다.
'java > jca' 카테고리의 다른 글
블록 암호를 사용한 암/복호화 (0) 2019.06.24 Runnable을 활용한 파일의 해시값 계산 (0) 2019.06.24 SecureRandom 사용하기 (0) 2019.06.05 Bouncy Castle Provider 등록하기 (0) 2019.06.04 자바 대칭키 암호화 복호화 예제 (0) 2019.04.26