2017-01-24 11 views
0

Я пытаюсь собрать следующую программу:Невозможно скомпилировать код с использованием OpenSSL библиотеки/функции

#include <openssl/conf.h> 
#include <openssl/evp.h> 
#include <openssl/err.h> 

#include <openssl/crypto.h> 

#include <string.h> 

int main (void) 
{ 
    /* Set up the key and iv. Do I need to say to not hard code these in a 
    * real application? :-) 
    */ 

    /* A 256 bit key */ 
    unsigned char *key = (unsigned char *)""; 

    /* A 128 bit IV */ 
    unsigned char *iv = (unsigned char *)""; 

    /* Message to be encrypted */ 
    unsigned char *plaintext = 
       (unsigned char *)"The quick brown fox jumps over the lazy dog"; 

    /* Buffer for ciphertext. Ensure the buffer is long enough for the 
    * ciphertext which may be longer than the plaintext, dependant on the 
    * algorithm and mode 
    */ 
    unsigned char ciphertext[128]; 

    /* Buffer for the decrypted text */ 
    unsigned char decryptedtext[128]; 

    int decryptedtext_len, ciphertext_len; 

    /* Initialise the library */ 
    ERR_load_crypto_strings(); 
    OpenSSL_add_all_algorithms(); 
    OPENSSL_config(NULL); 

    /* Encrypt the plaintext */ 
    ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv, 
          ciphertext); 

    /* Do something useful with the ciphertext here */ 
    printf("Ciphertext is:\n"); 
    BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len); 

    /* Decrypt the ciphertext */ 
    decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv, 
    decryptedtext); 

    /* Add a NULL terminator. We are expecting printable text */ 
    decryptedtext[decryptedtext_len] = '\0'; 

    /* Show the decrypted text */ 
    printf("Decrypted text is:\n"); 
    printf("%s\n", decryptedtext); 

    /* Clean up */ 
    EVP_cleanup(); 
    ERR_free_strings(); 

    return 0; 
} 


int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, 
    unsigned char *iv, unsigned char *ciphertext) 
{ 
    EVP_CIPHER_CTX *ctx; 

    int len; 

    int ciphertext_len; 

    /* Create and initialise the context */ 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 

    /* Initialise the encryption operation. IMPORTANT - ensure you use a key 
    * and IV size appropriate for your cipher 
    * In this example we are using 256 bit AES (i.e. a 256 bit key). The 
    * IV size for *most* modes is the same as the block size. For AES this 
    * is 128 bits */ 
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) 
    handleErrors(); 

    /* Provide the message to be encrypted, and obtain the encrypted output. 
    * EVP_EncryptUpdate can be called multiple times if necessary 
    */ 
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) 
    handleErrors(); 
    ciphertext_len = len; 

    /* Finalise the encryption. Further ciphertext bytes may be written at 
    * this stage. 
    */ 
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); 
    ciphertext_len += len; 

    /* Clean up */ 
    EVP_CIPHER_CTX_free(ctx); 

    return ciphertext_len; 
} 



int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, 
    unsigned char *iv, unsigned char *plaintext) 
{ 
    EVP_CIPHER_CTX *ctx; 

    int len; 

    int plaintext_len; 

    /* Create and initialise the context */ 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 

    /* Initialise the decryption operation. IMPORTANT - ensure you use a key 
    * and IV size appropriate for your cipher 
    * In this example we are using 256 bit AES (i.e. a 256 bit key). The 
    * IV size for *most* modes is the same as the block size. For AES this 
    * is 128 bits */ 
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) 
    handleErrors(); 

    /* Provide the message to be decrypted, and obtain the plaintext output. 
    * EVP_DecryptUpdate can be called multiple times if necessary 
    */ 
    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) 
    handleErrors(); 
    plaintext_len = len; 

    /* Finalise the decryption. Further plaintext bytes may be written at 
    * this stage. 
    */ 
    if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors(); 
    plaintext_len += len; 

    /* Clean up */ 
    EVP_CIPHER_CTX_free(ctx); 

    return plaintext_len; 
} 



void handleErrors(void) 
{ 
    ERR_print_errors_fp(stderr); 
    abort(); 
} 

Эта программа из https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption

Во всяком случае, когда я пытаюсь скомпилировать его я получаю следующее ошибки:

test.c: In function âmainâ: 
test.c:39:3: warning: âOPENSSL_configâ is deprecated [-Wdeprecated-declarations] 
    OPENSSL_config(NULL); 
^
In file included from /usr/local/include/openssl/crypto.h:32:0, 
       from /usr/local/include/openssl/bio.h:20, 
       from /usr/local/include/openssl/conf.h:13, 
       from test.c:1: 
