2016년 12월 19일 월요일

AES 암복호화 보완, (AES/CBC/PKCS5Padding 방식으로)

특정 DB컬럼의 값을 암호화하여 저장하라는 회사의 아키텍쳐 요건을 만족시키기 위해서 AES로 암호화하여 사용하고 있었다. 그런데 기존 방식이 AES/ECB/PKCS5Padding를 사용하고 있었는데 ECB가 문제가 되서 AES/CBC/PKCS5Padding로 변경하는 작업을 진행했다.
 

1.
암호화로 사용할 키는 KeyGeneratorSecureRandom으로 생성한다.

```
KeyGenerator generator = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom();
generator.init(128, random);
Key secureKey = generator.generateKey();

System.out.println(Base64.encodeBase64String(secureKey.getEncoded()));
```

2.
같은 문자열도 암호화할때마다 다른 문자열을 만들어내기 위해서 IV값을 랜덤하게 만들어준다.

```
/**
* 랜덤하게 IV 생성
*
* 같은 평문도 암호화할 때마다 암호문을 다르게 만들어 낸다.
* @return 랜덤하게 생성된 IvParameterSpec
*/
private static IvParameterSpec getRandomIvParameterSpec() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
```

3.
IV값과 암호키로 암호화한 값을 합쳐야 하는데 java byte concat으로 검색해보니 무려 자바 System 클래스에 배열복사가 있었다!

```
// IV + 암호문으로 출력할 Byte를 붙인다.
byte[] ivcipherByte = new byte[16 + cipherByte.length];
System.arraycopy(iv.getIV(), 0, ivcipherByte, 0, 16);
System.arraycopy(cipherByte, 0, ivcipherByte, 16, cipherByte.length);
```

4.
다시 복호화할때는 입력된 byte를 IV와 암호값으로 다시 나눈다.

```
// 입력된 Byte를 IV + 암호문으로 나눈다.
byte[] originalIvByte = Arrays.copyOfRange(cipherByte, 0, 16);
byte[] originalCipherByte = Arrays.copyOfRange(cipherByte, 16, cipherByte.length);
```

5.
이렇게 만든 encrypt와 decrypt를 IN/OUT을 모두 String으로 만들어서 쓰기 좋게

```
/**
* 암호화하고, Base64로 인코딩
* @param plainText - 평문
* @return 암호문
*/
public static String encryptAndEncoding(String plainText) {
// 암호화하고 나서, 다시 문자열로 만들기위해 Base64 인코딩
return Base64.encodeBase64String(encrypt(plainText));
}

/**
* Base64로 디코딩하고, 복호화
* @param cipherText - 암호문
* @return 평문
*/
public static String decodeAndDecrypt(String cipherText) {
// 다시 Byte로 만들기위해 Base64 디코딩하고 복호화
return decrypt(Base64.decodeBase64(cipherText));
}
```


2016년 12월 18일 일요일

[예전글] 업무연락하기 노하우

2012년 8월에 후배들에게 보여주기 위해 썼던 내용을 옮겨와 본다. 당시 부서 스텝에서 신입사원에게 교육할 때 사용한다고 정리해 달라고 했던 내용이다. 지금 다시 보면 좀 다르게 정리할 수도 있는 내용이 섞여 있겠지만, 그 때의 내가 가진 기준이나 느낌을 그대로 살리기 위해 변경없이 블로그에 남긴다. 원본에는 예시로 실제로 내가 당시에 주고 받은 메일을 캡쳐하여 추가했었지만, 그건 이해를 돕기 위한 것이고 본문만으로도 충분히 의도가 전달되므로 블로그에는 생략한다.

# 업무연락하기 노하우

## 보고 + 기록 + 자료

보고 : 본인이 수행한 업무 결과를 타인에게 알려줌
>> 타인의 입장에서 필요한 정보만 기술한다.

기록 :업무관계자끼리 결정된 내용을 글로 남김
>> 결정된 내용과 그에 따른 할일을 표시한다.

