2014-09-04 8 views
1

Apache 로그를 암호화하는 데 문제가 있습니다. OpenSSL EVP 기능을 사용하여 로그를 암호화하고 (예 : RSA 공개 키로 감싼 대칭 키 사용) 수신 로그 스트림을 디스크로 암호화합니다. 이렇게하려면 Apache에서 ErrorLog 지시문을 사용하여 STDIN의 로그를 암호화하고 디스크로 리디렉션하는 바이너리를 만들어야한다고 생각합니다.Apache 로그 RSA 암호화

다른 게시물에서 암호화가 작동한다고 생각합니다.

#include <stdio.h> 
#include <stdlib.h> 

#include <openssl/evp.h> 
#include <openssl/pem.h> 
#include <openssl/rsa.h> 
#include <openssl/err.h> 

#include <arpa/inet.h> /* For htonl() */ 

int do_evp_seal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file) 
{ 
    int retval = 0; 
    RSA *rsa_pkey = NULL; 
    EVP_PKEY *pkey = EVP_PKEY_new(); 
    EVP_CIPHER_CTX ctx; 
    unsigned char buffer[4096]; 
    unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH]; 
    size_t len; 
    int len_out; 
    unsigned char *ek = NULL; 
    int eklen; 
    uint32_t eklen_n; 
    unsigned char iv[EVP_MAX_IV_LENGTH]; 

    if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa_pkey, NULL, NULL)) 
    { 
     fprintf(stderr, "Error loading RSA Public Key File.\n"); 
     ERR_print_errors_fp(stderr); 
     retval = 2; 
     goto out; 
    } 

    if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey)) 
    { 
     fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n"); 
     retval = 3; 
     goto out; 
    } 

    EVP_CIPHER_CTX_init(&ctx); 
    ek = malloc(EVP_PKEY_size(pkey)); 

    if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1)) 
    { 
     fprintf(stderr, "EVP_SealInit: failed.\n"); 
     retval = 3; 
     goto out_free; 
    } 

    /* First we write out the encrypted key length, then the encrypted key, 
    * then the iv (the IV length is fixed by the cipher we have chosen). 
    */ 

    eklen_n = htonl(eklen); 
    if (fwrite(&eklen_n, sizeof eklen_n, 1, out_file) != 1) 
    { 
     perror("output file"); 
     retval = 5; 
     goto out_free; 
    } 
    if (fwrite(ek, eklen, 1, out_file) != 1) 
    { 
     perror("output file"); 
     retval = 5; 
     goto out_free; 
    } 
    if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, out_file) != 1) 
    { 
     perror("output file"); 
     retval = 5; 
     goto out_free; 
    } 

    /* Now we process the input file and write the encrypted data to the 
    * output file. */ 

    while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0) 
    { 
     if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len)) 
     { 
      fprintf(stderr, "EVP_SealUpdate: failed.\n"); 
      retval = 3; 
      goto out_free; 
     } 

     if (fwrite(buffer_out, len_out, 1, out_file) != 1) 
     { 
      perror("output file"); 
      retval = 5; 
      goto out_free; 
     } 
    } 

    if (ferror(in_file)) 
    { 
     perror("input file"); 
     retval = 4; 
     goto out_free; 
    } 

    if (!EVP_SealFinal(&ctx, buffer_out, &len_out)) 
    { 
     fprintf(stderr, "EVP_SealFinal: failed.\n"); 
     retval = 3; 
     goto out_free; 
    } 

    if (fwrite(buffer_out, len_out, 1, out_file) != 1) 
    { 
     perror("output file"); 
     retval = 5; 
     goto out_free; 
    } 

    out_free: 
    EVP_PKEY_free(pkey); 
    free(ek); 

    out: 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    FILE *rsa_pkey_file; 
    int rv; 

    if (argc < 2) 
    { 
     fprintf(stderr, "Usage: %s <PEM RSA Public Key File>\n", argv[0]); 
     exit(1); 
    } 

    rsa_pkey_file = fopen(argv[1], "rb"); 
    if (!rsa_pkey_file) 
    { 
     perror(argv[1]); 
     fprintf(stderr, "Error loading PEM RSA Public Key File.\n"); 
     exit(2); 
    } 

    rv = do_evp_seal(rsa_pkey_file, stdin, stdout); 

    fclose(rsa_pkey_file); 
    return rv; 
} 

및 암호 해독 :

#include <stdio.h> 
#include <stdlib.h> 

#include <openssl/evp.h> 
#include <openssl/pem.h> 
#include <openssl/rsa.h> 
#include <openssl/err.h> 

#include <arpa/inet.h> /* For htonl() */ 

