자바는 친절하게도 암호화 메시지 검증 코드를 구현해주는 클래스를 제공해준다.
JCE(Java Cryptography Extension) 이름의 프레임워크가 바로 그놈이다.
J2SE 1.4 이후부터는 JCE 1.2.2 기본적으로 포함되어 있어서 별다른 라이브러리를 추가해주지 않아도 사용할 있다.
초기 버젼인 JCE 1.2 미국 보안법(?)인가에 걸려서 국내에서는 사용할 수가 없었다. (무기밀매와 똑같은 처벌을 한다는 소문이..)
JCE 1.2.1 나오면서 제한이 풀어져서, 세계적으로 많이(?) 사용하게 되었다.
그런데 JCE 1.2.1 버전의 자체 디지털 서명이 2005 7 27일쯤인가 만료가 되서, 2005년도에 파란을 한번 일으킨적도 있다.
(그럼 만료기간을 어떻게 알수 있을까? 쉽게 알려면, 자신이 사용하는 파일의 정보를 보면 된다.
자신이 사용하는 자바 관련 디렉토리에서 jce.jar 풀어보면 META-INF JCE_RSA.RSA 파일이 있을것이다. 파일을 보면 있는데, 윈도우 환경에서 파일의 확장자를 "p7s" 변경하면 열어볼 있다.)



JCE 사용하지 않아도, 자체적으로 구현해서 마음껏 암호학의 세계를 여행할 있지만, 시간에 쫓기는 분들을 위해서 간단히 사용법을 알아보도록 하자.

암호화에는 크게 블럭 암호화(block encryption) 스트림 암호화(stream encryption) 있는데, 여기서는 가장(?) 많이 쓰이는 블럭 암호화에 대해서 알아보도록 하겠다.
블럭 암호화는 그대로 데이터를 정해진 블럭으로 나눈후 해당 블럭을 암호화하는것이다
대표적으로 DES/3DES/AES/SEED 등이 있다.

DES(Data Encryption Standard) Lucifer 보완하여 IBM에서 개발한 블럭암호 알고리즘이다.
64비트 입력 블럭을 56비트 비밀키를 사용하여 암호화하는 알고리즘이다.
전세계적으로 널리 사용되었다가, 56비트라는 짧은 (key) 인해 안전하지 않다고 보는 견해가 많아져서, 요즘은  AES한테 밀리는 추세이다.

3DES(Triple Data Encryption Standard) DES 단점을 보완하기 위해서 기존의 DES 방식을 3 적용(암호화->복호화->암호화)시킨것으로 과정에 따라서 56비트의 배수로 암호화 복잡도가 증가한다고 한다.
3번의 암복호화 , Encryption->Decryption->Encryption 첫글자를 따서 DESede 명칭하기도한다.

AES(Advanced Encryption Standard) 현재 미국 정부 표준으로 지정된 블럼 암호화 알고리즘으로서, DES 대체하고 있다.
(key) 크기는 128, 160, 190, 224, 256비트를 사용할 있으며, 현재 미국 표준으로 인정받은 것은 128비트이다.
(JCE에서 제공하는것도 128비트밖에 안될지도...)

SEED 한국정보보호진흥원을 중심으로 국내 암호 전문가들이 참여하여 만든, 순수 국내기술 블럭암호화 알고리즘이다.
(SEED 다음에 한번 구현에해보기도 하고 오늘은 다루지 않겠다.)

블럭 암호화를 하기 위해서는 당연히 원문(plain text) 있어야하고, 암화하 하기 위한 (key) 있어야한다.
그리고 블럭 암호화 운용모드에 따라서 IV(Initialization Vector) 필요하기도 하다.
(key) 따라서 대칭키 암호화와 비대칭키 암호화로 나눌 있다.
대칭키 암호화는 암호화키와 복호화키가 동일하다. 속도가 빠른 장점이 있으니 (key) 분배하기 어렵다.(키가 누출되면 암호화 자체가 의미가 없어진다.)
비대칭키 암호화는 (key) 분배 문제때문에 개발되었는데, 암호화와 복호화키가 다르다. , 공개키(PublicKey), 개인키(PrivateKey) 따로 생성된다.
간단히 설명하자면, 멀리 떨어진 시스템에서 사용할때에, 2가지를 결합하여 사용하고 있다.
대칭키 암호화에 사용할 (key) 생성한다음, 비대칭키 암호화를 이용해서 키를 분배한다.
키가 안전하게 분배되면 대칭키 암호화를 이용해서 서로 암호화된 문서를 주고 받고 하는것이다.
(비대칭키 암호화가 대칭키 암호화보다 느리기 때문에 키분배에만 사용한다.)
앞에 설명한 DEs/3DES/AES/SEED 대칭키 암호화 알고리즘이다. 비대칭키 암호화 알고리즘은 RSA(Rivest Shamir Adleman) 있다.(사람 이름 첫글자를 딴것임)

