반응형

하하... 살균제의 유해성이 발표된 지금...

자연식 가습기.. 가열식 가습기...

고민...

아무래도 아기가 있으니 자연스럽게 자연식으로 솔리고...

LG전자 휘센 LAW-B040PP

이넘으로 생각중...

http://shopping.naver.com/detail/detail.nhn?cat_id=00050503&nv_mid=5953821718&tc=4

 
 

차일드락 기능이 가장 꽃힘 !

울 애기는 이제 돌 지났는데 버튼을 보면 환장함 -_-ㅋ

문제는 가격...

아 고민중...

25만냥인디...

어디 싸게 파는데 없냥... 
반응형

'Private' 카테고리의 다른 글

Magicar AF BRONZE (매직카 브론즈)  (0) 2011.11.30
압력 밥솥 구매 ... 예정  (0) 2011.11.26
2012 피셔 프라이스 뉴 러닝홈  (0) 2011.11.16
OPENSSL 패스워드 변경  (0) 2011.10.20
존 더 리퍼 john-mmx  (1) 2011.09.28
반응형

주제 : egovframe 환경구성과 HTML5 개발
내용 : 전자정부 표준프레임워크 개요, egovframe 환경 구성 및 샘플 코드 리뷰
발표자 : 허광남 팀장님... www.okjsp.pe.kr 만드신분 !

제목과 같이 정기 기술 세미나는 14차이나

어제 처음으로 참석했다

사실 egovframe (이가브프레임워크)로 읽는 이놈에 대해 관심이 생겨 찾아간 세미나였음.

간단하게 어제 들은 내용을 정리한다...

강의는 졸립지 않을정도 재미가 있었고,

허팀장님의 콧수염(?)이 멋져보였어요~

egovframe을 시작하기 위해서는

http://www.egovframe.go.kr/

행정안전부 전자정부 프레임 워크 사이트에 가자 !

상단의 메뉴중 가이드 -> 초보자 가이드로 시작함 ~

사실,

표준 프레임워크 개인적으로 무지 생소하기도 하지만,

허 팀장님이 말씀해 주신건... 전부다 알려고 하면 힘들꺼다... 필요한것은 그때 그때 찾아서 하면된다 !

따라 해보기를 계속 권장해 주셨음...

사실 jdk 1.6이상으로 설치하고  visual VM 관련도 같이 알려주었으면 조금더 좋았으리라 생각한다...(리스스 조회 및 관리 등)

난 뭐... 개발보다는 인프라 담당이다 보니... 크크...

관심 같는것도 신기하긴 하지만 뭐든지 알면 도움이 되는거니깐...


* 알아야 할 사항 (숫자는 단계별로 생각하면 됨)
   1. 전자정부 프레임워크 개요
   2,3 maven(빌드도구), Elipse(통합개발환경)
   3,4 SVN(버젼관리) Hudson(형상 유지 관리) => CI(Contiguous Integration)라고 부름..
   5 FrameWork (springFrameWork, Mybatis(마이바티스-> 아이바티스가 이름을 바꿨다고 함.)/iBatis(아이바티스), jQuery)

maven(메이븐)은 pom.xml이 제일 중요함
pom : Project Object Model

참고로

JUnit 를 강조하셨다... TEST 자동화를 할려면 꼭 필요하다고 했다

뭐.. 잠깐 보여줬지만, expect...예상되는... 결과와 실행결과를 비교하여 보여주기도 했고

Rerun 이라는 기능을 사용해 바로 결과를 보여주었다...

자...

본인이 초보자라면

무조건 ! 3번이상 행안부 표준 프레임 워크 초보자 가이드를 3번이상 똑같이(?) 해보라

또한 설치가 D라면... 크크... 디스크 새로 사서 꽃아라(?) 라는 의미심장한 얘길 해주셨다..

뭐...

VMPlayer(가상 window 시스템으로 VMWare에서 나오는 것인데.. 작은 기능에 개인 무료로 알고있다...[가물...])으로 가상으로 디스크 2개인것 처럼 꾸며도 괜찮을꺼 같다...

jQuery 와 센차(?? 처음들봄...) 비교하면

jQuery 는 모바일 상관없이 UI가 일정하며, 접근이 쉽고, 고 수준으로 가야 javascript를 만남 그러나 ! 비교적 스킨이 없으며,  UI 콘트롤이 힘듬반면
센차는... UI 뛰어나고, 자바스크립트를 열쉬미 해야함.

즉, 공공기관같은 곳에 표준을 맞추려면 jQuery가 좋다는 것이다

위에 까지가 egovframe 내용이었고...

