Tistory View

openssl

명령줄 : aes256 cbc openssl

God Dangchy What should I do? 2020. 3. 23. 04:03


openssl을 설치하고 암호화작업을 하기위해 인터넷을 뒤져보면 다음과 같이 암호화와 복호화를 할 수 있다.



암호화 하기

openssl enc -e -aes-256-cbc -in plain.txt -out encrypted.data


이 명령어를 이용하면 중간에 비밀번호를 묻게되는 데, 이 때, 비밀번호를 입력하면 암호화가 된 파일이 생성되게 된다.


복호화 하기

openssl enc -d -aes-256-cbc -in encrypted.data -out plain.txt


이 또한 비밀번호를 물어보게 되고, 암호화할 때 입력한 비밀번호를 입력하게되면 문제없이 복호화된 파일이 생성된다.



옵션을 살펴보도록 하자.

enc : 암호화/복호화작업을 하겠다는 것이다, dec 명령은 없으며 -e와 -d를 이용하여 암호화인지 복호화인지를 결정하게 된다. -e나 -d가 없다면 -e로 암호화작업을 하게된다.

-e : 암호화

-d : 복호화

-aes-256-cbc : 암호화/복호화 작업에 사용될 cipher로 aes-256-cbc를 사용한다는 뜻이다.

-in [입력파일] : 입력파일을 지정한다. 지정하지 않으면 stdin에서 입력을 받는다.

-out [출력파일]   : 출력할 대상파일이다. 지정하지 않으면 stdout으로 출력이 된다.



비밀번호를 타이핑을 쳐야 하는 문제가 있으니, 다음과 같이 그냥 비밀번호를 명령어상에서 넣을 수가 있다.

openssl enc -e -aes-256-cbc -in plain.txt -out encrypted.data -k "my_password"


비밀번호가 그냥 노출되지만, 실제 이런 작업은 실제 프로그래밍 코드에서 shell명령을 호출하는 방식으로 쓸 때 유용하다.


그럼 이제 공부를 좀 해보자.

aes256_cbc 방식은(다른 것들도 대부부분 그렇지만) 암호화와 복호화에는 key와 iv두가지가 필요하다.

aes256_cbc는 key로 32바이트 / iv는 16바이트의 크기를 사용한다. 


key는 말 그대로 비밀번호에 해당하므로, 다른 사람에게 알려주면 안되는 정보이며 iv는 같은 파일을 암호화 하더라도 다른 결과를 만들기위해 있는 정보다. iv가 없다면 암호화된 데이터와 원본데이터의 구조를 잘 파악하면 iv가 있을 때보다 훨씬 유추하기가 쉬워지게 된다.


key와 iv 추출

(비밀번호를 통해 만들어지므로 생성이 아닌 [추출]이라는 용어를 사용했다.)


암호화/복호화 작업에는 key와 iv 두개가 필요하다. 위의 명령줄은 입력한 비밀번호를 이용하여 이 key와 iv를 추출하게 된다. aes-256-cbc의 경우 key는 32bytes, iv는 16바이트를 사용하기 때문에 입력한 비밀번호가 길던 짧던 이 크기의 key와 iv를 만들어야 한다. 이 추출에 쓰이는 함수는 EVP_BytesToKey다. 이 함수의 원형은 다음과 같다.



EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,

                       const unsigned char *salt,

                       const unsigned char *data, int datal, int count,

                       unsigned char *key,unsigned char *iv)



type : 암호화방식으로 우리는 aes256-cbc를 사용할 것이다. 이 값은 key와 iv의 크기를 알아내려는 용도로 사용되는 것 같다.

md : 추출과정에서 사용할 hash알고리즘이다. md5나 sha256을 이용하게 되는 데, 이는 명령줄에서 -md 옵션을 이용하여 지정할 수 있다.


salt

    NULL로 지정할 경우 salt를 쓰지 않는 것이고, 지정할 경우 8bytes의 크기로 넘겨 줘야한다. 암호화시는 salt를 생성하여 넘겨 줘야 하고, 복호화시는 암호화시 사용한 salt를 넘겨줘야 한다.


data, datal : 입력한 비밀번호와 길이


count : 

    몇번을 hash해서 만들 것인가. 이 값은 기본 명령줄에서는 1을 사용한다. 

    1을 사용하지만 내부적으로는 여러번 hash를 할 수도 있다. md5의 경우 1회만으로 48bytes(key32 + iv16)을 만들수가 없기 때문이다. (정확한 확인은 못해 봤다.)

    이 값은 암호화에서 반복한 횟수를 복호화에도 동일하게 넘겨줘야 한다.

    실제로 제대로된(?) 암호화를 위해서는 10000이상의 값을 줘야 의미가 있다.



key,iv : 추출된 key와 iv가 저장되는 위치


문제는 이 -md 옵션을 주지 않을 경우 openssl 버전마다 다른 것을 사용하게 된다.

필자가 알기로는 sha256을 사용하지만 그 전에는 md5를 사용한 것으로 알고 있다. 만약에 md5를 이용하여 생성하는 openssl 버전으로 암호화 할 경우, 복호화도 md5로 지정해 줘야 한다.