이제 한번 구현해보도록 하자.
(바이트들을 화면에 출력하기(?) 위해 ByteUtils 클래스를 사용하겠다. 첨부파일을 참조하도록 하자)

1. 암호화에 사용할 (key) 만들기
 - 키를 만드는 방법은 랜덤하게 동적으로 만드는 방법과, 정해진 키를 읽어와서 만드는 방법이 있다. 기능을 하는 메소드를 만들어보자.

view source

print?

01

package test.cipher;

02

  

 

03

import java.security.InvalidKeyException;

04

import java.security.Key;

 

05

import java.security.NoSuchAlgorithmException;

06

import java.security.spec.InvalidKeySpecException;

 

07

import java.security.spec.KeySpec;

08

  

 

09

import javax.crypto.Cipher;

10

import javax.crypto.KeyGenerator;

 

11

import javax.crypto.SecretKey;

12

import javax.crypto.SecretKeyFactory;

 

13

import javax.crypto.spec.DESKeySpec;

14

import javax.crypto.spec.DESedeKeySpec;

 

15

import javax.crypto.spec.IvParameterSpec;

16

import javax.crypto.spec.SecretKeySpec;

 

17

  

18

import kr.kangwoo.util.ByteUtils;

 

19

import kr.kangwoo.util.StringUtils;

20

  

 

21

public class CipherTest {

22

      

 

23

    /**

24

     * <p>해당 알고리즘에 사용할 비밀키(SecretKey)를 생성한다.</p>

 

25

     *

26

     * @return 비밀키(SecretKey)

 

27

     */

28

    public static Key generateKey(String algorithm) throws NoSuchAlgorithmException {

 

29

        KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);

30

        SecretKey key = keyGenerator.generateKey();

 

31

        return key;

32

    }

 

33

      

34

    /**

 

35

     * <p>주어진 데이터로, 해당 알고리즘에 사용할 비밀키(SecretKey)를 생성한다.</p>

36

     *

 

37

     * @param algorithm DES/DESede/TripleDES/AES

38

     * @param keyData

 

39

     * @return

40

     */

 

41

    public static Key generateKey(String algorithm, byte[] keyData) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {

42

        String upper = StringUtils.toUpperCase(algorithm);

 

43

        if ("DES".equals(upper)) {

44

            KeySpec keySpec = new DESKeySpec(keyData);

 

45

            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm);

46

            SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);

 

47

            return secretKey;

48

        } else if ("DESede".equals(upper) || "TripleDES".equals(upper)) {

 

49

            KeySpec keySpec = new DESedeKeySpec(keyData);

50

            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm);

 

51

            SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);

52

            return secretKey;

 

53

        } else {

54

            SecretKeySpec keySpec = new SecretKeySpec(keyData, algorithm);

 

55

            return keySpec;

56

        }

 

57

    }

58

}


  코드는 일단 정상(?) 작동하는데, 맞게 구현하지는 아직 모르겠다. (내공이 부족하여 혹시 틀린부분이 있으면 지적바란다.)

2. DES 암호화/복호화 해보기
 - DES 암호화/복화화를 하기위해선 Cipher 클래스를 사용하면 된다.
 - Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding"); 이런씩으로 "암호화알고리즘/운용모드/패딩"으로 사용하면 된다.
 - DES 암호화키가 64비트이므로 64비트 키를 생성하자
   (예리한 분은 여기서 의문을 가질것이다. ~에서 설명할때 DES 56비트 키라고 했는데, 갑자기 여기서는 64비트라고 우기는가에 대해서...
    설명하자면, 64비트의 (외부키) 56비트는 실제의 (내부키) 되고 나머지 8비트는 거사용(?) 비트로 사용된다고 한다.)

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("DES", ByteUtils.toBytes("68616e6765656e61", 16));

 

03

  

04

    String transformation = "DES/ECB/NoPadding";

 

05

    Cipher cipher = Cipher.getInstance(transformation);

06

    cipher.init(Cipher.ENCRYPT_MODE, key);

 

07

      

08

    String str = "hello123";

 

09

    byte[] plain = str.getBytes();

10

    byte[] encrypt = cipher.doFinal(plain);

 

11

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

12

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

 

13

      

14

    cipher.init(Cipher.DECRYPT_MODE, key);

 

15

    byte[] decrypt = cipher.doFinal(encrypt);

16

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

 

17

}


