2016-08-04 3 views
1

암호화 및 암호 해독 기능을 개발하고 싶습니다. 키 크기는 최소 128 비트 (16 바이트) 여야합니다.크기가 16의 배수가 아닌 암호화 된 데이터 생성

나는 OpenSSL의 AES* API 함수를 사용했습니다. AES* 함수에는 몇 가지 제한이 있습니다. 입력 데이터 버퍼는 16의 배수 여야합니다! 내 기능 후 다음

:

unsigned char encrypt_aes_key[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; 

static inline int enc_array_decrypt(unsigned char *encarray, unsigned char *decarray, int size) 
{ 
    int i; 
    AES_KEY dec_key; 
    unsigned char apibuf[512] = {0}; 
    unsigned char iv[AES_BLOCK_SIZE]; 
    memset(iv, 0x00, AES_BLOCK_SIZE); 

    AES_set_decrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &dec_key); // Size of key is in bits 
    AES_cbc_encrypt(encarray, apibuf, size, &dec_key, iv, AES_DECRYPT); 
    memcpy(decarray, apibuf, size); 

    return 0; 
} 

static inline int enc_array_encrypt(unsigned char *array, unsigned char *encarray, int size) 
{ 
    int i; 
    AES_KEY enc_key; 
    unsigned char apibuf[512] = {0}; 
    unsigned char iv[AES_BLOCK_SIZE]; 
    memset(iv, 0x00, AES_BLOCK_SIZE); 

    AES_set_encrypt_key(encrypt_aes_key, sizeof(encrypt_aes_key)*8, &enc_key); // Size of key is in bits 
    AES_cbc_encrypt((unsigned char *)array, apibuf, size, &enc_key, iv, AES_ENCRYPT); 
    memcpy(encarray, apibuf, size); 

    return 0; 
} 

내가 예를 들어, 기능 wron 출력

예를 반환합니다 버퍼 크기 (9) 내 함수를 호출하는 경우 :

int main(int argc, char *argv[]) 
{ 
    char buf[9] = {0}, encbuf[9] = {0}, decbuf[9] = {0}; 
    strcpy(buf, argv[1]); 

    enc_array_encrypt(buf, encbuf, 9); 
    enc_array_decrypt(encbuf, decbuf, 9); 

    printf("%s \n%s\n", buf, decbuf); 

    return 0; 
} 

프로그램 반환 :

$ ./myprogram any 
any 
2�����S� 

어떻게 해결할 수 있습니까?

나는 버퍼를 16 배수 크기로 강제 설정할 수 없습니다. 왜냐하면 필자는 다른 함수를 여러 입력 버퍼 크기로 호출하는 커다란 소스 코드 (SDK)에서 함수를 통합 할 것이기 때문입니다.

다른 종류의 암호화 (AES 제외)를 사용할 수 있지만 128 비트 길이의 키를 지원해야합니다. 입력 버퍼와 암호화 된 버퍼의 크기는 동일해야합니다.

+1

AES로 16보다 큰 블록 크기를 가질 수 있다고 생각하지 않습니다. 일관된 결과를 얻으려면 가장 가까운 16 바이트까지 라운드 버퍼 크기와 0으로 채운 바이트를 채 웁니다. – user694733

+0

@ user694733 다른 종류의 암호화 (AES 제외)를 사용하기 위해 열었지만 길이가 128 인 키를 지원해야합니다. – MOHAMED

+1

