자세한 내용을 알고 싶은 분은 다음의 블로그를 참조하세요
http://blog.naver.com/dury00?Redirect=Log&logNo=130044978311
1 내용
가) 일종의 데이터 지문
나) 데이터가 바뀌지 않았다는 것을 증명
다) 데이터의 길이에 상관없이 보통 16 또는 20byte
라) FTP파일 검증에 많이 사용
마) 해쉬를 이용
바) 한 방향 변환이고 역으로는 불가능
2 자바에서의 메시지 다이제스트 사용
가) java.security.MessageDigest
① getInstance()로 인자 생성
② MD5, SHA-1이 주로 사용됨
나) update()
① 데이터를 해쉬 함
다) digest()
① 바이트 배열로 해쉬를 반환
② 적은 데이터일 경우 digest에 직접 입력 가능
라) 파일의 메시지 다이제스트 계산
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
import com.Ostermiller.util.Base64;
public class DigestFile {
public static void main(String[] args) throws NoSuchAlgorithmException, IOException { MessageDigest md = MessageDigest.getInstance("MD5"); BufferedInputStream in = new BufferedInputStream(new FileInputStream("c:\\test.txt"));
int theByte = 0; while((theByte = in.read()) != -1) md.update((byte)theByte);
in.close(); byte[] theDigest = md.digest();
System.out.println(Base64.encode(theDigest));
}
} |
마) 실행결과
① test.txt 파일에는 ‘this is a test file’이 들어 있음 : [B@1a758츄
② ‘this is a test file.’로 수정한 결과 : [B@1b67f74
바) 스트림에서의 메시지 다이제스트
① DigestInputStream & DigestOutputStream
MessageDigest messageDigest = MessageDigest.getInstance(“MD5”); DigestOutputStream output = new DigestOutputStream(existingOutputStream, messageDigest); |
② 출력에 쓰는 모든 바이트가 자동으로 메시지 다이제스트를 계산할 때 사용됨
③ 예제
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.security.DigestInputStream; import java.security.MessageDigest;
import com.Ostermiller.util.Base64;
public class DigestStreamExample {
public static void main(String[] args) throws Exception{ MessageDigest md = MessageDigest.getInstance("MD5"); BufferedInputStream in = new BufferedInputStream(new FileInputStream("c:\\test.txt"));
//DigestInputStream을 생성한다. DigestInputStream digestIn = new DigestInputStream(in, md); // 모든 데이터를 읽어들인다. while(digestIn.read() != -1); byte[] theDigest = md.digest();
System.out.println(Base64.encode(theDigest)); } } |
3 패스워드 인증
가) 의미
① 패스워드를 해쉬하여 저장할 경우 복호화는 불가능하지만 모든 가능한 패스워드를 해쉬한 다음 비교해서 추즉하는게 가능함
② 이런 공격을 막기 위해 salt와 패스워드를 같이 저장해야 함
③ 서버가 실제 패스워드를 알 필요 없이 사용자가 정한 패스워드를 검증하는게 목적
나) 패스워드 저장
① 랜덤 salt 생성하여 패스워드 앞에 붙임
② 이것을 해쉬함
③ 패스워드 입력될 때마다 비교를 위해 salt와 해쉬 결과를 붙여서 저장
다) 패스워드 인증
① 저장된 패스워드의 salt와 사용자가 입력한 패스워드를 합친다.
② salt와 패스워드를 해쉬한다.
③ 결과 해쉬값을 파일에 저장된 것을 비교한다. 같다면 패스워드가 같은 것이다.
라) 예제
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Arrays;
public class Passwordauthenticator {
public static void main(String[] args) throws Exception{ createPassword("iloveyou"); authenticatePassword("iloveyou");
}
private static void createPassword(String password) throws Exception { // salt 생성 SecureRandom random = new SecureRandom(); byte[] salt = new byte[12]; random.nextBytes(salt);
// salt와 패스워드를 붙여서 해쉬한다. MessageDigest md = MessageDigest.getInstance("MD5"); md.update(salt); md.update(password.getBytes("UTF-8")); byte[] digest = md.digest();
// salt와 해쉬 결과를 파일에 저장한다. FileOutputStream fos = new FileOutputStream("c:\\password.txt"); fos.write(salt); fos.write(digest); fos.close(); }
private static void authenticatePassword(String password) throws Exception { // 파일을 읽어들인다. ByteArrayOutputStream baos = new ByteArrayOutputStream(); FileInputStream fis = new FileInputStream("c:\\password.txt"); int theByte = 0; while((theByte = fis.read()) != -1) baos.write(theByte); fis.close(); byte[] hashedPasswordWithSalt = baos.toByteArray(); baos.reset();
//salt를 얻는다. byte[] salt = new byte[12]; System.arraycopy(hashedPasswordWithSalt, 0, salt, 0, 12);
// salt와 입력한 패스워드를 붙여서 해쉬한다. MessageDigest md = MessageDigest.getInstance("MD5"); md.update(salt); md.update(password.getBytes("UTF-8")); byte[] digest = md.digest();
// 파일에 있는 내용과 비교한다. byte[] digestInFile = new byte[hashedPasswordWithSalt.length-12]; System.arraycopy(hashedPasswordWithSalt, 12, digestInFile, 0, hashedPasswordWithSalt.length-12);
if(Arrays.equals(digest, digestInFile)) System.out.println("Password matches."); else System.out.println("Password does not matches."); } } |
'UP! > Crypto' 카테고리의 다른 글
MAC (0) | 2015.11.05 |
---|---|
Session key (0) | 2015.11.05 |
대칭키 암호화 (0) | 2015.11.05 |
패스워드 기반 암호화 (0) | 2015.11.05 |
JCA, JCE (0) | 2015.11.05 |