자료 :업무수행을 위해 필요한 자료를 공유
>> 자료에 대한 설명 위주로 작성한다.

## 한번에 한가지 내용만

수신자가 같더라도 서로 다른 종류의 업무에 대한 내용이 하나의 메일/쪽지에 담기지 않도록 주의한다.

특히 답장을 보내면서 원문과 상관없는 내용을 추가하여 질문하는 것을 피한다.
이런 경우 별도의 메일/쪽지를 작성하여 보낸다.

## 제목은 구체적으로

ex) 회의결과 공유합니다.
어떤 주제에 대한 회의였는지 없음
회의결과에 대한 내용이 없음
수신인이 내용을 저장할때 난감함
나중에 검색할때 제목으로 검색이 불가

ex) 주민등록번호 입력은 숫자만 13자리로 결정함

## 수신자와 참조자를 구분

수신자
연락을 기다리는 사람
관련된 할일이 있는 사람

참조자
할일은 없지만 내용을 알고 있어야 하는 사람

수신/참조자 목록을 공유할 필요가 있을 경우
본문 시작에 수신자와 참조자를 구분하여 표시

## 표현은 간결하게

최대한 짧고 간단한 문장으로 표현한다.

자기소개를 장황하게 하지 않는다.

과도하게 높임을 사용하지 않는다.

## 번호로 내용 구분

여러 항목에 대한 내용이 포함된 경우
각각의 답변이 필요한 경우
쪽지/메일 안에서 각 항목을 지칭해야 하는 경우
ex) 1번과 2번이 결정된다면 3번은 생략하겠습니다.

한 번호에 내용이 너무 길지 않도록 주의. 그런 경우 번호를 나누면 된다.
번호마다 꼭 소제목을 달 필요는 없다.
번호마다 시공간상 흐름이 있다면 흐름대로 순서

## 중요한 내용은 색으로 표시

최종 결정된 내용
수신인이 해야 하는 일
이슈로 제기된 내용

붉은색, 파란색 글자색 활용
노란색, 연두색 바탕색 활용

## 첨부파일에 대한 설명필수

첨부파일에 대한 설명을 본문에 포함시킨다.
파일이 여러개일 경우, 파일명을 정확하게 명시하여 구분한다.

첨부파일의 특정부분이 중요한 경우, 위치를 명시한다.

본문에 첨부파일의 모든 내용이 포함된 경우, 본문에 동일함을 명시
수신자가 본문내용과 첨부파일 중에서 선택하여 읽을수 있도록

## 답장하는 내용은 색으로 구분

답장시에는 본인이 작성한 부분을 원문과 구분
특수기호를 넣거나 색을 다르게 표시

2016년 12월 16일 금요일

maven central에 없는 라이브러리 github에서 가져오기

개발셀에서 Gephi라는 프로그램의 Toolkit을 쓸 일이 생겨서 Toolkit으로 오픈된 라이브러리를 이용해서 커맨드라인으로 파일을 변환하는 자바 어플리케이션의 개발환경을 구축하게 되었다.

1.
라이브러리는 github에서 제공되고 있었는데, 다운로드를 받아보니 Fat Jar 형태였다. 즉, 라이브러리에서 직접 제공하는 자바 클래스와 실행을 위해 필요한 다른 라이브러리의 클래스까지 모두 하나의 jar로 압축되어 있었다.

2.
담당 개발자가 POC처럼 이것저것 해볼때는 fat jar를 다운받아서 로컬에서 이클립스 프로젝트를 구성하여 사용하였는데, 이걸 다시 github에 올리기 전에 빌드를 gradle로 구성하기로 했다.

3.
우선 Gephi Toolkit이 maven에 올라가져 있길래 gradle dependency에 추가했다.

```
dependencies {
// gephi toolkit
compile group: 'org.gephi', name: 'gephi-toolkit', version: '0.9.1'
}
```