사실 html5는 관심 없는 분야라...

들었떤 내용을 대략적으로 정리해본다...

아직 beta 버젼이고... 정식 1.0은 없고

html5 개발시... www.html5test.com 사이트에서 점수가 높은 브라우져(현재는 구글)을 쓰라

firefox 를 사용할 때는

아래의 부가기능을 쓰기를 추천.
1. firebug(파이어버그) : 각 dom 객체등 요소들을 조작 가능한 녀석...
    브라우져 상에서 수정할 내용의 마우스 우클릭 -> 요소검사 수행
    net 기능을 사용하면 각 요소들 loading (Server <--> Client PC) 호가인 가능

2. selenium(쉘레니움) : www.seleniumhq.org 이나.. 부가기능 검색하면 너무 많이 나와서.. 뭘 설치할지 모름 -_-ㅋ
    기능은 브라우져 상에서 했던 작업들을 기억하고 반복적으로 수행가능함.
    즉, 어떤 요소를 수정하고 똑같은 작업을 시행해 볼수 이씀.... 또한 ! 원격 분산 테스트도 가능(?)하다고 함.

about:mozilla : 모질라 역사가 나옴.

신기한건... html5에서는 browser에서 select문을 날릴수 있다는 것이었다...

보안에는 어떤지 궁금하기도 했다...

뭐.. 중간 RSE 기능에 대해서도 나왔지만... 난 이미 사용중이었고...

아쉬운 점은

질의 응답이 없다는 거다....

하하하...

다음에 또 들어야 겟음...
반응형
반응형

 

출처 : http://blog.kangwoo.kr/49

