[Concept | Encription] 암호화의 기본개념

시스템 개발시 악의적인 공격을 피하기 위해 암호화는 필수적으로 적용되어야 한다. 암호화의 기본적인 의미와 원리를 정리해보자.


작성일 : 2017-03-01
수정일 : 2021-04-09

1> 사전적의미의 암호화

암호화(encryption)란? 정보가 노출되는 것을 방지하기위해 특정 알고리즘을 이용하여 변형하는 것.

  • 암호화를 역행하여 다시정보를 읽게 하는 것은 복호화(decryption)라고 함.
  • 군사와 정부의 은밀한 대화를 위하여 오랫동안 이용되어 왔음.
  • 근래 기업에서는 데이터 전달개인의 정보를 저장하는데 자주 이용함.

2> 시스템 개발에서의 암호화

보안이 필요한 정보를 특정 알고리즘을 통해 의미없는 문자열(이진수 덩어리)로 바꾸는 것.

  • 악의적인 목적으로 암호를 해독해 공격하는 것을 방지할 수 있음.
  • 보안에 있어 시스템적인 보호 방법 보다 근본적인 해결방법이라 할 수 있음.

3> 암호화의 기본조건

암호화는 아래 두가지 조건을 충족해야 함.

* Confusion(혼돈) : 원문의 내용을 짐작하기 어렵게 만들어야 한다.
* Diffusion(확산) : 알고리즘의 패턴을 추론하기 어렵게 만들어야 한다.
  • 가장 좋은 암호화는 알고리즘을 알아내기 어렵게 해서 정보를 해독하지 못하게 하는 것이지만 항상 암호화 하려는 자와 복호화 하려는자의 노력이 있을뿐 100% 해독 불가능한 암호화란 있을 수 없음.

4> 고전적인 암호화

아래 설명하는 치환(Substitution)과 이동(Transposition)을 교차적용해 암호화 하였음.

4-1> 치환 (Substitution) : 단순히 다른문자로 치환하여 혼돈의 조건을 만족시킴.

4-2> 이동 (Transposition) : 무작위로(실제로는 특정규칙이 존재) 다른문자로 치환하여 확산의 조건을 만족시킴.


5> 암호화의 발전

컴퓨터의 등장으로 과거 기계식에 비해 계산능력이 월등해 졌고 그앞에서 고전적인 암호화는 무용지물이 되었다. 따라서 안전성 보완을 위해 임의의 문자열값인 암호화키(Encryption Key)를 활용하게 되었음.

5-1> 원리

암호화키와 평문(Plain Text)을 바이너리 형태로 변형한 후 배타적 논리합(XOR) 연산에 따라 암호화 및 복호화를 함.

ABA XOR B
000
101
011
110
[참고] XOR 연산

5-2> 암호화 규격

암호화키의 길이나 사용횟수가 제약이 없다면 복잡도를 무한히 증가시켜 거의 완벽한 암호화가 가능하겠지만 복호화 하는데 비용(시간소모)이 계속 커진다면 사용할 수가 없을 것이기 때문에 일정한 규격에 의한 암호화를 고려해야 함.

5-3> 양자연산

양자연산이 가능한 컴퓨팅 방식으로 인해 연산속도가 월등히 빨라진다면 위험하지 않느냐는 의문이 제기 되고는 있지만 양자연산을 통한 해독 알고리즘이 발전되기 전까지는 안전하다고 함.

5-4> 암호화의 불완전성

현재까지 주로 사용되는 방식의 암호화는 엄밀히 말하여 완벽한 안전을 보장하는 것이 아니라 현실적으로 풀기 어렵다는 조건부 안전에 의존하고 있음.

[Source | MyBatis] DB 부하를 줄이기 위한 쿼리캐싱 기능

거의 바뀌지 않거나 고정된 값을 디비에서 자주 쿼리해야할 경우가 있다. 이때 마이바티스에서 제공하는 쿼리캐싱 기능 사용법을 알아보자.


작성일 : 2021-04-06

https://mybatis.org/mybatis-3/ko/sqlmap-xml.html#cache
공식문서에 잘 설명이 되어있다.


1> 캐싱적용시 고려해야하는 사항들

* flush / set 하는 시점을 명확히 정의 해야한다.
--> 단순히 부하를 줄인다고 여기저기 사용했다가 갑자기 이상한 데이터로 에러가 발생할 수 있고 추적 또한 어렵다.
* 마이바티스의 경우 쿼리 단위로 캐싱을 해줘 문제가 되지 않지만 Redis나 Memcached, ehcache등을 사용한다면 값저장시 키값을 잘 정의해야한다.
--> 보통 키값에 prefix(객체명+'_')를 주어 구분한다.
* 데이터가 자주 변경되는 경우 사용여부를 다시한번 고려해보자.
--> 변경시 flush하고 확인시 다시 set해줘야 하기 때문에 불필요한 절차만 추가할 뿐이다.