* 실행 결과
원문 : 68656c6c6f313233
암호 : 51d6aa8bcc176819
복호 : 68656c6c6f313233

 실행해보면 암호화/복호화가 잘되는것을 있다.
 DES 암호화 알고리즘이고, ECB 뭘까? 운용모드라고 했는데,  http://blog.kangwoo.kr/13 여기에 퍼온글이 있으니 참조하기 바란다.
 패딩(padding) 그대로 패딩인데, 번역하면 채워넣기, 모자란만큼 채워넣는 역할을 한다. DES 블럭 암호화 알고리즘이다.
 그래서 암호화 할라면 블럭이 필요한데, DES 경우 64비트가 블럭을 형성한다. 그런데 입력한 데이터가 64비트가 안된다면 어떻게 될까?
 궁금하면 "hello123" "hello"으로 바꾼다음 실행해보자. 아마 다음과 같은 에러가 발생할 것이다.
 
* 실행 결과
 Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytes

 입력한 데이터가 8 bytes , 64비트가 아니니 배째라는것이다
 그러면 정상작동을 하기위해서는 블럭크기의 배수만큼 나머지 데이터를 채워줘야하는데 역할을 하는게 패딩이다.
 "DES/ECB/NoPadding" "DES/ECB/PKCS5Padding" 바꾼다음 실행해보자
 이제 데이터가 64비트가 아니어도 정상작동한다. 그래서 귀찮으면 가능한한 패딩을 해주게 하면 좋다.
 (운용 모드가 OFB/CFB 경우 NoPadding 사용해도 상관없다. IV 이용해서 처리할때 필요가 없어지기때문이다. 믿거나 말거나)


3. DESede 암호화/복호화 해보기
 - DES 별반 차이 없다. 크기가 64비트 * 3 = 192비트로 늘어난것밖에 없다.

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("DESede", ByteUtils.toBytes("696d697373796f7568616e6765656e61696d697373796f75", 16));

 

03

  

04

    String transformation = "DESede/ECB/PKCS5Padding";

 

05

    Cipher cipher = Cipher.getInstance(transformation);

06

    cipher.init(Cipher.ENCRYPT_MODE, key);

 

07

      

08

    String str = "hello123";

 

09

    byte[] plain = str.getBytes();

10

    byte[] encrypt = cipher.doFinal(plain);

 

11

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

12

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

 

13

      

14

    cipher.init(Cipher.DECRYPT_MODE, key);

 

15

    byte[] decrypt = cipher.doFinal(encrypt);

16

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

 

17

}


* 실행 결과
원문 : 68656c6c6f313233
암호 : ad44691609cb1e017378631303581279
복호 : 68656c6c6f313233

4. AES 암호화/복호화 해보기
 - DES 별반 차이 없다. 크기가 128비트인것을 제외하면 말이다.

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("AES", ByteUtils.toBytes("696d697373796f7568616e6765656e61", 16));

 

03

  

04

    String transformation = "AES/ECB/PKCS5Padding";

 

05

    Cipher cipher = Cipher.getInstance(transformation);

06

    cipher.init(Cipher.ENCRYPT_MODE, key);

 

07

      

08

    String str = "hello123";

 

09

    byte[] plain = str.getBytes();

10

    byte[] encrypt = cipher.doFinal(plain);

 

11

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

12

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

 

13

      

14

    cipher.init(Cipher.DECRYPT_MODE, key);

 

15

    byte[] decrypt = cipher.doFinal(encrypt);

16

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

 

17

}


* 실행 결과
원문 : 68656c6c6f313233
암호 : d5c5e1ffb734b610679f36c0e535fe39
복호 : 68656c6c6f313233
5. IV 사용하기.
- 블록 암호의 운용 모드(Block engine modes of operation) CBC/OFB/CFB 사용할 경우에는 Initialization Vector(IV) 설정해줘야한다. 왜냐면 사용하기 때문이다. AES 암호화/복호화 코드에서 운용 모드가 CBC 변경해보자.

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("AES", ByteUtils.toBytes("696d697373796f7568616e6765656e61", 16));

 

03

  

04

    String transformation = "AES/CBC/PKCS5Padding";

 

05

    Cipher cipher = Cipher.getInstance(transformation);

06

    cipher.init(Cipher.ENCRYPT_MODE, key);

 

07

      

08

    String str = "hello123";

 

09

    byte[] plain = str.getBytes();

10

    byte[] encrypt = cipher.doFinal(plain);

 

11

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

12

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

 

13

      

14

    cipher.init(Cipher.DECRYPT_MODE, key);

 

15

    byte[] decrypt = cipher.doFinal(encrypt);

16

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

 

17

}