인터넷 뱅킹을 하시는 분이라면 대부분 공인인증서를 가지고 있다. 이 공인인증서를 가지고 전자서명을 해보도록하자(전혀 쓸데없는 일이긴 하다 ^^;)
필자의 경우 yessign에서 발급한 은행용 공인인증서를 가지고 있는데 그 경로는 C:\NPKI\yessign\USER\아래폴더... 에 위치해 있다.
그 디렉토리에 보면 CaPubs, signCert.der, signPri.key 세 파일이 존재한다.
CaPubs은 무슨 파일인지 잘 모르겠다. signCert.der는 공인 인증서 파일이고, signPri.key는 개인키 파일이다.
(der은 인증서 저장시 바이너르 형태로 저장하기 위한 포맷이고, pem은 문자열로 표현가능한 데이터로 인코딩(BASE64같은..)한 포맷이다.)
한국정보보호진흥원(http://www.rootca.or.kr/kcac.html)의 기술규격을 참조해보면, 현재 사용하는 공인인증서는 RFC3280을 준수하여, 전자서명인증체계에서 사용하는 정수2를 갖는 X.509 v3을 사용하고 있다고 한다.

1. 공개키 가져오기.
- 자바에서 X.590를 지원해주니 간단히 사용해보자.

01 package test.security;
02
03 import java.io.File;
04 import java.io.FileInputStream;
05 import java.io.IOException;
06 import java.security.cert.CertificateFactory;
07 import java.security.cert.X509Certificate;
08
09 public class CertificateTest1 {
10
11 public static void main(String[] args) throws Exception {
12 X509Certificate cert = null;
13 FileInputStream fis = null;
14 try {
15 fis = new FileInputStream(new File("C:/signCert.der"));
16 CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
17 cert = (X509Certificate) certificateFactory.generateCertificate(fis);
18 } finally {
19 if (fis != null) try {fis.close();} catch(IOException ie) {}
20 }
21 System.out.println(cert);
22 System.out.println("-----------------");
23 System.out.println(cert.getPublicKey());
24 }
25 }

실행해보면 아래처럼 인증서에 대한 정보를 볼 수 있을것이다.(보안 관계상 많은 부분을 생략하겠다.)

[
[
Version: V3
Subject: CN=누굴까(RangWoo)0000000000000000, OU=XXX, OU=personalXXX, O=yessign, C=kr
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

Key: Sun RSA public key, 1024 bits
... 생략 ...
[7]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
[accessMethod: 1.3.6.1.5.5.7.48.1
accessLocation: URIName: http://ocsp.yessign.org:4612]
]
... 생략 ...
Sun RSA public key, 1024 bits
modulus: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
public exponent: 00000

당연히, V3 버젼을 사용하고 서명 알고리즘은 SHA1withRSA을 사용한다. SHA1withRSA 옆에 보면 OID란 놈이 있다.
OID란 Object IDentifier의 약어로서 객체식별체계정도로 이해하면 되겠다. 즉, OID의 값이 1.2.840.113549.1.1.5이면 SHA1withRSA란 의미이다.
http://www.oid-info.com/ 사이트에 가서 1.2.840.113549.1.1.5 값을 입력하면 아래와 같은 값을 얻을 수 있다.

그리고 중간쯤에 ocsp(Online Certificate Status Protocol)라고 실시간으로 인증서 유효성 검증을 할수 있는 정보도 나온다.
좀더 내려가보면 공개키부분이 나오는데, 이놈이 우리가 사용할 부분이다. cert.getPublicKey() 메소드를 이용하면 직접 공개키를 가져올 수 있다.

2. 개인키 가져오기
- 공개키는 거의 날로 먹었는데, 개인키란 놈은 만만하지가 않다.
- 기본적으로(?)는 PKCS#8를 이용해서 개인키를 저장하는데, 국내 공인인증서에 사용하는 개인키 파일는 암호화(?)해서 저장한다.
PKCS#5(Password-Based Cryptography Standard)의 PBKDF1(Password-Based Key Derivation Function), PBES1(Password-Based Encryption Scheme)를 이용한다는 것이다.
여기까지는 별 문제가 없는데, 데이터 암호화를 할때 국내에서만 사용하는 SEED란 블럭암호화 알고리즘를 사용한다는것이다.
즉, 기본적으로 제공이 안되므로 직접 구현을 해야한다.
뭔소리인지 이해가 안가면 한국정보보호진흥원(http://www.rootca.or.kr/)의 암호 알고리즘 규격(KCAC.TS.ENC)를 한번 읽어보자. (사실 읽어봐도 이해가 안가지만... ^^;)
간단히 설명을 하자면, PBES(Password-Based Encryption Scheme) 즉 패스워드 기반의 키 암호화 기법을 사용하겠다는 것이다. 암호화 할때 필요한게 비밀키이다. 이 키는 해당 알고리즘에 맞는 바이트 배열로 보통 사용을 하는데, 이것을 사람이 쉽게 인식할 수 있는 패스워드로 사용하겠다는것이다.
뭐 필자처럼 무식하게 "hello123".getBytes(); 를 사용해서 키로 사용할 수 있지만, 모양새가 안좋아보인다는것이다. 그래서 "hello123" 문자열을 가공해서 멋진(?) 키로 만들어 사용한다는 것이다.
이 가공하는 함수가 PBKDF(Password-Based Key Derivation Function)이다. 그리고 이 함수를 이용해서 비밀키를 생성해서 암호화/복화하는 하는 구조를 PBES라고 한다.
자바에서 기본적으로 "PBEWithMD5AndDES", "PBEWithSHA1AndDESede" 등의 알고리즘을 제공해준다.
Security.getProviders(); 메소드를 이용해서, Provider 정보를 출력해보면 지원하는 알고리즘을 알 수 있다.
01 package test.security;
02
03 import java.security.Provider;
04 import java.security.Security;
05
06 public class ProviderInfo {
07
08 public static void main(String[] args) {
09 Provider[] providers = Security.getProviders();
10 for (int i = 0; i < providers.length; i++) {
11 String name = providers[i].getName();
12 String info = providers[i].getInfo();
13 double version = providers[i].getVersion();
14 System.out.println("--------------------------------------------------");
15 System.out.println("name: " + name);
16 System.out.println("info: " + info);
17 System.out.println("version: " + version);
18
19 for (Object key : providers[i].keySet()) {
20 System.out.println(key + "\t"+ providers[i].getProperty((String)key));
21 }
22 }
23 }
24 }

그런데 불행히도 "PBEWithSHA1AndSeed"같은 알고리즘은 없는거 같다. 어떻게 해야할까? 당연히 삽~을 들어야한다.(아~~ 또 무덤을 파는구나 ㅠㅠ)
일단 파일의 구조를 파악해서 필요한 정보를 읽어와야한다.(ASN. 1으로 인코딩되어있다.)
다행히도 PKCS#8로 정의하고 있는 구조를 읽을 수 있는 EncryptedPrivateKeyInfo 클래스가 존재해서 한결 쉽게 작업을 할 수 있다
EncryptedPrivateKeyInfo 클래스를 사용해서 정보를 읽어오자. 사용하는 알고리즘을 출력해 보자.
01 // 1. 개인키 파일 읽어오기
02 byte[] encodedKey = null;
03 FileInputStream fis = null;
04 ByteArrayOutputStream bos = null;
05 try {
06 fis = new FileInputStream(new File("C:/signPri.key"));
07 bos = new ByteArrayOutputStream();
08 byte[] buffer = new byte[1024];
09 int read = -1;
10 while ((read = fis.read(buffer)) != -1) {
11 bos.write(buffer, 0, read);
12 }
13 encodedKey = bos.toByteArray();
14 } finally {
15 if (bos != null) try {bos.close();} catch(IOException ie) {}
16 if (fis != null) try {fis.close();} catch(IOException ie) {}
17 }
18
19 System.out.println("EncodedKey : " + ByteUtils.toHexString(encodedKey));
20
21 // 2. 개인카 파일 분석하기
22 EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(encodedKey);
23 System.out.println(encryptedPrivateKeyInfo);
24 System.out.println(encryptedPrivateKeyInfo.getAlgName());

필자의 경우 "1.2.410.200004.1.15"란 값을 얻을 수 있었다. 나머지 파라메터 정보는 불행히도 제공을 안해줘서 직접 처리해야한다.
"1.2.410.200004.1.15" 어디서 많이 본 형식이다. 그렇다. OID이다. 사이트(http://www.oid-info.com/)가서 조회를 해보자.
"Key Generation with SHA1 and Encryption with SEED CBC mode" 란다.

한국정보보호진흥원(http://www.rootca.or.kr/)의 암호 알고리즘 규격(KCAC.TS.ENC)에서도 해당 OID에 대한 정보를 알 수 있다.

즉, 두 번째 방법이라는 것인데, DK의 값을 이용해서 해쉬값을 만든다음 그 값을 IV(초기화 벡터)로 사용하라는 것이다.
여기서 DK란 PBKDF를 사용해서 만든 추출키를 의미한다. 그렇다면 먼저 추출키를 만들어보자.

위의 설명대로 해당 함수를 구현해보자.
salt와 iteration count가 필요하다.
salt는 공인인증서를 발급할때마다 랜덤하게 생성되는것으로, 블특정다수의 사전(Dictionary) 공격을 방지하는 역할을 한다.(21-28바이트 사이의 8바이트를 사용함)
iteration count는 비밀키 생성을 위해 해쉬함수를 몇번 반복할 것인가를 나타낸다. (31-32바이트 사이의 2바이트를 사용함)
1 byte[] salt = new byte[8];
2 System.arraycopy(encodedKey, 20, salt, 0, 8);
3 System.out.println("salt : " + ByteUtils.toHexString(salt));
4 byte[] cBytes = new byte[4];
5 System.arraycopy(encodedKey, 30, cBytes, 2, 2);
6 int iterationCount = ByteUtils.toInt(cBytes);
7 System.out.println("iterationCount : " + ByteUtils.toHexString(cBytes));
8 System.out.println("iterationCount : " + iterationCount);

그럼 PBKDF1을 구현해보자. RFC2898(http://www.ietf.org/rfc/rfc2898.txt)을 보면 아래처럼 설명이 나와있다.
5.1 PBKDF1

   PBKDF1 applies a hash function, which shall be MD2 [6], MD5 [19] or
   SHA-1 [18], to derive keys. The length of the derived key is bounded
   by the length of the hash function output, which is 16 octets for MD2
   and MD5 and 20 octets for SHA-1. PBKDF1 is compatible with the key
   derivation process in PKCS #5 v1.5.

   PBKDF1 is recommended only for compatibility with existing
   applications since the keys it produces may not be large enough for
   some applications.

   PBKDF1 (P, S, c, dkLen)

   Options:        Hash       underlying hash function

   Input:          P          password, an octet string
                   S          salt, an eight-octet string
                   c          iteration count, a positive integer
                   dkLen      intended length in octets of derived key,
                              a positive integer, at most 16 for MD2 or
                              MD5 and 20 for SHA-1

   Output:         DK         derived key, a dkLen-octet string

   Steps:

      1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
         "derived key too long" and stop.

      2. Apply the underlying hash function Hash for c iterations to the
         concatenation of the password P and the salt S, then extract
         the first dkLen octets to produce a derived key DK:

                   T_1 = Hash (P || S) ,
                   T_2 = Hash (T_1) ,
                   ...
                   T_c = Hash (T_{c-1}) ,
                   DK = Tc<0..dkLen-1>

      3. Output the derived key DK.
설명대로 구현해주자. 피곤한 관계상 SHA1을 사용해서 20바이트의 추출키만을 반환하도록 만들었다.
01 public static byte[] pbkdf1(String password, byte[] salt, int iterationCount) throws NoSuchAlgorithmException {
02 byte[] dk = new byte[20];
03 MessageDigest md = MessageDigest.getInstance("SHA1");
04 md.update(password.getBytes());
05 md.update(salt);
06 dk = md.digest();
07 for (int i = 1; i < iterationCount; i++) {
08 dk = md.digest(dk);
09 }
10 return dk;
11 }
12 }

해당 함수를 사용해서 추출키(DK) 초기화 벡터(IV)를 만들어 보자.
01 String password = "password";
02
03 // 추출키(DK) 생성
04 byte[] dk = pbkdf1(password, salt, iterationCount);
05 System.out.println("dk : " + ByteUtils.toHexString(dk));
06
07 // 생성된 추출키(DK)에서 처음 16바이트를 암호화 키(K)로 정의한다.
08 byte[] keyData = new byte[16];
09 System.arraycopy(dk, 0, keyData, 0, 16);
10
11 // 추출키(DK)에서 암호화 키(K)를 제외한 나머지 4바이트를 SHA-1
12 // 으로 해쉬하여 20바이트의 값(DIV)을 생성하고, 그 중 처음 16바이트를 초기
13 // 벡터(IV)로 정의한다.
14 byte[] div = new byte[20];
15 byte[] tmp4Bytes = new byte[4];
16 System.arraycopy(dk, 16, tmp4Bytes, 0, 4);
17 div = SHA1Utils.getHash(tmp4Bytes);
18 System.out.println("div : " + ByteUtils.toHexString(div));
19 byte[] iv = new byte[16];
20 System.arraycopy(div, 0, iv, 0, 16);
21 System.out.println("iv : " + ByteUtils.toHexString(iv));

당연히 password 변수에는 공인인증서 암호를 입력해야한다. 안그러면 에러가 난다.
이제 고지가 눈앞에 보인다. 남은것은 SEED를 이용해서 복화만 하면 되는것이다. SEED 구현 + CBC 운용모드 구현을 직접하려면 정신적인 데미지가 커질 수 있으므로, 만들어놓은것을 가져다 쓰겠다.
Bouncy Castle Crypto APIs(http://www.bouncycastle.org/)를 감사하는 마음으로 가져다 쓰자.
%JAVA_HOME%/jre/lib/ext에 해당 jar파일을 복사한 다음, %JAVA_HOME%/jre/lib/security/java.security 파일에
security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider
을 추가해서 사용할 수 있지만, 귀찮은 관계로 그냥(?) 사용하겠다.
1 // 3. SEED로 복호화하기
2 BouncyCastleProvider provider = new BouncyCastleProvider();
3 Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding", provider);
4 Key key = new SecretKeySpec(keyData, "SEED");
5 cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
6 byte[] output = cipher.doFinal(encryptedPrivateKeyInfo.getEncryptedData());

이젠 해당 데이터로 개인키를 생성만 해주면 된다.
1 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(output);
2 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
3 RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey)keyFactory.generatePrivate(keySpec);
4 System.out.println(privateKey);
패스워드를 일치여부는 PBES에서 정의한 패딩이 존재하는지 여부로 판단한다. 만약 잘못된 패스워드라면
Exception in thread "main" javax.crypto.BadPaddingException: pad block corrupted
같은 에러가 발생할것이다.


그럼 마지막으로 공인인증서의 공개키와 개인키를 가지고 어제 해본 전자서명을 한번 해보자.
001 package test.security;
002
003 import java.io.ByteArrayOutputStream;
004 import java.io.File;
005 import java.io.FileInputStream;
006 import java.io.IOException;
007 import java.security.Key;
008 import java.security.KeyFactory;
009 import java.security.MessageDigest;
010 import java.security.NoSuchAlgorithmException;
011 import java.security.PrivateKey;
012 import java.security.PublicKey;
013 import java.security.Signature;
014 import java.security.cert.CertificateFactory;
015 import java.security.cert.X509Certificate;
016 import java.security.interfaces.RSAPrivateCrtKey;
017 import java.security.spec.PKCS8EncodedKeySpec;
018
019 import javax.crypto.Cipher;
020 import javax.crypto.EncryptedPrivateKeyInfo;
021 import javax.crypto.spec.IvParameterSpec;
022 import javax.crypto.spec.SecretKeySpec;
023
024 import kr.kangwoo.util.ByteUtils;
025
026 import org.bouncycastle.jce.provider.BouncyCastleProvider;
027
028 import com.jarusoft.util.security.SHA1Utils;
029
030 public class CertificateTest {
031
032 public static void main(String[] args) throws Exception {
033 String msg = "하늘에는 달이 없고, 땅에는 바람이 없습니다.\n사람들은 소리가 없고, 나는 마음이 없습니다.\n\n우주는 죽음인가요.\n인생은 잠인가요.";
034 PublicKey publicKey = getPublicKey("C:/signCert.der");
035 PrivateKey privateKey = getPrivateKey("C:/signPri.key");
036
037 // 전자서명하기
038 Signature signatureA = Signature.getInstance("SHA1withRSA");
039 signatureA.initSign(privateKey);
040 signatureA.update(msg.getBytes());
041 byte[] sign = signatureA.sign();
042 System.out.println("signature : " + ByteUtils.toHexString(sign));
043
044 // 전사서명 검증하기
045 String msgB = msg;
046 Signature signatureB = Signature.getInstance("SHA1withRSA");
047 signatureB.initVerify(publicKey);
048 signatureB.update(msgB.getBytes());
049 boolean verifty = signatureB.verify(sign);
050 System.out.println("검증 결과 : " + verifty);
051 }
052
053 public static PublicKey getPublicKey(String file) throws Exception {
054 X509Certificate cert = null;
055 FileInputStream fis = null;
056 try {
057 fis = new FileInputStream(new File(file));
058 CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
059 cert = (X509Certificate) certificateFactory.generateCertificate(fis);
060 } finally {
061 if (fis != null) try {fis.close();} catch(IOException ie) {}
062 }
063 System.out.println(cert.getPublicKey());
064 return cert.getPublicKey();
065 }
066
067 public static PrivateKey getPrivateKey(String file) throws Exception {
068 // 1. 개인키 파일 읽어오기
069 byte[] encodedKey = null;
070 FileInputStream fis = null;
071 ByteArrayOutputStream bos = null;
072 try {
073 fis = new FileInputStream(new File(file));
074 bos = new ByteArrayOutputStream();
075 byte[] buffer = new byte[1024];
076 int read = -1;
077 while ((read = fis.read(buffer)) != -1) {
078 bos.write(buffer, 0, read);
079 }
080 encodedKey = bos.toByteArray();
081 } finally {
082 if (bos != null) try {bos.close();} catch(IOException ie) {}
083 if (fis != null) try {fis.close();} catch(IOException ie) {}
084 }
085
086 System.out.println("EncodedKey : " + ByteUtils.toHexString(encodedKey));
087
088 // 2. 개인카 파일 분석하기
089 EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(encodedKey);
090 System.out.println(encryptedPrivateKeyInfo);
091 System.out.println(encryptedPrivateKeyInfo.getAlgName());
092
093 byte[] salt = new byte[8];
094 System.arraycopy(encodedKey, 20, salt, 0, 8);
095 System.out.println("salt : " + ByteUtils.toHexString(salt));
096 byte[] cBytes = new byte[4];
097 System.arraycopy(encodedKey, 30, cBytes, 2, 2);
098 int iterationCount = ByteUtils.toInt(cBytes);
099 System.out.println("iterationCount : " + ByteUtils.toHexString(cBytes));
100 System.out.println("iterationCount : " + iterationCount);
101
102
103 String password = "password";
104
105 // 추출키(DK) 생성
106 byte[] dk = pbkdf1(password, salt, iterationCount);
107 System.out.println("dk : " + ByteUtils.toHexString(dk));
108
109 // 생성된 추출키(DK)에서 처음 16바이트를 암호화 키(K)로 정의한다.
110 byte[] keyData = new byte[16];
111 System.arraycopy(dk, 0, keyData, 0, 16);
112
113 // 추출키(DK)에서 암호화 키(K)를 제외한 나머지 4바이트를 SHA-1
114 // 으로 해쉬하여 20바이트의 값(DIV)을 생성하고, 그 중 처음 16바이트를 초기
115 // 벡터(IV)로 정의한다.
116 byte[] div = new byte[20];
117 byte[] tmp4Bytes = new byte[4];
118 System.arraycopy(dk, 16, tmp4Bytes, 0, 4);
119 div = SHA1Utils.getHash(tmp4Bytes);
120 System.out.println("div : " + ByteUtils.toHexString(div));
121 byte[] iv = new byte[16];
122 System.arraycopy(div, 0, iv, 0, 16);
123 System.out.println("iv : " + ByteUtils.toHexString(iv));
124
125 // 3. SEED로 복호화하기
126 BouncyCastleProvider provider = new BouncyCastleProvider();
127 Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding", provider);
128 Key key = new SecretKeySpec(keyData, "SEED");
129 cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
130 byte[] output = cipher.doFinal(encryptedPrivateKeyInfo.getEncryptedData());
131
132 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(output);
133 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
134 RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey)keyFactory.generatePrivate(keySpec);
135 System.out.println(privateKey);
136 return privateKey;
137
138 }
139
140 public static byte[] pbkdf1(String password, byte[] salt, int iterationCount) throws NoSuchAlgorithmException {
141 byte[] dk = new byte[20]; // 생성이 의미가 없지만 한눈에 알아보라고 20바이트로 초기화
142 MessageDigest md = MessageDigest.getInstance("SHA1");
143 md.update(password.getBytes());
144 md.update(salt);
145 dk = md.digest();
146 for (int i = 1; i < iterationCount; i++) {
147 dk = md.digest(dk);
148 }
149 return dk;
150 }
151 }



반응형
반응형

 
 ADOBE ACROBAT 8 Professional 에서
 
주석 기능을 활용한 업무 협업

Adobe Acrobat의 주석 기능을 활용하여 하나의 업무를 어떤 식으로 협업하여 활용할 수 있는지를 중심으로 설명하고자 한다.

네트워크가 발달된 오늘날, 필자를 포함한 많은 사람이 업무를 같은 장소에서 하지 않고 각자의 사무실 혹은 재택근무 등 다양한 곳에서 한 업무를 협업하여 진행한다. 이에 Adobe Acrobat으로 문서 검토를 관리해 지연, 분실되거나 업무에 차질이 생기지 않도록 하기 위한 방안으로 주석 기능을 활용하는 방안에 대해 설명하고자 한다.

문서 협업 작업을 위한 순서는 다음과 같다.
  1. 작업문서 메일전송

  2. 작업문서 검토 (주석 도구를 활용한 주석추가)

  3. 작업문서 재 전송

  4. 작업문서 결합

  5. 작업문서 검토 관리
위 5단계 작업 과정을 통해 Adobe Acrobat을 활용한 문서 공동 작업 과정을 설명하겠다.



1. 작업문서 메일전송

공동 작업할 pdf 문서를 대상자들에게 전송한다.
<그림 1>과 같이 Adobe Acrobat 메뉴 중 주석에 ‘전자메일 검토용으로 첨부'를 클릭한 후
<그림 2>, <그림 3>과 같이 작업한다.

 
<그림 1> 검토파일 메일 보내기 화면 <그림 2> 검토대상 이메일 추가 화면


<그림 3> 초대장 미리 보기 화면



2. 작업문서 검토


이제 공동 작업할 문서 전송이 끝났으니 문서를 검토해보자. 이메일로 전송된 pdf 문서가 열리면 주석 도구 모음에 두 가지 도구가 나타나고 문서에 권한이 부여되어 있으므로 프로그램 창의 상단 도구 모음에 ‘사용자 정의도구 모음 옵션'이 보이고, 여기에 있는 메뉴를 클릭해 도구 모음을 추가할 수 있다. 다른 도구 모음을 추가하는 방법은 Adobe Acrobat의 도구 모음에서 ‘사용자 정의 도구 모음' 단추를 클릭하고 필요한 도구를 추가, 확인한다. <그림 4>


<그림 4> 다른 도구 추가 팝업 창

일단 주석 작업에 많이 쓰이는 기능들을 <그림 5>에 나오는 메뉴 순서에 따라 간략하게 설명하겠다.


<그림 5> 주석 및 마크업 메뉴 화면

스티커 노트: 보통 다른 주석 도구들보다 많이 사용하는 도구로 문서를 클릭하면 팝업 창이 뜨고 입력을 시작하면 텍스트가 삽입된다. 페이지를 클릭해서 저장하는데 이때 페이지에 작은 노트 아이콘이 생기고 다시 이를 클릭하면 노트 팝업 창이 뜬다.


텍스트 편집:
  • 텍스트 삽입: 문서의 텍스트 사이를 클릭 후 입력한다. 내용이 팝업 주석 상자에 삽입된다.

  • 텍스트 삭제: ‘텍스트 편집' 도구를 이용하여 삭제할 텍스트를 선택하고 delete를 누른다. 이때 텍스트의 한가운데 빨간줄이 생긴다.

  • 텍스트 교체: ‘텍스트 편집' 도구를 이용하여 텍스트 선택 후 새 텍스트를 입력한다. 교체할 텍스트는 ‘교체텍스트' 창에 입력되고, 선택한 텍스트에는 줄이 그어지고 삽입 아이콘이 나타난다. 이때 팝업 창이 보이지 않을 경우 마우스를 해당 위에 움직이면 대체 텍스트가 보인다.
<그림 6>은 주석 및 마크업 도구를 활용하여 주석을 테스트한 화면이다.


<그림 6> 주석 및 마크업 테스트



3. 작업문서 재전송

편집과 주석 추가 작업이 끝나면 결과를 이메일로 전송을 해야 된다. <그림 5> 주석 및 마크업 메뉴에서 마지막 메뉴 ‘주석 보내기' 버튼을 클릭해 처음 작업 요청 메일을 보냈던 사람에게 되돌려 보낼 수 있다. 이때 주석이 첨부되면서 전송된다.


<그림 7> 주석 보내기



4. 작업문서 결합

공동 작업을 요청한 사람들이 이메일을 보내오면 그 문서를 Adobe Acrobat을 이용하여 주석과 마크업을 병합하는 작업을 한다. 공동 작업자가 보내온 첨부 문서 pdf 파일을 클릭하면 <그림 8> 과 같은 팝업 창이 뜨고 ‘예'를 눌러 병합을 한다.


<그림 8> 주석 병합 확인



5. 작업문서 검토 관리

주석 병합작업이 마무리되면 처음 이메일을 보낸 사람은 초기 작업을 했던 파일을 Adobe Acrobat의 ‘검토 추적기'를 통해 누가 어떤 작업을 했는지 확인하고 관리할 수 있다. Adobe Acrobat 메뉴의 ‘검토 및 주석' 메뉴를 클릭하고 ‘검토 추적기' 메뉴를 선택하면 <그림 9>와 같은 별도의 팝업 창이 뜬다.


<그림 9 > 검토 추적기 화면

검토 작업이 마무리되면 새로운 PDF를 만든 후, 모든 검토자에게 재전송 후 승인을 받으면 모든 작업이 끝난다.




전자 서명을 이용한 문서 보안을 적용한 문서 배포

완성된 문서를 본사에 보고하면 되는데, 이때 내가 보고하는 문서가 유출되거나 변경된 문서가 보고되면 안 된다. 이럴 경우 Adobe Acrobat의 ‘디지털 ID'라는 것을 활용하여 전달할 수 있다.

Adobe Acrobat은 공개키 기반구조(PKI)라는 방식을 채택하고 있다. Adobe Acrobat을 이용하여 ‘디지털 ID'를 하게 되면 이때 공개키와 개인키 두 개가 만들어진다. 개인 키는 서명을 발행한 본인이 갖고 있고 공개키는 다른 사람들과 공유한다. 즉 다른 사람이 문서에 포함된 공개키를 갖고 있으면 그 사람과 정보를 공유할 수 있다.




Adobe Acrobat 을 이용해서 서명을 추가 해보자

1. Adobe Acrobat의 ‘서명 작업도구'를 선택하고 ‘서명 삽입'을 선택한다. 그러면 서명 방법을 알려주는 팝업 창이 뜰 것이다. <그림 10>


<그림 10> 서명 삽입

확인을 선택하고 페이지 위로 마우스를 서명할 곳으로 움직인 후 서명을 추가할 만큼 드래그한 후 마우스를 놓는다. 그러면 ‘디지털 ID' 추가 대화 상자가 <그림 11>처럼 뜬다.


<그림 11> 디지털 ID 추가 상자 1


<그림 12> 디지털 ID 추가 2

2. ‘디지털 ID' 추가 대화상자 그림에서 디지털 ID를 처음 작성하는 사람은 세 번째 옵션을 사용하고, 서명 파일이 이미 있는 사람은 ‘기존 파일 찾기'를 선택하고 다름을 클릭한다.

3. [그림 12]에 보이는 찾아보기 버튼 클릭 후 서명 파일을 선택한다. 그리고 암호 필드에 암호 입력 후 패스워드를 입력하고 다름 버튼을 누른다.

 
<그림 13> 문서 서명  <그림 14> 서명 확인 화면

4. [그림 13]의 문서 서명 창이 뜨면 암호를 입력하고 서명 버튼을 누르면 처음 마우스로 위치를 정한 곳에 서명이 생긴다. <그림 14> 참조

이렇게 해서 주석을 활용한 문서 협업 과정을 알아봤고, 그리고 완성된 문서를 Adobe Acrobat의 디지털 서명을 통해 전달하는 방법까지 확인했다. 아직 국내에서는 디지털 서명을 통한 문서확인을 많이 사용하고 있지 않지만 추후 중요한 문서를 주고 받는 경우가 생긴다면 한번쯤은 사용해 볼만한 가치가 있다고 생각한다.

 

출처 : http://www.acrobatpdf.com/tip/detail_02.asp?id=17&gotopage=7&code=
반응형

+ Recent posts