4.
수많은 다른 라이브러리들을 하나씩 내려받다가 2개 라이브러리를 내려받지 못해서 에러가 발생했다. 찾아보니 정말로 maven central에 각각의 라이브러리는 있지만 찾고 있는 버전은 등록되어 있지 않았다. stax-utils-snapshot-20100402.jartrove-2.1.0.jar이 그것들이다.

5.
검색을 좀 해보니 당연히 나만 이런 것이 아니었고, 해결책으로는 
들이 이미 덧글로 달려있었다. 2개만 별도로 다운로드 하라는 것은 그 2개의 라이브러리가 가지고 있을지도 모르는 depencency는 무시하게 될 것이다. 그래서 all 버전을 사용하기로 결정했다.

6.
그렇다고 all 버전을 git에 올릴 수는 없었다. 그래서 github에 제공된 링크를 통해서 gradle 빌드시점에 다운로드 받는 방법을 찾아보기로 했다. 조금 검색해보니 Gradle Download Task라는 plugin을 찾을 수 있었다. Java 컴파일 하기전에 다운로드 받도록 gradle 파일을 구성했다.

```
apply plugin: 'de.undercouch.download'

import de.undercouch.gradle.tasks.download.Download

task downloadGephiToolkit(type: Download) {
    src 'http://github.com/gephi/gephi-toolkit/releases/download/v0.9.1/gephi-toolkit-0.9.1-all.jar'
    dest 'lib/'
    overwrite false
}

compileJava.dependsOn downloadGephiToolkit
```

7.
그리고 gradle의 dependency도 아래처럼 변경하고, 마지막으로 gradle 파일이 이렇게 된 이유를 설명하는 주석을 달아두었다.

```
dependencies {
// gephi toolkit
compile name: 'gephi-toolkit-0.9.1-all'

//XXX 아래처럼 선언하면 stax-utils와 trove를 maven에서 찾다가 에러난다. 그래서 gephi-toolkit-0.9.1-all을 사용한다.
// compile group: 'org.gephi', name: 'gephi-toolkit', version: '0.9.1'
}
```




2016년 12월 13일 화요일

Underscore.js 스터디 계획

자주 사용하게 되는 Underscore.js에 대한 스터디를 시작하게 되어, 그 계획을 짧게 적어본다. 다양한 API에 대해서 인지하고, 사용법을 숙지하고, Functional Programming에 대해서 간단히 감을 잡는 시간이 될 것 같다. 그리고 사용법만 보지 않고 소스코드도 같이 보면 좋을 것 같다.

1. 첫째날
- Introduction : 같이 읽어 보고 어떤 느낌의 라이브러리인지 공감한다.
- Collections : 이때 filter, map, reduce 유형으로 크게 나누고, 각 함수마다 어느 유형에 속하는지 이야기해본다.


2. 둘쨰날
- Arrays
- Objects
- OOP Style
- Chaining

3. 셋째날
- Functions
- Utility

4. 넷째날
- Change Log
- Links : Underscore.string, Underscore.java
- 다른 라이브러리 : Lodash

2016년 12월 1일 목요일

git repo로 구성된 소스코드의 Tab과 Space 일괄 통일 작업 실행


예전에 작성한 git repo로 구성된 소스코드의 Tab과 Space 일괄 통일 작업 계획을 오늘 실제로 실행했기에 블로그를 적어 본다.

작업 전에 미리 생각해볼 문제들


Tab과 Space 중 Tab으로 결정
- 이유 1 : 개발팀원이 모두 Tab을 선호함
- 이유 2 : 이클립스의 기본 설정
- 이유 3 : 키보드의 Tab키를 눌러서 들여쓰기를 하니까 실제 행동과 결과를 맞추려고

Space 4개를 Tab 1개로 하고, 4개 미만의 Space는 버림
- 이유 1 : 단순한 계산이 가능해서
- 이유 2 : 이클립스의 기본 설정이 Space 4 = Tab 1