/usr/local/include/openssl/conf.h:92:1: note: declared here 
DEPRECATEDIN_1_1_0(void OPENSSL_config(const char *config_name)) 
^ 
test.c:42:20: warning: implicit declaration of function âencryptâ [-Wimplicit-function-declaration] 
    ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv, 
        ^
test.c:50:23: warning: implicit declaration of function âdecryptâ [-Wimplicit-function-declaration] 
    decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv, 
        ^
test.c: In function âencryptâ: 
test.c:78:37: warning: implicit declaration of function âhandleErrorsâ [-Wimplicit-function-declaration] 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 
            ^
test.c: At top level: 
test.c:150:6: warning: conflicting types for âhandleErrorsâ 
void handleErrors(void) 
    ^
test.c:78:37: note: previous implicit declaration of âhandleErrorsâ was here 
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); 
            ^
/tmp/ccmG8aWM.o: In function `main': 
test.c:(.text+0x47): undefined reference to `OPENSSL_init_crypto' 
test.c:(.text+0x58): undefined reference to `OPENSSL_init_crypto' 
test.c:(.text+0x65): undefined reference to `OPENSSL_config' 
test.c:(.text+0xd1): undefined reference to `BIO_dump_fp' 
/tmp/ccmG8aWM.o: In function `encrypt': 
test.c:(.text+0x186): undefined reference to `EVP_CIPHER_CTX_new' 
test.c:(.text+0x199): undefined reference to `EVP_aes_256_cbc' 
test.c:(.text+0x1ad): undefined reference to `EVP_EncryptInit_ex' 
test.c:(.text+0x1d2): undefined reference to `EVP_EncryptUpdate' 
test.c:(.text+0x1ff): undefined reference to `EVP_EncryptFinal_ex' 
test.c:(.text+0x21d): undefined reference to `EVP_CIPHER_CTX_free' 
/tmp/ccmG8aWM.o: In function `decrypt': 
test.c:(.text+0x264): undefined reference to `EVP_CIPHER_CTX_new' 
test.c:(.text+0x277): undefined reference to `EVP_aes_256_cbc' 
test.c:(.text+0x28b): undefined reference to `EVP_DecryptInit_ex' 
test.c:(.text+0x2b0): undefined reference to `EVP_DecryptUpdate' 
test.c:(.text+0x2dd): undefined reference to `EVP_DecryptFinal_ex' 
test.c:(.text+0x2fb): undefined reference to `EVP_CIPHER_CTX_free' 
/tmp/ccmG8aWM.o: In function `handleErrors': 
test.c:(.text+0x328): undefined reference to `ERR_print_errors_fp' 
collect2: error: ld returned 1 exit status 

Я добавил #include <openssl/crypto.h> к исходному коду, так что там https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_init_crypto.html означает, что он живет, и я до сих пор г et "ошибки неопределенной ссылки".

Любые идеи?

+0

Вот ваши дубликаты за ошибки связи OpenSSL: [? Как использовать OpenSSL в GCC] (http://stackoverflow.com/q/1894013/608639) и [Ошибки, которые ссылаются на кучу нерешенным Символы OpenSSL, которые явно существуют?] (Http://stackoverflow.com/q/15318978/608639) – jww

ответ

2

В заголовочные файлы, которые вы включили, даются декларации функций OpenSSL. Тем не менее, фактическая библиотека по-прежнему должна быть связана.

При компиляции вам необходимо добавить -lcrypto в конец командной строки gcc для связи в библиотеке криптографии OpenSSL.

Кроме того, вы используете функции в своем собственном коде, прежде чем определять их. В результате компилятор неявно объявляет их как принимающие произвольное количество аргументов и возвращающихся в int. Поскольку это соответствует фактическому объявлению, это приводит к неопределенному поведению.

Вы должны создать объявления для каждой из своих функций в верхней части файла. Таким образом, другие функции знают, как их называть.

#include <openssl/conf.h> 
#include <openssl/evp.h> 
#include <openssl/err.h> 

#include <openssl/crypto.h> 

#include <string.h> 

int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, 
    unsigned char *iv, unsigned char *ciphertext); 
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, 
    unsigned char *iv, unsigned char *plaintext); 
void handleErrors(void); 

int main(void) 
{ 
    ... 
+0

Я сделал предложенные изменения и сделал gcc -lcrypto test.c' и получил следующие ошибки: http: // pastebin .com/WKwx1NDv – neubert

+1

@neubert Поместите '-lcrypto' в конце команды. – dbush