* 실행 결과 원문 : 68656c6c6f313233
암호 : 92e4fa9add0d4d5a07954207890e5b5c
Exception in thread "main" java.security.InvalidAlgorithmParameterException: Parameters missing
...생략...

실행해보면 암호화는 되는데, 복호화도중 파라메터가 없다고 에러가 발생한다. 예상한데로라면 암호화할때도 에러가 나야하는데, 불행히도 암호화는 정상적으로 작동한다. 왜냐면 암호화할때는 IV 지정해주지 않으면, 자동적으로 랜덤 IV 만들어서 사용해버린다.
정말인지 테스트해보자.

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("AES", ByteUtils.toBytes("696d697373796f7568616e6765656e61", 16));

 

03

  

04

    String transformation = "AES/CBC/PKCS5Padding";

 

05

  

06

    Cipher cipher = Cipher.getInstance(transformation);

 

07

    cipher.init(Cipher.ENCRYPT_MODE, key);

08

      

 

09

    String str = "hello123";

10

    byte[] plain = str.getBytes();

 

11

    byte[] encrypt = cipher.doFinal(plain);

12

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

 

13

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

14

      

 

15

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(cipher.getIV()));

16

    byte[] decrypt = cipher.doFinal(encrypt);

 

17

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

18

}


* 실행 결과
원문 : 68656c6c6f313233
암호 : 26c7d1d26c142de0a3b82f7e8f90860a
복호 : 68656c6c6f313233
new IvParameterSpec(cipher.getIV()) 이용해서 자동 생성된 IV 초기화 파라메터를 넘겨주니 정상 작동한다.
실제 사용할때는 암호화 복호화가 따로(?) 작동하니 이렇게 구현하는건 불가능할것이다. IV 크기는 블럭크기와 동일하므로 키처럼 생성해서 관리하면 되겠다.

01

public static void main(String[] args) throws Exception {

02

    Key key = generateKey("AES", ByteUtils.toBytes("696d697373796f7568616e6765656e61", 16));

 

03

    byte[] iv = ByteUtils.toBytes("26c7d1d26c142de0a3b82f7e8f90860a", 16);

04

    String transformation = "AES/CBC/PKCS5Padding";

 

05

  

06

    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

 

07

    Cipher cipher = Cipher.getInstance(transformation);

08

    cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);

 

09

      

10

    String str = "hello123";

 

11

    byte[] plain = str.getBytes();

12

    byte[] encrypt = cipher.doFinal(plain);

 

13

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

14

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

 

15

      

16

    cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);

 

17

    byte[] decrypt = cipher.doFinal(encrypt);

18

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

 

19

}


* 실행 결과
원문 : 68656c6c6f313233
암호 : 1876c3ae98760ccf1821ea46fc9ce761
복호 : 68656c6c6f313233
6. 파일을 AES 암호화/복호화 해보기
 - 이번에 파일을 읽어와서 암호화/복호화를 해보자. JavaIO 다룰 있으면 간단히 구현할 있을것이다.

01

public static void main(String[] args) throws Exception {

02

      

 

03

    Key key = generateKey("AES", ByteUtils.toBytes("696d697373796f7568616e6765656e61", 16));

04

    String transformation = "AES/ECB/PKCS5Padding";

 

05

  

06

    Cipher cipher = Cipher.getInstance(transformation);

 

07

    cipher.init(Cipher.ENCRYPT_MODE, key);

08

  

 

09

    File plainFile = new File("c:/plain.txt");

10

    File encryptFile = new File("c:/encrypt.txt");

 

11

    File decryptFile = new File("c:/decrypt.txt");

12

      

 

13

    BufferedInputStream input = null;

14

    BufferedOutputStream output = null;

 

15

    try {

16

        input = new BufferedInputStream(new FileInputStream(plainFile));

 

17

        output = new BufferedOutputStream(new FileOutputStream(encryptFile));

18

          

 

19

        int read = 0;

20

        byte[] inBuf = new byte[1024];

 

21

        byte[] outBuf = null;

22

        while ((read = input.read(inBuf)) != -1) {

 

23

            outBuf = cipher.update(inBuf, 0, read);

24

            if (outBuf != null) {

 

25

                output.write(outBuf);

26

            }

 

27

        }

28

        outBuf = cipher.doFinal();

 

29

        if (outBuf != null) {

30

            output.write(outBuf);

 

31

        }

32

    } finally {

 

33

        if (output != null) try {output.close();} catch(IOException ie) {}

34

        if (input != null) try {input.close();} catch(IOException ie) {}

 

35

    }

36

              

 

37

    cipher.init(Cipher.DECRYPT_MODE, key);

38

    try {

 

39

        input = new BufferedInputStream(new FileInputStream(encryptFile));

40

        output = new BufferedOutputStream(new FileOutputStream(decryptFile));

 

41

          

42

        int read = 0;

 

43

        byte[] inBuf = new byte[1024];

44

        byte[] outBuf = null;

 

45

        while ((read = input.read(inBuf)) != -1) {

46

            outBuf = cipher.update(inBuf, 0, read);

 

47

            if (outBuf != null) {

48

                output.write(outBuf);

 

49

            }

50

        }

 

51

        outBuf = cipher.doFinal();

52

        if (outBuf != null) {

 

53

            output.write(outBuf);

54

        }

 

55

    } finally {

56

        if (output != null) try {output.close();} catch(IOException ie) {}

 

57

        if (input != null) try {input.close();} catch(IOException ie) {}

58

    }

 

59

}