변경 후 혹시 틀어지게 되는 들여쓰기는 무시했다.
- 이유 1 : 나중에 그 부분을 수정할 때 고치겠지.
- 이유 2 : 어차피 지금도 일관된 규칙으로 들여쓰기 되지 않음
- 이유 3 : 일괄로 들여쓰기 정도를 고치면 들여쓰기가 틀어질 수 있음

일괄 작업 날짜는 특정 버전 릴리즈 직후로 했다.
- 이유 1 : 개별 개발자가 별도 branch를 만들 경우가 거의 없다.
- 이유 2 : 일괄 작업한 결과를 master와 development 모두 merge 가능

작업하는 김에 줄끝의 공백문자도 같이 지워주고, 줄바꿈문자도 UNIX(\n)로 같이 통일했다.


작업 방법


소스코드를 변경하는 java 프로그램을 작성해서 일괄로 작업했다. 이런 작업을 일괄로 하위 디렉토리까지 해주는 도구를 찾아볼까도 생각했는데, 프로그램을 직접 만드는게 간단할 것 같아서 그냥 구현했다.

파일을 한줄씩 읽어서 처리하고 다시 한줄씩 쓰는 형태인데, java7 nio 패키지의 Files를 이용해서 한번에 읽어서 처리하고 다시 한번에 쓰는 형태로 구현했다.

그리고 Files.write를 할 때 UNIX 줄바꿈 문자를 사용해야 하는데, 작업을 해보니 그대로 DOS형식이 유지되어 파일이 생성되고 있었다. javadoc을 보면 line.separator라는 시스템 프러퍼티에서 지정한 플랫폼별 줄바꿈문자를 사용한다고 한다. 그래서 시스템 프러퍼티를 강제로 \n으로 바꿔 주어야 한다.

```java
System.setProperty("line.separator", "\n");

List<String> readAllLines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);

for (int i = 0; i < readAllLines.size(); i++) {
String line = readAllLines.get(i);
String changedline = StringUtils.stripEnd(line, null);
changedline = changeToTab(changedline);
readAllLines.set(i, changedline);
}

Files.write(file.toPath(), readAllLines, StandardCharsets.UTF_8);
```

이 프로그램이 정말 소스코드의 앞뒤 공백문자와 줄바꿈문자만 변경했는지를 확인하고 싶었다. 그래서 생각해 낸 것이 git diff를 공백을 무시하여 확인하는 방법인데, command line에서 아래 명령을 실행해서 변경된 것이 아무것도 없는 것을 확인하여 예상대로 작업이 되었다고 확인할 수 있었다.

```
git diff --ignore-all-space
```


작업 후 처리


앞으로 변경되는 소스코드에서 일괄작업에서 적용한 규칙을 지켜서 git 형상에 들어올 수 있도록 개별 개발자의 개발편집환경을 맞출 필요가 생겼다. 우리 개발팀은 모두 이클립스를 사용하므로, 이클립스에서 각 프로젝트의 환경설정과 AnyEdit라는 플러그인의 옵션을 설정하는 것으로 이를 맞출 수 있었다.

.settings/org.eclipse.core.resources.prefs 파일 내용
eclipse.preferences.version=1
encoding/<project>=UTF-8

.settings/org.eclipse.core.runtime.prefs 파일 내용
eclipse.preferences.version=1
line.separator=\n

.settings/de.loskutov.anyedit.AnyEditTools.prefs 파일 내용
activeContentFilterList=
addNewLine=false
convertActionOnSaave=AnyEdit.CnvrtSpacesToTabs
eclipse.preferences.version=1
fixLineDelimiters=true
ignoreBlankLinesWhenTrimming=false
inActiveContentFilterList=
javaTabWidthForJava=false
org.eclipse.jdt.ui.editor.tab.width=4
projectPropsEnabled=true
removeTrailingSpaces=true
replaceAllSpaces=false
replaceAllTabs=false
saveAndAddLine=false
saveAndConvert=false
saveAndFixLineDelimiters=true
saveAndTrim=true
useModulo4Tabs=false