2017-01-24 112 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意味着它的生命,我仍然摹等「未定義的參考」錯誤。

任何想法?

+0

您可以通過以下OpenSSL的鏈接錯誤重複:?如何在GCC使用OpenSSL(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