"plain.txt" 파일을 만들어 놓고 실행하면, "encrypt.txt" "decrypt.txt" 파일이 생성될것이다. 제대로 암호화 복호화되었는지 비교해보자
7. 비밀번호 암호화
 - 대부분의 사이트에서 비밀번호를 암호화한다.(불행히도 안하는곳도 많다.) 위에서 배운 블럭암호화 알고리즘으로 암호화를 한다면, 사이트 관리자들은 비밀번호를 있을것이다. (키를 해당 사이트에서 관리하므로, 키를 알면 복호화가 가능하다.) 정말 기분 나쁘다. 타인이 나의 비밀번호를 안다는것은... 그러면 관리자들도 모르게 암호화를 할려면 어떻게 해야할까?
아주 간단하다. 암호화에 사용하는 자체를 평문 , 비밀번호로 사용하면 된다. 아래 처럼 구현하면 본인만 수가 있는것이다. 암호화 할려는 비밀번호 자체가 역활을 동시에 하는것이다. 한번 구현해보자.

01

public static void main(String[] args) throws Exception {

02

    String password = "mypassword";

 

03

      

04

    byte[] passwordBytes = password.getBytes();

 

05

    int len = passwordBytes.length;

06

    byte[] keyBytes = new byte[16];

 

07

    if (len >= 16) {

08

        System.arraycopy(passwordBytes, 0, keyBytes, 0, 16);

 

09

    } else {

10

        System.arraycopy(passwordBytes, 0, keyBytes, 0, len);

 

11

        for (int i = 0; i < (16 - len); i++) {

12

            keyBytes[len + i] = passwordBytes[i % len];

 

13

        }

14

    }

 

15

      

16

    Key key = generateKey("AES", keyBytes);

 

17

    String transformation = "AES/ECB/PKCS5Padding";

18

    Cipher cipher = Cipher.getInstance(transformation);

 

19

    cipher.init(Cipher.ENCRYPT_MODE, key);

20

      

 

21

      

22

    byte[] plain = password.getBytes();

 

23

    byte[] encrypt = cipher.doFinal(plain);

24

    System.out.println("원문 : " + ByteUtils.toHexString(plain));

 

25

    System.out.println("암호 : " + ByteUtils.toHexString(encrypt));

26

      

 

27

    cipher.init(Cipher.DECRYPT_MODE, key);

28

    byte[] decrypt = cipher.doFinal(encrypt);

 

29

    System.out.println("복호 : " + ByteUtils.toHexString(decrypt));

30

}


  키는 패딩이 안되기 때문에 자체적으로 길이를 맞춰줘야한다. 여기서는 16바이트보다 크면 자르고, 16바이트보다 작으면 입력받는 비밀번호 문자를 반복해서 뒤에 붙여두는식으로 구현하였다
 이런 방식이 귀찮다면 블럭 암호화 방법 대신, MD5 SHA1으로 메시지 해쉬값을 저장해서 값을 비교해도 된다. ( 방식은 복호화가 안된다.) my-sql password() 함수가 SHA1 이용하는데, 다음번에 알아보도록 하자.

 ByteUtils.java

 

 

출처 - http://blog.kangwoo.kr/44


===================================================================================

Invalid AES key length 

[출처] Invalid AES key length|작성자 HIRU



AES 암호화, 복호화 과정에서 발생하는 메시지

 

암호화, 복호화에 사용되는 키의 길이가 맞지 않다는 메시지

 

해결]

키 값은 16, 24, 32 Byte 이다..

 

암호와 키 값을 16글자 나 24글자.. 32 글자로 바꾸어 주면 해결된다


출처 - http://blog.naver.com/PostView.nhn?blogId=by685&logNo=50106891639&categoryNo=25&viewDate=&currentPage=1&listtype=0



