2012-02-23 6 views
15

저는 (개인 키를 기반으로) 암호화하고 공개 키를 기반으로 해독하는 C 프로그램을 작성하고 있습니다. 나는 OpenSSL lib로 이것을하려고 노력하고있다. 누구든지 좋은 튜토리얼, 빠른 시작 가이드 또는 샘플 코드를 알고 있습니까? 나는 웹상에서 어떤 것도 찾지 못했다.RSA 암호화/암호 해독

+4

암호화에 대한 시동기부터 시작해야합니다. 당신은 일반적으로 공개 키로 암호화하고 개인 키로 해독합니다. –

답변

30

여기서 I 대칭 알고리즘 비대칭 알고리즘 AES-128-CBC 위해 RSA를 사용하여 파일을 암호화하기 위해 생성하는 예에는 OpenSSL EVP 함수와 같습니다

#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; 
} 

나는 상당히 쉽게 따라갈 수 있다고 생각합니다.

+0

대칭 암호화 알고리즘을 비대칭 공개 키 암호화 시스템 RSA로 가져 오는 이유를 이해할 수 없습니까? 이것도 맞습니까? – scarface

+4

@scarface : 여러 가지 이유로 인해 비대칭 키 시스템은 대량 데이터를 암호화하는 데 사용되지 않습니다. 대칭 키 시스템은 자체적으로 대량 데이터를 암호화하는 데 사용되는 대칭 키 시스템의 키를 암호화하는 데 사용됩니다. 이것이 바로 EVP * "봉투 암호화"기능이 작동하는 방식입니다. – caf

+0

완벽합니다. 고맙습니다. – scarface

관련 문제