int do_evp_unseal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file) 
{ 
    int retval = 0; 
    RSA *rsa_pkey = NULL; 
    EVP_PKEY *pkey = EVP_PKEY_new(); 
    EVP_CIPHER_CTX ctx; 
    unsigned char buffer[4096]; 
    unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH]; 
    size_t len; 
    int len_out; 
    unsigned char *ek; 
    unsigned int eklen; 
    uint32_t eklen_n; 
    unsigned char iv[EVP_MAX_IV_LENGTH]; 

    if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL)) 
    { 
     fprintf(stderr, "Error loading RSA Private Key File.\n"); 
     ERR_print_errors_fp(stderr); 
     retval = 2; 
     goto out; 
    } 

    if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey)) 
    { 
     fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n"); 
     retval = 3; 
     goto out; 
    } 

    EVP_CIPHER_CTX_init(&ctx); 
    ek = malloc(EVP_PKEY_size(pkey)); 

    /* First need to fetch the encrypted key length, encrypted key and IV */ 

    if (fread(&eklen_n, sizeof eklen_n, 1, in_file) != 1) 
    { 
     perror("input file"); 
     retval = 4; 
     goto out_free; 
    } 
    eklen = ntohl(eklen_n); 
    if (eklen > EVP_PKEY_size(pkey)) 
    { 
     fprintf(stderr, "Bad encrypted key length (%u > %d)\n", eklen, 
      EVP_PKEY_size(pkey)); 
     retval = 4; 
     goto out_free; 
    } 
    if (fread(ek, eklen, 1, in_file) != 1) 
    { 
     perror("input file"); 
     retval = 4; 
     goto out_free; 
    } 
    if (fread(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, in_file) != 1) 
    { 
     perror("input file"); 
     retval = 4; 
     goto out_free; 
    } 

    if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey)) 
    { 
     fprintf(stderr, "EVP_OpenInit: failed.\n"); 
     retval = 3; 
     goto out_free; 
    } 

    while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0) 
    { 
     if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len)) 
     { 
      fprintf(stderr, "EVP_OpenUpdate: failed.\n"); 
      retval = 3; 
      goto out_free; 
     } 

     if (fwrite(buffer_out, len_out, 1, out_file) != 1) 
     { 
      perror("output file"); 
      retval = 5; 
      goto out_free; 
     } 
    } 

    if (ferror(in_file)) 
    { 
     perror("input file"); 
     retval = 4; 
     goto out_free; 
    } 

    if (!EVP_OpenFinal(&ctx, buffer_out, &len_out)) 
    { 
     fprintf(stderr, "EVP_SealFinal: failed.\n"); 
     retval = 3; 
     goto out_free; 
    } 

    if (fwrite(buffer_out, len_out, 1, out_file) != 1) 
    { 
     perror("output file"); 
     retval = 5; 
     goto out_free; 
    } 

    out_free: 
    EVP_PKEY_free(pkey); 
    free(ek); 

    out: 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    FILE *rsa_pkey_file; 
    int rv; 

    if (argc < 2) 
    { 
     fprintf(stderr, "Usage: %s <PEM RSA Private Key File>\n", argv[0]); 
     exit(1); 
    } 

    rsa_pkey_file = fopen(argv[1], "rb"); 
    if (!rsa_pkey_file) 
    { 
     perror(argv[1]); 
     fprintf(stderr, "Error loading PEM RSA Private Key File.\n"); 
     exit(2); 
    } 

    rv = do_evp_unseal(rsa_pkey_file, stdin, stdout); 

    fclose(rsa_pkey_file); 
    return rv; 
} 

제가 아파치에있는이 지침은 다음과 같습니다 내 암호화 코드는

ErrorLog "|/home/Desktop/encrypt /home/Desktop/public.pem > /home/Desktop/output.log" 

하지만 아파치를 다시 시작하고, 출력을 검색하기 시작합니다. 로그 파일이 나타나지 않습니다. 쉘 프롬프트에서 암호화 기능을 실행하면 예상대로 결과가 생성됩니다.

도움말!

답변

0

명령 줄에서 정상적으로 작동하는 경우 Apache에 바탕 화면에 쓸 수있는 권한이없는 것일 수 있습니다. Apache docs에서

:

파이프 로그 프로세스는 부모 아파치 httpd 프로세스가 띄우고, 프로세스의 사용자 ID를 상속하고 있습니다.

output.log 파일에 대한 하위 디렉토리를 만들고, chown을 사용하여 Apache에서 쓰기를 허용하십시오.

+0

감사합니다. 트릭을 수행 한 것처럼 보였습니다! 지금 다른 문제가 하나 있는데, 다른 스레드에서 더 나을 수도 있습니다.하지만 누군가 먼저 여기에 대해 알고 있는지 궁금합니다. 출력은 4096 바이트 덩어리의 파일에만 나타납니다 (아마도 STDIN에서 읽는 버퍼 때문에). 파일에 출력을 플러시하여 모든 출력이 출력되도록하는 방법이 있습니까? 나는 while 루프가 STDIN으로부터 입력을 계속 받기 위해 무한 루프가되어야하기 때문에 어떻게해야하는지 이해하지 못한다. – user4005750

+0

@ user4005750 암호화를 위해 블록 암호를 사용한다면 그건 불가능하다. RC4와 같은 스트림 암호에 더 많은 행운이 있을지 모르지만, 당신이 말했듯이 다른 스레드에서 이것을 묻는 것이 나을 것입니다. –