===================================================================================


다시 구현 해보기


public class AESTest {

    

public static void main(String [] args) throws Exception {

   

    // 암호 대상 문자열

    String plainString = "패스워드";

    byte[] plainByte = plainString.getBytes();

   

    System.out.println("원문(String) : " + plainString);

   

   

   

    // key 생성. key 길이는 16, 24, 32byte 중에 하나

    String keyString = "keyLength16Byte!";

    byte[] keyByte = keyString.getBytes();

    SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");

   

    // IV 생성. IV 길이는 16, 24, 32byte 중에 하나

    String ivString = "ivLengthIs16Byte";

    byte[] ivByte = ivString.getBytes();

    IvParameterSpec ivSpec = new IvParameterSpec(ivByte);

   

   

   

    // AES 암호화

    String transformation = "AES/CBC/PKCS5Padding";

    Cipher cipherObj = Cipher.getInstance(transformation);

    cipherObj.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

    byte[] encryptByte = cipherObj.doFinal(plainByte);

    String encryptHexString = byteArrayToHexString(encryptByte);


    System.out.println("암호(HexString) : " + encryptHexString);

   

    // AES 복호화

    byte[] encryptHexStringToByteArray = hexStringToByteArray(encryptHexString);

    cipherObj.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

    byte[] decryptByte = cipherObj.doFinal(encryptHexStringToByteArray);

    String decryptString = new String(decryptByte, "UTF-8");

   

    System.out.println("복호(String) : " + decryptString);

   

    }

   

 

    // byte[] to hexString

    public static String byteArrayToHexString(byte[] ba) {

        if (ba == null || ba.length == 0) {

            return null;

        }

         

        StringBuffer sb = new StringBuffer(ba.length * 2);

        String hexNumber;

        

        for (int x = 0; x < ba.length; x++) {

            hexNumber = "0" + Integer.toHexString(0xff & ba[x]);

            sb.append(hexNumber.substring(hexNumber.length() - 2));

        }

        

        return sb.toString();

    }

    

    // hex to byte[]

    public static byte[] hexStringToByteArray(String hex) {

        if (hex == null || hex.length() == 0) {

            return null;

        }


        byte[] ba = new byte[hex.length() / 2];

        for (int i = 0; i < ba.length; i++) {

            ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);

        }

        return ba;

    }

}

[출처] Invalid AES key length|작성자 HIRU

Posted by linuxism
,

FLOSS (치실)은 Free / Libre and Open Source Software의 약자 이며 주석 1] , 자유 소프트웨어 와 오픈 소스 소프트웨어 를 함께 표현하는 용어이다. Free / Open Source Software의 약자를 가지고 FOSS 라고도 불린다.

목차

  [ 숨기기 ] 

FLOSS라는 명칭의 배경 편집 ]

옛부터 자유 소프트웨어 라는 용어는 있었지만, 자유로운 소프트웨어를 취급하는 기업에서 보면 몇 가지 문제점이 있었다. 따라서 1998 년에는 중립적인 용어로 오픈 소스 라는 용어가 만들어지고 많은 사용자 와 개발자, 매스 미디어 에 퍼졌다. 그러나 반면에, 자유 소프트웨어 운동 의 창시자인 리처드 스톨만 , 그 용어가 의도를 엄격하게 나타내지 않는로이를 비난했다 [1] .

그 결과 자유 소프트웨어와 오픈 소스라는 구분 소프트웨어를 모두 포괄하는 표현으로 FOSS (Free / Open Source Software)와 FLOSS를 사용하도록되어 갔다.

FOSS와 FLOSS 편집 ]

Free / Open Source Software 는 영어 의 약자 이다 FOSS은 시간이 지날수록 더 많은 언어로 개념을 전달하기 위해 FLOSS되어 갔다 주석 2] . L "자유로운"를 의미하는 프랑스어 및 스페인어 libre , 이탈리아어 libero 를 나타낸다.

자유 소프트웨어와 오픈 소스의 개념을 만들어낸 진영은 각각의 용어를 만들어 낸 경위도있어, FLOSS 등의 약자를지지하는 입장은 아니다. 그러나 두 진영 사이의 마찰을 바라고있는 것은 아니기 때문에, 양자의 관계를 양호하게이 용어를 환영하고있다. 사실, 자유 소프트웨어의 창시자인 리차드 스톨 공공 장소에서이 약어를 사용한다. 특히 연구 프로젝트 등에서는이 약어를 사용하여 중립성을 유지하고있다 [2] .

