시작하며
지난 글에서 ecb 한블록 암호화를 이용하여 cbc와 ctr 모드의 구현을 살펴보았고, 이제 이 둘을 이용해 제대로 암호화를 진행하는 end, dec 함수의 구현을 살펴보겠다. 이 암복호화 함수는 CBC, CTR 모드 두가지를 지원하며, 암호 알고리즘, 암복호화에 필요한 파라미터 구조체, 암복호화에 필요한 키, 인풋과 아웃풋을 파라미터로 받아 기능을 수행한다. 이전 글에서 다뤘던 cbc, ctr 함수는 패딩처리까지 진행하지 않았고 이 enc, dec에서 마지막에 패딩처리를 해주는 방식이다. 이제 설명을 시작하겠다.
1. 파라미터
어때요..? 뭔가 직접 Doxygen으로 문서화 한걸로 딱 올리니까... 나 좀 있어보이는..... 뭔가 자랑스러운...... 기분좋은...
아무튼 위는 함수 파라미터를 포함한 대략적인 인터페이스에 대한 설명이다. 위 사진을 참조하면 될 것 같다.
2. i_enc 암호화 함수 구현
이제 소스코드를 보며 분석을 시작해보자.
파라미터와 변수부분을 제외하고 라인 222~223은 파라미터에 대한 검증을 하는 부분이다. 225, 236은 cipher 파라미터 구조체에서 cbc모드인지 ecb모드인지 체크하고 그에 따른 함수를 호출하는 부분이다.
이 후 아래 225부터 236라인을 보자. 여기서 조건이 p_inputlength >= blocklength라고 되어있는데 기본적으로 한 블록의 사이즈는 16바이트이다. 그리고 암호화는 무조건 16의 배수가 되도록 패딩을 붙여서 진행하게 된다. 만약 데이터가 16보다 작은 8이 들어왔다고 가정하자. 그렇다면 패딩 8을 붙여 16바이트를 맞춘 후 암호화를 진행한다. 만약 딱 맞게 16이 들어오면 16바이트를 암호화하고, 패딩으로만 16바이트를 만들어 이것을 암호화한다. 16보다 큰 36이 들어왔다면 16의 배수로 끊어야하므로 32바이트는 암호화하고 남은 4바이트에 12바이트 패딩을 더한 후 최종 암호화를 마무리한다. 이때 패딩은 pkcs7방식으로, 비어있는 바이트를 패딩값으로 집어넣는다. 만약 데이터가 12바이트이고 패딩 4바이트를 채워넣어야 한다면, 패딩은 0x04가 네 번 들어가는 형식이다. 여기서 알 수 있는 건, 16이 딱 맞게 들어오면 패딩으로만 16바이트를 만들어 붙이는 것처럼, 패딩처리를 안하는 경우는 없다. 어찌되었든 우선 16바이트 이상이라면 16의 배수만큼은 cbc나 ctr에 그대로 돌리고, 그 후 남은 나머지 데이터는 패딩처리 후 암호화하는 방식이다.
그래서 조건을 걸고 225~236라인까지 16의 배수만큼의 데이터를 처리하고 남은 데이터에 대해 239부터 처리를 한다. 239부터 244는 패딩을 붙이는 작업이다. 이 후 246부터 266까지 다시 패딩을 붙인 데이터를 각 블록암호 모드에 맞게 암호화를 진행한다. 269부터는 출력에 관한 부분이라 잘려도 크게 신경안써도된다(사실 당연히 출력 부분은 따로 빼는게 정석이나, 그냥 테스트하기 편하게 하기 위해 출력부분을 굳이 지우지 않았다.)
여기서 확인할 것은 함수 앞에 붙은 I_EXPORT 이다. 이전에 cbc와 ctr 함수는 패딩처리도 없고 그저 16의 배수만큼의 데이터를 일단 암호화만 진행하는 함수들이었고, 이는 i_enc에서 이 함수들을 래핑하고 enc 내부에서 패딩처리를 하기 때문에 사용자에게 제공하지 않는 함수였다. 때문에 I_LOCAL 키워드를 붙였다. 이제 이 최종적으로 패딩까지 모두 처리하는 하나의 완벽한 암호화 함수를 만들었기 때문에 이 함수는 전적으로 사용자가 사용하는 함수이며 앞에 I_EXPORT를 붙이면서 함수를 공개한다. 즉 사용자가 직접 호출 할 수 있다. 이렇듯, 사용자에게 오픈할 것과 그렇지 않은 것을 구별하는 것이 중요하다는 것을 이 프로젝트를 하면서 깨달을 수 있었다.
3. i_dec 복호화 함수 구현
이제 복호화 함수 i_dec이다. 우선 당연히 암호화된 데이터에 대한 복호화는 진행하지만, 추가적으로 복호화 함수가 처리해줘야 하는 부분이 있다. 바로 패딩에 대한 검증이다. 패딩은 아까 말한대로 16의 배수가 되지 않는 블록, 예를 들어 12바이트가 있다면 나머지 4바이트를 빈 만큼, 0x04가 네개 들어가게 된다. 즉 패딩을 검증함으로써 어느정도 복호화가 잘 되었다는 것을 신뢰할 수 있게된다. 패딩 검증은 마지막 바이트의 데이터를 읽고 그만큼의 자리가 똑같은 값으로 채워졌는지 체크하면된다. 위의 예시로보면 마지막 바이트에 0x04가 있다면
16, 15, 14, 13(인덱스로는 15, 14, 13, 12) 이렇게 네개 모두 0x04가 들어있는지 확인하면 된다. 그걸 전제로 봤을 때, 299부터 308라인까지는 cbc, ctr 복호화를 돌리고, 마지막 311부터 318라인에서 패딩에 대한 검증을 진행한다. 그러고 나서 최종적으로 p_outputlength를 패딩 값을 뺀 사이즈로 설정해준다면, 원본 데이터를 복호화해 얻을 수 있게 된다. 이렇게 암복호화 함수에 대한 구현을 살펴보았다. 추가적으로 파라미터로 받는 I_CIPHER_PARAMTERS에 대해 살펴보자.
3. I_CIPHER_PARAMETERS
이것도 Doxygen으로 보여주겠다. 이 구조체는 블록암호운용모드를 설정하는 mode(1이면 cbc, 2면 ctr) 그리고 iv와 iv의 길이를 저장하고 있다. 사실 보다 추가적인 요소들도 포함하고 있어야 하겠지만 이 프로젝트에선 이정도만 담기로 하였다. 그리고 사실 애초에 파라미터도 많아서 이것마저 구조체로 묶지 않으면 함수 파라미터가 너무 많아진다 ㅠㅠ 아무튼 이런식으로 암복호화 함수를 구현하였고 다음 글에선 내부상태를 저장하며 데이터를 분할하여 암호화와 복호화를 진행할 수 있는 init, update, final에 대해 다뤄보겠다. 그럼 다음에 봐용
현재 글에서 다루는 부분은 아래 깃 repository에서 i_crypto_library/src/i_crypto.c에서 확인할 수 있습니다.
github : https://github.com/0xGh-st/I_CRYPTO.git
GitHub - 0xGh-st/I_CRYPTO
Contribute to 0xGh-st/I_CRYPTO development by creating an account on GitHub.
github.com
'C > Crypto' 카테고리의 다른 글
Crypto Project : 1-5. 암복호화 init, update, final 구현 (0) | 2023.04.16 |
---|---|
Crypto Project : 1-4. C언어에서 멤버변수 접근을 막는 방법과 init, update, final의 개념 (0) | 2023.04.15 |
Crypto Project : 1-2. 블록암호운용모드 ECB를 이용한 CBC, CTR 모드 구현 (0) | 2023.04.13 |
Crypto Project : 1-1. i_crypto library - 구조 및 문서화 예시 (0) | 2023.04.11 |
Crypto Project : Prologue (0) | 2023.04.10 |