2011년 6월 9일 목요일

자바보안과 암호화 - 4

Chapter 4 인증
인증에 유요한 세가지 암호화 개념
- 메시지 축약(message digest)은 대용량 데이터 집합을 나타내는 식별자를 생성한다.
- 전자 서명(digital signature)은 데이터의 무결성을 증명하는데 사용한다.
- 인증서(certificate)는 암호적으로 공개키의 안전한 컨테이너로 사용된다.

변경된 메시지 축약
package test.crypto.part6;
import java.security.*;
import java.io.*;
import sun.misc.*;
public class MessageDigestTester {
public MessageDigestTester() {
}
private void exec(String targetFileName) {
try {
// MD5알고리즘을 이용한 메시지 축약 객체를 생성한다.
MessageDigest md = MessageDigest.getInstance("MD5");
// 주어진 파일에 대한 축약 계산
DigestInputStream in = new DigestInputStream(new FileInputStream(targetFileName), md);
byte[] buffer = new byte[8192];
while ( in.read(buffer) != -1 ) {
}
byte[] raw = md.digest();
// 출력 가능한 문자열로 변환한다.
BASE64Encoder encoder = new BASE64Encoder();
String base64 = encoder.encode(raw);
System.out.println(base64);
} catch(NoSuchAlgorithmException nalgoe) {
System.err.println(nalgoe);
} catch(FileNotFoundException fnote) {
System.err.println(fnote);
} catch(IOException ioe) {
System.err.println(ioe);
}
}
public static void main(String[] args) {
if(args.length < 1) {
System.out.println("메시지 축약의 대상 파일을 선택하여 주십시요");
System.exit(0);
}
String targetFileName = args[0];
MessageDigestTester masher = new MessageDigestTester();
masher.exec(targetFileName);
}
}


암호화된 패스워드 로그인
클라이언트에서 서버로 평문을 전송하는 것을 피하기 위해서, 클라이언트는 평문 대신에 패스워드 메시지를 축약하여 보내게 되며, 서버는 보유하고 있는 패스워드 사본의 메시지 축약을 비교하여 개의 메시지 축약 내용이 같을 경우에 클라이 언트를 인증하게 된다.
//--- < masher Server >
package test.crypto.part6;
import java.util.*;
import java.net.*;
import java.io.*;
import java.security.*;
public class MasherServer {
public MasherServer() {
}
public void exec(int port) throws Exception {
ServerSocket ss = new ServerSocket(port);
System.out.println("요청을 기다리고 있습니다.... port : "+port);
Socket s = ss.accept();
DataInputStream in = new DataInputStream(s.getInputStream());
// 클라이언트가 보낸 순서로받는다.
String user = in.readUTF();
long time = in.readLong();
double randomQ = in.readDouble();
int leng = in.readInt();
byte[] masherBytesIn = new byte[leng];
in.readFully(masherBytesIn);
byte[] masherBytesOut = userMasher.makeDigest(user, getPassword(), time, randomQ);
if(isUser(masherBytesIn, masherBytesOut)) {
System.out.println("Login");
} else {
System.out.println("No password");
}
in.close();
}
private String getPassword() {
return "rlarudwls";
}
private boolean isUser(byte[] inBytes, byte[] outBytes){
return MessageDigest.isEqual(inBytes, outBytes);
}
public static void main(String[] args) throws Exception {
if(args.length < 1) {
System.out.print("포트를 입력하여 주십시요....");
System.exit(0);
}
MasherServer ms = new MasherServer();
ms.exec(Integer.parseInt(args[0]));
}
}

//---< masherClient >
package test.crypto.part6;
import java.util.*;
import java.net.*;
import java.io.*;
public class MasherClient {
public MasherClient() {
}
public void exec(String user, String password, String host, int port) throws Exception {
Date date = new Date();
long time = date.getTime();
double randomQ = Math.random();
byte[] masherBytes = userMasher.makeDigest(user, password, time, randomQ);
Socket s = new Socket(host, port);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeUTF(user);
out.writeLong(time);
out.writeDouble(randomQ);
out.writeInt(masherBytes.length);
out.write(masherBytes);
out.flush();
out.close();
}
public static void main(String[] args) throws Exception {
if(args.length < 2) {
System.out.print("서버 주소와 포트를 입력하여 주십시요....");
System.exit(0);
}
String user = "inter999";
String password = "rlarudwls";
MasherClient mc = new MasherClient();
mc.exec(user, password, args[0], Integer.parseInt(args[1]));
}
}

package test.crypto.part6;
import java.io.*;
import java.security.*;
public class userMasher {
public static byte[] makeDigest(String user, String password, long time, double randomQ)
throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(user.getBytes());
md.update(password.getBytes());
md.update(makeBytes(time, randomQ));
return md.digest();
}
public static byte[] makeBytes(long time, double randomQ) {
try {
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
DataOutputStream dataout = new DataOutputStream(byteout);
dataout.writeLong(time);
dataout.writeDouble(randomQ);
return byteout.toByteArray();
} catch (IOException ioe) {
return new byte[0];
}
}
}


이중 암호화 패스워드 로그인
메시지 축약을 사용하여 패스워드 정보를 보호하는 강력한 방법으로 이중 암호화 기법이 있는데, 이의 구성은암호화 패스워드 로그인 추가적으로 타임스템프와 난수를 포함한다. 번째 축약에서 처음 축약메시지와 타임스템프, 난수를 이용하여 축약한다.

MAC
클래스는 메시지 인증 코드(MAC)에 대한 API를 정의한다. MAC은 비밀키를 공유하는 집단 사이에서 전송되는 정보의 무결성을 검사할 있다. MAC은 공개키/개인키가 아니라 비밀키와 함께 생성된다는 점을 제외하면 디지털 서명과 비슷하다. MAC 클래스는 알고리즘과 무관하며 제공자-기반이다. 정적 getInstance() 팩토리 메소드 하나를 호출하여 희망하는 MAC 알고리즘의 이름을 지정하여 MAC 객체를 얻는다.

SunJCE"제공자는HmacMD5", "HmacSHA1"이라는 개의 알고리즘을 구현한다.
1. Mac 객체를 얻은 후에는 init() 메소드를 호출하여 SecretKey를 지정하여 Mac 객체를 초기화 한다.
2. Mac 객체를 얻고 초기화 후에는, Mac이 계산될 데이터를 지정한다. 단순히 단일 바이트 배열을 처리 할때는 doFinal()에 전달하고, 스트리밍이나 다양한 위치에 저장된다면 update()를 여러번 호출하여 처리한다.
SecureRandom sr = new SecureRandom();
byte[] keyBytes = new byte[20];
sr.nextBytes(keyBytes);
SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac m = Mac.getInstance("HmacSHA1");
m.init(key);
m.update(inputData);
byte[] mac = m.doFinal();

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...