2004 년 말에는 FLOSS는 약어, 남아 프리카 공화국 [3] 와 스페인 [4] 브라질 [5] 를 포함한 여러 국가의 영어 공식 문서에서 사용되고있다. 그러나 스페인 포르투갈어로 쓰여진 문서에는이 약어는 사용되지 않고,라고하는 것은 libre 또는 livre 에서 오해가 발생하지 않고 충분히 때문이다.

그러나 개념은 현재 정의되어 있지 않기 때문에, 더 나은 이해를 위해 개념을 명문화하고 설명하는 것이 바람직합니다.


각주 편집 ]

주석 편집 ]

  1. libre 은 프랑스어로 " 자유 의 "의 뜻.
  2. ^ 독일의 "자유로운"는 frei 이기 때문에 FOSS에 이미 들어있다.

출처 편집 ]

  1. Richard M. Stallman "제 6 장"오픈 소스 "가 아니라"자유 소프트웨어 "라고 불러야 할 이유" "자유 소프트웨어와 자유로운 사회 Richard M. Stallman 에세이집"통역 : 주식 회사 롱테일 / 나가 타카 히로, 아스키, 2003 년 5 월 11 일 초판 89 페이지에서 98 페이지. ISBN 4-7561-4281-8 .
  2. Free Software - Free Society!  : 리차드 스톨만 인터뷰, 2004.
  3. Free / Libre and Open Source Software and Open Standards in South Africa : A Critical Issue for Addressing the Digital Divide , National Advisory Council on Innovation (NACI)에 의한다. 2004 년 7 월.
  4. FLOSS deployment in Extremadura, Spain , Interoperable Delivery of European eGovernment Services to public Administrations, Business and Citizens 때문이다. 2003 년 10 월.
  5. Relatório da ONU aponta o Software Livre (FLOSS) como melhor , softwarelivre.org에서. 2004 년 2 월 2 일.

외부 링크 편집 ]

관련 항목 편집 ]





'OpenSource > Common' 카테고리의 다른 글

루씬(Lucene) 개요 및 원리  (2) 2012.09.24
MINA 소개  (0) 2012.09.20
redis - redis 소개  (0) 2012.09.14
부드러운 종신 독재자  (0) 2012.04.08
[현장] “얘기해봐요, 오픈소스란…”  (0) 2012.03.07
Posted by linuxism
,


Jasypt 를 이용한 암호화 방법입니다
Jasypt 를 이용하여 Spring 설정파일의 설정값을 암호화 할 수 있습니다. 


http://www.jasypt.org/ 


다운로드 받습니다. (현재 1.9.0 버젼이 최신입니다.)

* StringEncryptor.java (
 Encoding 소스 )

package com.sample.crypto;

import java.util.ArrayList;
 


import java.util.List;

import org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI;

public class StringEncryptor {

    public static void main(String[] args) {

        List<String> argList = new ArrayList<String>();
        String input = "input=";

        if ( args.length < 1 ) {
            System.out.println("String for encryption must be inserted");
            return;
        }
        else {
            input = input + args[0];
            argList.add(input);
        }

        argList.add("algorithm=PBEWithMD5AndDES");   // 대칭암호화
        argList.add("password=SAMPLE");                  // Key
        argList.add("verbose=false");

        String[] result = new String[argList.size()];

        argList.toArray(result);

        JasyptPBEStringEncryptionCLI.main(result);

    }
}

* 암호화 문자 생성

set classpath=jasypt\1.9.0\jasypt-1.9.0.jar 

java -cp .;%classpathcom.sample.crypto.StringEncryptor {암호화할 문자}


* applicationContext-resource.xml

<bean id="encryptorConfig" 
         class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
        <property name="algorithm" value="PBEWithMD5AndDES" />
        <property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" />
</bean>
     
<bean id="encryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="config" ref="encryptorConfig" />
        <property name="password" value="
 
SAMPLE
 
" />     <!-- 
 
StringEncryptor.java 의 Key
 
 -->

</bean>

     
<bean id="propertyConfigurer" 
         class="org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer">
        <constructor-arg ref="encryptor" />
        <property name="locations">
               <list>
                   <value>classpath:config/${osp.server.type}/applicationSystemConfig.xml</value>
               </list>
        </property>
</bean>

* applicationSystemConfig.xml (ENC로 감싸진 문자가 암호화된 문자임.)

<entry key="mysql.jdbc.driverClassName">core.log.jdbc.driver.MysqlDriver</entry>
<entry key="mysql.jdbc.url">jdbc:mysql://localhost:3306/sample</entry>
<entry key="mysql.jdbc.username">scott</entry>
<entry key="mysql.jdbc.password">ENC(ne3e529X5YPW2IdfL0G0bg==)</entry>
 

* 참고

http://www.jasypt.org/spring3.html 
 


