티스토리 뷰
[cipher] Advenced Encryption Standard (AES), OpenSSL을 사용한 Encryprt/Decrypt 예제
LEIBNIZ 2017. 2. 23. 11:20고급 암호화 표준이라고 불리는 AES는 미국 표준기술 연구소에서 제정한 암호화 방식이다.
레인달(Rijndael) 알고리즘에 기반된 암호화 방식으로 128, 192, 256비트 의 키길이로 처리할 수 있고 무료 배포가 가능하여 채택되었다.
AES암호화에 사용되는 알고리즘들은 아래와 같이 4가지가 있다. (이들을 묶어 레인달 알고리즘이라 한다.)
- Substitution Box (일명 s-box) : 바이트들을 s-box에 있는 바이트들과 바꾸는 알고리즘, 이는 입력데이터를 지정된 숫자로 바꿔 암호를 깨기 어렵게 만드는 기법이다.
- ShiftRows : 바이트의 행을 Shift하는 알고리즘
- MixColumns : 특수한 공식으로 바이트값들을 바꾸는 알고리즘
- AddRoundKey : XOR 연산자를 사용하여 바이트를 바꾸는 알고리즘
레인달 알고리즘 순서는
키 스케쥴(AES 알고리즘은 대칭키 암호화 알고리즘 이다.) 다음에,
ADDRoundKey로 CipherText를 암호화 시킨다음,
Encrypt 된 Text에 위의 4가지 알고리즘을 적용시킨다.
키의 크기에 따라 반복하는 횟수가 AES128 는 9번, 192는 11번 256은 13번 반복한다.
따라서 AES128,192,256은 사실 같은 알고리즘을 키의 크기에 따라 얼마나 반복하느냐에 따라 나뉘는 것이다.
이렇게 생성된 cipher text를 base64 인코딩을 통해 바이너리 데이터를 가시화 할 수 있으며,
PKCS7 Padding는 base64 인코딩 후, 디코딩 전에 사용하여 바이트 크기를 맞춰주면 된다.
사실 레인달 알고리즘을 구현 할 필요는 없다. OpenSSL에서 다 제공해주기 때문에 AES암호화가 어떤것이냐 어떻게 동작하느냐만 안다면 사용하는데는 크게 문제가 없을 것이다.
아래는 OpenSSL을 사용하여 C에서 해당 AES-CBC 암호화를 EVP를 사용하여 Encrypt/Decrypt한 예제이다.
int
AESCipher(unsigned char* returnText, unsigned char* plainText, unsigned int plainTextLen, unsigned char* key, unsigned char* iv, int algorithm, int mode){
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX));
int returnTextLength = 0;
unsigned long err = 0;
int retTextLen = 0;
int addLen = 0;
EVP_CIPHER_CTX_init(ctx);
/*
* MODE ENCYPRT
*/
if (mode == ENCRYPT){
if (algorithm == AES_CBC256){
if (EVP_EncryptInit(ctx, EVP_aes_256_cbc(), key, iv) != 1) {
err = ERR_get_error();
printf("ERR : EVP_Encrypt() - %s\n", ERR_error_string(err, NULL));
return -1;
}
}
else if (algorithm == AES_CBC128){
if (EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv) != 1) {
err = ERR_get_error();
printf("ERR : EVP_Encrypt() - %s\n", ERR_error_string(err, NULL));
return -1;
}
}
if (EVP_EncryptUpdate(ctx, returnText, &retTextLen, plainText, plainTextLen) != 1
|| (EVP_EncryptFinal(ctx, returnText + retTextLen, &addLen) != 1)) {
err = ERR_get_error();
printf("ERR : %s\n", ERR_error_string(err, NULL));
return -1;
}
}
/*
* MODE DECYPRT
*/
else if (mode == DECRYPT){
if (algorithm == AES_CBC256){
if (EVP_DecryptInit(ctx, EVP_aes_256_cbc(), key, iv) != 1){
//|| EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
err = ERR_get_error();
printf("ERR : EVP_Decrypt() - %s\n", ERR_error_string(err, NULL));
return -1;
}
}
else if (algorithm == AES_CBC128){
if (EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv) != 1){
//|| EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
err = ERR_get_error();
printf("ERR : EVP_Decrypt() - %s\n", ERR_error_string(err, NULL));
return -1;
}
}
if (EVP_DecryptUpdate(ctx, returnText, &retTextLen, plainText, plainTextLen) != 1
|| (EVP_DecryptFinal(ctx, returnText + retTextLen, &addLen) != 1)) {
err = ERR_get_error();
printf("ERR : %s\n", ERR_error_string(err, NULL));
return -1;
}
}
returnTextLength = addLen + retTextLen;
EVP_CIPHER_CTX_cleanup(ctx);
return returnTextLength;
}
'programming > 암호화 & 보안' 카테고리의 다른 글
[cipher] 양방향 SSL (2 way SSL) (0) | 2018.05.03 |
---|---|
[cipher] 암호화 기본 용어 정리 (0) | 2018.05.03 |
[cipher] 대칭키 암호화 (Symmetric key cipher) (0) | 2018.03.28 |
[cipher] PKI (0) | 2017.02.01 |
- Total
- Today
- Yesterday
- ucrtbase.dll
- Universal CRT
- full stack
- 비대칭키
- MEAN stack
- executable jar
- cipher
- iOS10
- remote debug
- rxswift
- HTTPS
- TLS1.2
- 암호화
- TypedArray
- JavaScript
- build set
- yss
- 윈도우 라이브러리
- 대칭키
- Node.js
- PCX
- reactivex
- node js
- App Transport Security
- ATS
- execute double click
- AES
- 전자서명
- angular
- Visual Studio
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |