'2008/08'에 해당되는 글 4건

콘솔로부터 패스워드 입력받기 :: 2008/08/24 14:19

커맨드라인 기반의 어플리케이션이나 서버 어플리케이션 등에서 커맨드라인에서 패스워드를 입력받는 경우는 종종 필요하다. 자바는 AWT/Swing에서는 패스워드를 마스킹할 수 있는 메소드를 별도로 제공하기 때문에 쉽게 구현할 수 있지만, 커맨드라인에서 패스워드를 마스킹하는 API를 별도로 제공하지 않아 여러 개발자에게 불편함을 주었다.

Java SE 6.0에서는 java.io.Console 이라는 클래스에서 콘솔 장치에 대한 IO를 지원하는데, 패스워드 마스킹을 readPassword()라는 메소드를 통해 쉽게 구현할 수 있다. 아래는 Java SE 5.0 이하에서 사용할 수 있는 커맨드라인에서 패스워드를 입력을 마스킹하는 코드이다.

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 콘솔로부터 패스워드 입력 마스킹하기
 */
public class ConsolePassword {

    public static void main(String[] args) throws Exception {
        BufferedReader stdin =
            new BufferedReader(new InputStreamReader(System.in));
        ConsoleEraser consoleEraser = new ConsoleEraser();
        System.out.print("Enter Password: ");
        consoleEraser.start();
        String password = stdin.readLine();
        consoleEraser.halt();
        System.out.print("\b");
        System.out.println("password=" + password);
    }
}

class ConsoleEraser extends Thread {

    private boolean running = true;

    public void run() {
        while (running) {
            // System.out.print("\b*");
            System.out.print("\b ");
            try {
                Thread.currentThread().sleep(1);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }

    public synchronized void halt() {
        running = false;
    }
}

참조: http://java.sun.com/developer/technicalArticles/Security/pwordmask/

자바 암호화/복호화 코드 :: 2008/08/23 23:11

자바에서 대칭키 방식의 문자열 및 파일을 암호화/복호화하는 코드이다. 암복호화 알고리즘은 Java Cryptography Extension (JCE)에 의해 지원된다.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;

/**
 * 문자열 및 파일에 대한 암호화/복호화
 */
public class Crypto {

    /** 파일 처리용 버퍼 크기 */
    private static final int BUFFER_SIZE = 8192;

    /** 디폴트 비밀키 파일 */
    private static final String DEFAULT_KEY_FILE = "default.key";

    /** 비밀키 */
    private static Key key = null;

    /**
     * 비밀키 파일 생성 메소드
     * 
     * @return 비밀키 파일
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static File makeKey() throws IOException, NoSuchAlgorithmException {
        return makeKey(DEFAULT_KEY_FILE);
    }

    public static File makeKey(String filename) throws IOException,
                    NoSuchAlgorithmException {
        File file = new File(filename);
        KeyGenerator generator = KeyGenerator.getInstance("DES");
        generator.init(new SecureRandom());
        Key key = generator.generateKey();
        ObjectOutputStream out =
            new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(key);
        out.close();
        return file;
    }

    /**
     * 지정된 비밀키를 가지고 오는 메서드
     * 
     * @return 비밀키
     * @throws Exception
     */
    private static Key getKey() throws Exception {
        if (key != null) {
            return key;
        } else {
            return getKey(DEFAULT_KEY_FILE);
        }
    }

    private static Key getKey(String filename) throws Exception {
        if (key == null) {
            File file = new File(filename);
            if (!file.exists()) {
                file = makeKey();
            }
            if (file.exists()) {
                ObjectInputStream in =
                    new ObjectInputStream(new FileInputStream(filename));
                key = (Key) in.readObject();
                in.close();
            } else {
                throw new Exception("암호키 객체를 생성할 수 없습니다.");
            }
        }
        return key;
    }

    /**
     * 문자열 대칭 암호화
     * 
     * @param strVal 암호화할 문자열
     * @return 암호화된 문자열
     * @throws Exception
     */
    public static String encrypt(String strVal) throws Exception {
        if (strVal == null || strVal.length() == 0)
            return "";
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, getKey());
        String amalgam = strVal;

        byte[] inputBytes1 = amalgam.getBytes("UTF-8");
        byte[] outputBytes1 = cipher.doFinal(inputBytes1);
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        String outputStr1 = encoder.encode(outputBytes1);
        return outputStr1;
    }

    /**
     * 문자열 대칭 복호화
     * 
     * @param strVal 복호화할 문자열
     * @return 복호화된 문자열
     * @throws Exception
     */
    public static String decrypt(String strVal) throws Exception {
        if (strVal == null || strVal.length() == 0)
            return "";
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, getKey());
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();

        byte[] inputBytes1 = decoder.decodeBuffer(strVal);
        byte[] outputBytes2 = cipher.doFinal(inputBytes1);

        String strResult = new String(outputBytes2, "UTF-8");
        return strResult;
    }