@ user694733 널 패딩을 추가하지 마십시오. 안전하지 않고 바이너리 데이터와 함께 사용할 수 있습니다. [PKCS # 7 패딩 [(https://en.wikipedia.org/wiki/Padding_ (cryptography) # PKCS7)을 사용하십시오. – zaph

답변

1

일반적으로 OpenSSL에서 AES * 기능을 직접 사용하지 않는 것이 좋습니다. EVP 제품군을 사용하는 것이 좋습니다. 이것들을 사용하면 (자), 임의의 길이의 입력 버퍼를 지정할 수 있습니다.

void log_ssl_err(const char *mes) 
{ 
    unsigned long err; 
    char errstr[1000]; 

    while ((err = ERR_get_error())) { 
     ERR_error_string(err, errstr); 
     printf("%s: %s", mes, errstr); 
    } 
} 

int encrypt_block(const unsigned char *IV, const unsigned char *key, 
        const unsigned char *src, unsigned int srclen, 
        unsigned char *dest, unsigned int *destlen) 
{ 
    EVP_CIPHER_CTX ctx; 
    const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC"); 
    int mode, len; 

    if (cipher == NULL) { 
     printf("Invalid keytype"); 
     return 0; 
    } 
    mode = EVP_CIPHER_mode(cipher); 
    EVP_CIPHER_CTX_init(&ctx); 
    if (!EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) { 
     log_ssl_err("EncryptInit for cipher failed"); 
     return 0; 
    } 
    if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, IV)) { 
     log_ssl_err("EncryptInit for key/IV failed"); 
     return 0; 
    } 
    len = 0; 
    if (!EVP_EncryptUpdate(&ctx, dest, &len, src, srclen)) { 
     log_ssl_err("EncryptUpdate for data failed"); 
     EVP_CIPHER_CTX_cleanup(&ctx); 
     return 0; 
    } 
    *destlen = len; 
    if (!EVP_EncryptFinal_ex(&ctx, dest + *destlen, &len)) { 
     log_ssl_err("EncryptFinal failed"); 
     EVP_CIPHER_CTX_cleanup(&ctx); 
     return 0; 
    } 
    *destlen += len; 
    EVP_CIPHER_CTX_cleanup(&ctx); 

    return 1; 
} 

int decrypt_block(const unsigned char *IV, const unsigned char *key, 
        unsigned char *src, unsigned int srclen, 
        unsigned char *dest, unsigned int *destlen) 
{ 
    EVP_CIPHER_CTX ctx; 
    const EVP_CIPHER *cipher = EVP_get_cipherbyname("AES-256-CBC"); 
    int mode, len; 

    if (cipher == NULL) { 
     printf("Invalid keytype"); 
     return 0; 
    } 
    mode = EVP_CIPHER_mode(cipher); 
    EVP_CIPHER_CTX_init(&ctx); 
    if (!EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL)) { 
     log_ssl_err("DecryptInit for cipher failed"); 
     return 0; 
    } 
    if (!EVP_DecryptUpdate(&ctx, dest, &len, src, srclen)) { 
     log_ssl_err("DecryptUpdate for data failed"); 
     EVP_CIPHER_CTX_cleanup(&ctx); 
     return 0; 
    } 
    *destlen = len; 
    if (!EVP_DecryptFinal_ex(&ctx, dest + *destlen, &len)) { 
     log_ssl_err("DecryptFinal failed"); 
     EVP_CIPHER_CTX_cleanup(&ctx); 
     return 0; 
    } 
    *destlen += len; 
    EVP_CIPHER_CTX_cleanup(&ctx); 

    return 1; 
} 
+0

임의의 데이터 크기를 암호화 할 수있는 이유는 기본적으로 PKCS # 7 패딩을 추가하기 때문입니다. 모든 라이브러리 함수가 그렇게하지는 않습니다. – zaph

+0

의'encrypt_block()'함수에서'* destlen'의 최종 값은'srclen'과 같은가요? 내 입력 데이터 버퍼는 암호화 된 버퍼의 크기가 같아야합니다. – MOHAMED

+0

ompenssl wiki에서'* destlen = srclen + 1'을 이해하므로'EVP_ *'가 작동합니다. 1 바이트의 패딩을 만듭니다. 패딩 바이트는'EVP_EncryptFinal_ex' 함수에 의해 추가됩니다. 내가 맞습니까? – MOHAMED

관련 문제