http://blog.teamextension.com/quick-jasypt-spring-3-tutorial-626 
 





출처 - http://hermeslog.tistory.com/139

===================================================================================


프로젝트에서 IBatis 도입을 하려는데, DB 접속 패스워드를 암호화된 파일로만

관리해야한다는 제약이 있어 도입을 늦추고 있었다.

 

IBatis 원 소스를 수정할까 고민하여 구글링을 하는데,

초기화시 다음과 같은 방법으로 설정파일에 든 password 를 엎어칠수가 있었다능..

 

먼저, sqlmapConfig.xml 에 다음과 같이 원하는 항목에 변수를 지정한다.

            .....

            <property name="JDBC.ConnectionURL" value="${url}" />

            <property name="JDBC.Username" value="${username}" />

            <property name="JDBC.Password" value="${password}" />

            .....


SqlMapConfig.xml 을 읽어들이는 초기화 소스에,

위에서 ${password} 지정했던 동일한 key( 예. password )로 아래 Properties 를 세팅한다.


            Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
            String sPassword = decryptPassword();
            Properties properties = new Properties();
            properties.setProperty("password", sPassword);

            client = SqlMapClientBuilder.buildSqlMapClient(reader, properties);

 

decryptPassword() 메소드는 자체적으로 특정파일에 암호화된

DB접속 패스워드를 decrypt 하는 메소드이니,

상황에 따라 적절히 구현하면 되겟고,

이후 Properties에 담아 buildSqlMapClient 에 넘기면 되겠다.


url 이나 username 도 동일한 방법으로 설정이 가능한데. ibatis 소스에 보면 config.xml 파일의 ${xxxxxxx} 패턴의 value 를 Properties 로 replace하도록 되어있군.


mybatis  로 바뀌고는 예전 ibatis repository를 잘 못 찾겠음.

http://code.google.com/p/mybatis/source/browse/

:)


출처 - http://blog.naver.com/olovesun?Redirect=Log&logNo=10037215677

===================================================================================

In reply to this post by Halloweenx8
Hi,
i met this condition once when i had to encrypt my database connection on an desktop application,
the workaround is by put encrypted password + username on a properties file,
and load it on SqlSessionFactoryBuilder class after i decrypt it.


*--------------------- class where i load my properties file and decrypt it -------------*
public class MyBatisSqlSessionFactory {

protected static final SqlSessionFactory FACTORY;

static {
try {

// load my properties file
File file = new File("database.properties");
FileInputStream fileInputStream
= new FileInputStream(file);
Properties properties
= new Properties();
properties
.load(fileInputStream);
fileInputStream
.close();

// put my decrypt username and password on Properties
Properties jdbcProp = new Properties();
EncryptionFactory encryptionFactory
= EncryptionFactory.getFactory();
jdbcProp
.setProperty("JDBC.Password", encryptionFactory.decrypt(properties.getProperty("JDBC.Password")));
jdbcProp
.setProperty("JDBC.Username", encryptionFactory.decrypt(properties.getProperty("JDBC.Username")));

Reader reader
= Resources.getResourceAsReader("com/baculsoft/mybatis/xml/Configuration.xml");
FACTORY
= new SqlSessionFactoryBuilder().build(reader,properties);
} catch (Exception e){
throw new RuntimeException("Fatal Error. Cause: " + e, e);
}
}

public static SqlSessionFactory getSqlSessionFactory() {
return FACTORY;
}
}

*--------------------- my database.properties -------------*
JDBC.Username=7GY1NGTIIkl788aCQqhIck9Hw==
JDBC.Password=5HOxG3c6ovDu77wed3pPMU1weouJqzieCdB


well, it's not pretty but at least it works. :)

On Fri, Dec 31, 2010 at 13:32, Halloweenx8 <[hidden email]> wrote:
<dataSource type="POOLED">
   <property name="driver" value="${driverClassName}" />
   <property name="url" value="${url}" />
   <property name="username" value="${username}" />
   <property name="password" value="${password}" />
</dataSource>

i need to encrypt the database password in this file used by myBatis

Any idea how  would decrypt it using myBatis?

-- 
Regards,


edwin.

출처 -  http://mybatis-user.963551.n3.nabble.com/Encrypting-the-db-password-td2172564.html 










'Framework & Platform > mybatis' 카테고리의 다른 글

useGenerateKeys 사용하기 예제  (0) 2012.05.01
mybatis 3 settings 예제  (0) 2012.04.30
Mybatis selectList 예제  (0) 2012.03.28
mybatis 설치 예제  (0) 2012.03.18
ibatis vs MyBatis  (0) 2012.03.15
Posted by linuxism
,