    /**
     * 파일 대칭 암호화
     * 
     * @param infile 암호화할 파일명
     * @param outfile 암호화된 파일명
     * @throws Exception
     */
    public static void encryptFile(String infile, String outfile)
                    throws Exception {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, getKey());

        FileInputStream in = new FileInputStream(infile);
        FileOutputStream fileOut = new FileOutputStream(outfile);

        CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while ((length = in.read(buffer)) != -1)
            out.write(buffer, 0, length);
        in.close();
        out.close();
    }

    /**
     * 파일 대칭 복호화
     * 
     * @param infile 복호화할 파일명
     * @param outfile 복호화된 파일명
     * @throws Exception
     */
    public static void decryptFile(String infile, String outfile)
                    throws Exception {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, getKey());

        FileInputStream in = new FileInputStream(infile);
        FileOutputStream fileOut = new FileOutputStream(outfile);

        CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while ((length = in.read(buffer)) != -1)
            out.write(buffer, 0, length);
        in.close();
        out.close();
    }
}

JUnit과 TestNG 비교 :: 2008/08/20 17:02

다양한 프레임워크에서 도입되고 확장되어온 JUnit은 최근에 JUnit 4.5가 릴리즈 되었다. 한편 단위테스트를 넘어 통합/기능테스트를 지원하는 TestNG는 JUnit 보다 더 많은 테스팅 기능들을 제공하고 있다. 두 테스팅 프레임워크의 기능/특징 비교 내용을 옮겨보았다.

Feature JUnit TestNG
User Defined Life Cycle check check
Test Organization (groups, etc)   check
Distributed Test Execution   check
Parallel Test Execution   check
Data Driven Tests   check
Dependency Testing   check
IDE Integration check check
Ant Integration check check
Maven Integration check check
Domain Specific Extensions (Database, HTTP, etc) check  
Active Community check check

출처: http://www.michaelminella.com/blog/2.html

자바 파일 복사 코드 :: 2008/08/08 10:17

자바에서 파일을 복사하는 코드이다. JDK 1.4 이상에부터는 java.nio.* 패키지를 사용하며 더 빠른 IO 작업을 할 수 있다.

1. JDK 1.4 이전에서 IO 패키지 이용
import java.io.*;

public static void copyFile(String source, String target) throws IOException {
    FileInputStream fis = new FileInputStream(source);
    FileOutputStream fos = new FileOutputStream(target);
    try {
        byte[] buf = new byte[1024];
        int i = 0;
        while ((i = fis.read(buf)) != -1) {
            fos.write(buf, 0, i);
        }
    } catch (IOException e) {
        throw e;
    } finally {
        if (fis != null)
            fis.close();
        if (fos != null)
            fos.close();
    }
}

2. JDK 1.4 이상에서 NIO 패키지 이용 (더 빠름)
import java.io.*;
import java.nio.channels.*;

public static void copyFile(String source, String target) throws IOException {
    FileChannel inChannel = new FileInputStream(source).getChannel();
    FileChannel outChannel = new FileOutputStream(target).getChannel();
    try {
        // magic number for Windows, 64Mb - 32Kb
        int maxCount = (64 * 1024 * 1024) - (32 * 1024);
        long size = inChannel.size();
        long position = 0;
        while (position < size) {
            position += inChannel.transferTo(position, maxCount, outChannel);
        }
    } catch (IOException e) {
        throw e;
    } finally {
        if (inChannel != null)
            inChannel.close();
        if (outChannel != null)
            outChannel.close();
    }
}