2> 적용예제

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.opendocs.www.repository.categorys.CategorysDaoMapper">
    
   <!-- Configuration Caching -->
   <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

   <!-- Insert Query Flush Cache --> 
   <insert id="insert" parameterType="categorys">
      INSERT INTO opendocs_www.categorys (uid, pid, name, status, created_at) 
         VALUES(#{uid}, #{pid}, #{name}, #{status}, now())
   </insert>

   <!-- Select Query Use Cache --> 
   <select id="select" parameterType="categorys" resultType="categorys">
      SELECT uid, pid, name, status, created_at, updated_at 
      FROM opendocs_www.categorys T1 
   </select>
	
   <!-- Update Query Flush Cache --> 
   <update id="update" parameterType="categorys">
      UPDATE opendocs_www.categorys
      <set>
         <if test="1 == 1">updated_at = now(),</if>
         <if test="pid != null">pid = #{pid},</if>
         <if test="name != null">name = #{name},</if>
         <if test="status != null">status = #{status},</if>
      </set> 
      WHERE uid = #{uid}
   </update>
	
   <!-- Delete Query Flush Cache --> 
   <delete id="delete" parameterType="categorys">
      DELETE FROM opendocs_www.categorys WHERE uid = #{uid}
   </delete>
	
</mapper>
위의 예제는 select시 캐싱하고 insert, update, delete시 캐싱된 데이터를 지운다.
<cache/>를 선언하게 되면 다음 속성을 선언한 것과 같으며 특정쿼리가 캐싱되지 않기를 원한다면 useCache="false"를 선언해주면 된다.
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>

2-1> eviction : 캐싱전략

* LRU - 가장 오랜시간 사용하지 않는 객체를 제거
* FIFO - 캐시에 들어온 순서대로 객체를 제거
* SOFT - 가비지 컬렉터의 상태와 강하지 않은 참조(Soft References )의 규칙에 기초하여 객체를 제거
* WEAK - 가비지 컬렉터의 상태와 약한 참조(Weak References)의 규칙에 기초하여 점진적으로 객체 제거

2-2> flushInterval : 플러시 주기 (밀리세컨드 단위 1초 = 1000)

* 밀리세컨드 단위로 1초이면 1000
* 기본값없음 (미선언시 쿼리수행시만 동작)

2-3> size : 캐싱 사이즈

* 메모리 상황을 고려한 적정한 사이즈
* 기본값 1024

2-4> readOnly : 읽기전용 여부

* 모든 호출자에게 캐시된 객체의 같은 인스턴스(변경불가)를 리턴
* 사용시 성능 향상
* 기본값 false

3> 다른 캐싱방법

상황에 맞추어 아래 캐싱방법도 고려하여 보자.

  • Memcached
  • Redis
  • ehcache

[Setting | VSCode] ftp / sftp 접속

CI환경이 구축되지 않아서 수정한내용을 번거롭게 개발 & 배포를 해야할 경우가 있다.
이때 번거로움을 피하고자 서버에 직접 접속하여 수정하게 된다.
(물론, 이력관리서비스 장애에 취약하게 되니 추천되는 방법은 아니다.)
Visual Studio Code 에서 sftp로 서버에 직접 접속하여 소스를 수정하는 방법을 정리해 본다.


작성일 : 2021-03-27

1> Extenstions(단축키 Ctrl+Shift+X) > ftp-simple을 검색하여 설치한다.


2> 설치가 완료되면 단축키 Ctrl+Shift+P > ftp-simple : Config – FTP connection setting 실행


3> 다음과 같이 설정하고 저장

name : 접속구분
host : 서버호스트
port : 접속포트
type : ftp or sftp
username : 사용자명
password : 패스워드
path : 수정할 폴더경로
autosave : 수정후 저장시 자동으로 서버에 수정 및 저장여부
confirm : 저장시 덮어쓸지여부를 선택
privateKey : 접속시 키파일이 필요할경우 경로를 입력

※ 전체옵션

name - string - Display name.
host - string - server domain or ip.
port - number - (option) port (Default: : 21)
type - string - (option) ftp type. 'ftp' or 'sftp' (Default: : 'ftp'). If 'ftp' does not work, try 'ftp2'.
username - string - username for authentication.
password - string - (option) password for authentication.
privateKey - string - (option) (only sftp) String that contains a private key for either key-based or hostbased user authentication (OpenSSH format) Default: none
passphrase - string - (option) Use sftp 'privateKey' only. For an encrypted private key, this is the passphrase used to decrypt it. Default: none
agent - string - (option) (only sftp) Path to ssh-agent's UNIX socket for ssh-agent-based user authentication. Important: Windows users: set to 'pageant' for authenticating with Pageant or (actual) path to a cygwin "UNIX socket." Default: none
agentForward - boolean - (option) (only sftp) Set to true to use OpenSSH agent forwarding (auth-agent@openssh.com) for the life of the connection. agent must also be set to use this feature. Default: false
secure - boolean - (only ftp) Explicit FTPS over TLS, default: false
secureOptions - object - (only ftp) Options for TLS, same as for tls.connect() in Node.js.
path - string - (option) remote root path. Default: '/'
autosave - boolean - (option) To determine whether the automatically uploaded when you open a file directly and modify and save. Default: true
backup - string - (option) The local path you want to back up before file saving on the server.
confirm - boolean - (option) Only save option. When you save the file, ask if you want to overwrite the file if it already exists.. Default: true
project - object - (option) Only save option. Pre-specify local workspace path and server root path to save directly without selecting a path. Overwrite unconditionally.
ignore - array - (option) Only 'Remote directory open to workspace' option. Path to be ignore. Use glog pattern. (Caution : server path (ex:/home) + ignore pattern (ex:/**/node_modules) => /home/**/node_modules)

4> 단축키 Ctrl+Shift+P > ftp-simple : Remote directory open to workspace

선택하면 3>에서 설정한 접속구분명이 보여지고 접속할 폴더도 선택가능하다.


5> 파일 수정이 되지 않는다면…

파일에 권한을 확인해야 한다.
접속한 사용자가 파일수정권한이 없을경우 에러메시지 없이 서버에 내용이 반영되지 않는다.
파일의 소유자를 변경하거나 접속 username을 변경해야 한다.