Salt

기본적으로 salt이용하는 것으로 되어 있기 때문에, salt를 이용하지 않으려면 "-nosalt" 옵션을 주면 된다.

어떤 key와 iv와 salt가 사용되었는지 알고 싶다면 "-p"옵션을 이용하면 화면에 hex값으로 보여주게 된다.



근데 Salt는 뭐고 왜 쓰는 건가요?

salt를 사용하지 않을 경우 key와 iv는 늘 같은 값으로 생성이 되게 된다. 

salt가 없다면 무차별대입법을 이용하여 비밀번호를 때려 맞추기가 상대적으로 너무 쉽기 때문에 salt를 사용한다. 

예를 들어 비슷한 내용의 원본을 암호화해 비교해보면, 같은 비밀번호를 사용했다는 것을 쉽게 유추할 수가 있다.

또한 salt를 사용하면 암호화문서마다 따로따로 무차별대입을 해야하기 때문에 시간을 지연시키려는 목적을 가지고 있다.





암호화 파일 구조

저장은 다음과 같이 된다.




처음 검은색 부분 8bytes "Salted__"가 채워지고, 

다음 노란색 부분 8Bytes는 Salt값이 저장되어 있다. 

그 다음은 빨간색 암호화된 데이터가 저장된다.


암호화된 데이터의 크기는 aes-256-cbc의 경우 16bytes의 배수로 저장이 된다. 이는 padding이 들어가기 때문이다. 정확한 것이 아니므로 그리 신뢰하지는 말아라.




padding은 또 뭔가?

padding은 말 그대로 맨 뒷부분에 엉뚱한 데이터를 일부러 넣는 것이다. 예를 들어, 편지는 생각해보면 편지의 맨 마지막은 보통 "~~~ 올림" 등 과 같이 일정한 형태를 가지는 것이 보통이다. 이 일정한 정보를 이용해 값을 유추해내는 것을 방지하기 위해 일부러 값을 넣어서 유추하기 힘들게 만드는 것이 목적이다.



암호화 플로우

암호화 플로우



1. 사용자가 입력한 비밀번호로 key와 iv를 추출해낸다. 이 때 key와 iv 추출시 매번 새로 만들어지는 salt값은 나중에 저장된다.

2. 원본데이터에 padding을 붙인다.(원본에 붙는 건지 암호화후에 붙는 건지는 확인은 못해 봤지만, 암호화/복호화에는 문제가 없다.)

3. 1번에서 생성된 salt값과 암호화된 데이터를 저장한다.



복호화 플로우

복호화 플로우



1. 사용자가 입력한 비밀번호와 암호화파일에 저장된 salt값을 가지고 와서 key와 iv를 생성한다.

2. key와 iv를 이용해 암호화된 데이터를 복호화한다.

3. 원본데이터는 저장한다.





복호화에서 비밀번호가 올바른지 아닌지를 먼저 검사할 수는 없다.(아마도), 복호화과정 중에 실패하면 비밀번호가 틀린 것으로 처리된다. 좀 더 정확히 복호화과정 맨 마지막에 결과를 알수 있다.



여기 끝이면 얼마나 좋을 까...ㅠㅠ


EVP_BytesToKey의 매뉴얼에 보면 새 어플리케이션에는 이 함수를 쓰지 말고, PKCS5_PBKDF2_HMAC를 사용하라고 되어있다.

실제 명령줄에서도 pbkdf2(password based key derived function)를 고려해보라는 메세지가 나오게 된다. 


WARNING : deprecated key derivation used.



명령줄에서 pbkdf2를 사용하려면 "-pbkdf2" 옵션을 주면 된다. 또는 "-iter 횟수"를 지정하면 EVP_BytesToKey를 사용하지 않고 pbkdf2를 이용하게 된다.



따라서 맨 위에 작성된 명렬줄을 통해 암호화한 것은...... 젠X, 망한거다.


다음의 명령줄을 이용하여 암호화와 복호화를 해야 한다.


암호화 

   openssl enc -e -aes-256-cbc  -in plain.txt -out encrypted.data -k "my_password" -pbkdf2 -iter 10000


복호화

   openssl enc -d -aes-256-cbc  -in encrypted.data -out plain.txt -k "my_password" -pbkdf2 -iter 10000



-iter를 사용했으므로 굳이 -pbkdf2를 넣어줄 필요는 없으나, 정확히 인지하기위해 넣어 두었다.




암호화파일 압축하기

암호화된 파일을 압축을 해보면 압축이 하나도 안된다.... 헐...얼마나 복잡하길래..

결국 용량을 줄일려면, 압축을 먼저하고 그 다음에 암호화 작업을 해야한다.






'openssl' 카테고리의 다른 글

복호화(PHP) : aes256 cbc openssl  (2) 2020.03.23
복호화(C/C++) : aes256 cbc openssl  (0) 2020.03.23
명령줄 : aes256 cbc openssl  (0) 2020.03.23
Replies
Reply Write