ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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 등을 사용할 수 있다. 

Designed by Tistory.