Java ME 개발자라면 언제 어떻게 보안 기술을 제대로 사용할 수 있는지 반드시 알아야 한다. 모바일 장치에 획기적인 전기를 마련한 MSA(Mobile Service Architecture) 사양을 지원하는 모바일 장치는 앞으로 몇 개월간(그리고 몇 년간) 계속 늘어날 것이다. MSA는 SATSA(Security and Trust Services API)를 비롯한 다양한 모바일 Java 사양을 포함하고 있다.

SATSA를 사용하는 모바일 개발자는 다음과 같은 보안 기능을 수행할 수 있다.

  • 3DES 및 AES와 같은 표준 암호화 알고리즘을 사용하여 데이터를 암호화하고 해독한다.
  • 디지털 서명을 작성, 서명하고 확인한다.
  • 대칭 및 비대칭 키를 작성한다.
  • 모바일 장치에 포함된 보안 요소와 상호 작용한다.

    SATSA에 구현된 암호화 API는 SATSA-Crypto라고도 부르며 JDK 1.4에 구현된 암호화 API를 모델로 한 것이다. 따라서 이 테크팁에서 학습하는 기술은 어디서든 사용할 수 있다.

    이 테크팁에서는 독자가 암호화 기술에 대한 배경 지식이 없다고 가정한다. 따라서 대칭 암호화와 비대칭 암호화의 차이점을 이해할 필요가 있다. 다음 그림을 살펴보자.





    대칭암호화



    보다시피 대칭 암호화에서는 데이터를 암호화하는 키가 해독하는 데에도 쓰인다. 이러한 대칭 암호화의 특징 때문에 그 사용 범위가 제한적이다. 본인이 사용할 데이터를 암호화할 경우 대칭 암호화가 효과적이지만, 다른 사람이 나에게 안전하게 데이터를 보내야 하는 경우에는 좋은 방법이 아니다. 보안을 위태롭게 하는 상황이 벌어질 수 있으므로, 자신의 대칭 키를 다른 사람과 공유하는 것은 좋은 생각이 아니다.

    그러나 다음 그림은 비대칭 암호화가 이 문제를 어떻게 해결하는지 보여 준다.

    비대칭암호화



    비대칭 암호화 기술을 사용할 경우 하나가 아니라 두 개의 키가 존재한다. 첫 번째 키(공개 키)는 데이터를 보호하고 암호화할 수만 있다(데이터 해독에 절대 쓰일 수 없음). 두 번째 키(개인 키)는 오로지 데이터를 해독하는 데에만 쓰일 수 있다(데이터 암호화에 쓰일 수 없음). 본인이 사용할 데이터를 보호하기 위해 비대칭 암호화까지 사용할 필요는 없을 것이다. 하지만 여러 상대방과 통신하는 가운데 그들이 여러분에게 안전하게 데이터를 보내야 한다면 개의치 않고 그 사람들에게 공개 키를 제공하면 된다. 이 키는 데이터를 암호화하는 데에만 쓰이며, 그 데이터는 오로지 여러분 자신만 해독할 수 있기 때문이다. 물론 개인 키는 혼자서만 보관해야 한다.

    이 예에서는 3DES 대칭 암호화를 사용하여 일반 문자열을 어떻게 암호화하고 해독하는지 보여 준다. 다음과 같이 키를 작성한다.

    // 24 byte symmetric 3DES-EDE key

        byte[] symKey = {

          (byte) 0xca, (byte) 0x00, (byte) 0x25, (byte) 0x06,

          (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xbd,

          (byte) 0x2b, (byte) 0x7e, (byte) 0x15, (byte) 0x16,

          (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xa6,

          (byte) 0x2c, (byte) 0x7e, (byte) 0x10, (byte) 0x96,

          (byte) 0x28, (byte) 0xff, (byte) 0xd2, (byte) 0xa6,

        };

    보다시피 키를 만들기 위해 바이트로 분류되는 24개의 바이트 어레이를 작성했다. 정해진 순서는 없으며 24바이트의 어레이만 있으면 된다. 코드 예제에서 이 어레이의 바이트 값을 변경해야 이 키가 암호화된 텍스트의 결과에 어떤 영향을 주는지 알 수 있다.

    다음 행은 실제 Key 및 Cipher 개체를 작성하는 방법을 보여 준다.

    Key encryptionKey = new SecretKeySpec(symKey, 0, symKey.length, "DESede");

    Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");

    이와 같이 SecretKeySpec 생성자의 마지막 매개 변수는 암호화된 알고리즘이 제공되어야 함을 나타낸다. 이 예제에서 3DES 알고리즘을 사용할 것이라고 말했으므로, 그 암호화 알고리즘을 나타낼 String, “DESede”도 제공한다. 또한 암호화 알고리즘은 Cipher 클래스에서 새 인스턴스를 가져오도록 지정해야 한다. 그러나 여기서는 블록 문자와 패딩 모드도 지정해야 했다. Key와 Cipher가 있으면 데이터 암호화는 식은 죽 먹기이다.

    cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);

       byte[] ciphertext = new byte[ciphertextLength];

       cipher.doFinal(messageBytes, 0, messageBytes.length, ciphertext, 0);

    데이터 해독 역시 매우 쉽다. Cipher 모드만 바꾸면 된다.


    cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
    byte[] decrypted = new byte[messageBytes.length];
    cipher.doFinal(ciphertext, 0, ciphertext.length, decrypted, 0);

    다음 전체 작업 예제는 Sun Wireless Toolkit for CLDCSATSA 지원 모바일 장치에서 실행된다.


    import java.security.*;
    import java.security.spec.*;

    import javax.crypto.*;
    import javax.crypto.spec.*;

    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;

    public class EncryptionTest extends MIDlet implements CommandListener, Runnable {

    // 24 byte symmetric 3DES-EDE key
    byte[] symKey = {
    (byte) 0xca, (byte) 0x00, (byte) 0x25, (byte) 0x06,
    (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xbd,
    (byte) 0x2b, (byte) 0x7e, (byte) 0x15, (byte) 0x16,
    (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xa6,
    (byte) 0x2c, (byte) 0x7e, (byte) 0x10, (byte) 0x96,
    (byte) 0x28, (byte) 0xff, (byte) 0xd2, (byte) 0xa6,
    };

    private Display display;
    private Form startForm;
    private Command exitCommand;

    public EncryptionTest() {
    exitCommand = new Command("Exit", Command.EXIT, 0);

    startForm = new Form("Encryption Example");
    startForm.append("");
    startForm.addCommand(exitCommand);
    startForm.setCommandListener(this);
    }

    public void startApp() {
    display = Display.getDisplay(this);
    display.setCurrent(startForm);

    Thread t = new Thread(this);
    t.start();
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command command, Displayable s) {
    if (command == exitCommand) {
    notifyDestroyed();
    }
    }

    public void run() {
    try {
    encryptAndDecrypt("This is string with some text");
    encryptAndDecrypt("ID: 2341234");
    encryptAndDecrypt("PIN: 0001");

    } catch (Exception e) {
    System.out.println(e.toString());

    }

    }

    private void encryptAndDecrypt(String plainText)
    throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
    InvalidKeyException, IllegalStateException, ShortBufferException,
    IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {

    byte[] messageBytes = plainText.getBytes();
    print("Plain text: " + plainText);

    // Create the symmetric encryption Key
    Key encryptionKey = new SecretKeySpec(symKey, 0, symKey.length, "DESede");

    /* Construct Cipher class with name of the transformation algorithm */
    Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");

    // Calculate ciphertext size.
    int blocksize = 16;
    int ciphertextLength = 0;
    int remainder = messageBytes.length % blocksize;

    if (remainder == 0) {
    ciphertextLength = messageBytes.length;
    } else {
    ciphertextLength = messageBytes.length - remainder + blocksize;
    }
    System.out.println("ciphertext length: " + ciphertextLength);

    cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
    byte[] ciphertext = new byte[ciphertextLength];
    cipher.doFinal(messageBytes, 0, messageBytes.length, ciphertext, 0);
    print("Encrypted text: " + new String(ciphertext));

    cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
    byte[] decrypted = new byte[messageBytes.length];
    cipher.doFinal(ciphertext, 0, ciphertext.length, decrypted, 0);
    print("the decrypted text is: " + new String(decrypted));

    }

    private void print(String s) {
    startForm.append(s);
    }
    }

    * 저자소개
    : Bruce HopkinsBluetooth for Java (Apress Publishers)의 저자이며 JB-22 developer kit 개발자이기도 하다.

    이 아티클의 영문 원본은
    http://blogs.sun.com/mobility_techtips/entry/how_to_encrypt_data_in
    에서 볼 수 있습니다.

  • "Java ME" 카테고리의 다른 글

    2007/12/03 17:35 2007/12/03 17:35

    TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/469

    댓글을 달아 주세요

    [로그인][오픈아이디란?]

    ◀ Prev 1  ... 195 196 197 198 199 200 201 202 203  ... 641  Next ▶