2011-12-20 9 views
0

私はここで間違っていますか?私は何かが欠けている必要があります..evp_sealinit/evp_openinit apiを使用しているときに正しいデータ(通常は最初の16バイト)が得られません。私はここで間違って何をしていますか?

私はEVP_Seal/EVP_Open APIを使用しています。公開鍵/秘密鍵と証明書を生成しました。私はいくつかの厄介なことを見ている - 私はデコード後に戻ってきている最初の16bytesはゴミです。私のデータが小さい(16バイトより小さい)場合は、EVP_Open関数からの出力が得られません。

HERESに私のテストプログラム:

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

    #include <openssl/ssl.h> 
    #include <openssl/err.h> 
    #include <openssl/rsa.h> 
    #include <openssl/pem.h> 
    #include <openssl/err.h> 
    #include <openssl/rand.h> 

    #define PORT 6999 
    #define HOST "localhost" 

    #define PUBLIC_KEYFILE "pubkey.pem" 
    #define CERT_FILE "server.crt" 

    #define PRIVATE_KEYFILE "server.key" 

    void run_client(void); 

    EVP_CIPHER_CTX en_ctx; 
    EVP_CIPHER_CTX de_ctx; 

    typedef struct { 
    int keylen; 
    unsigned char key[512]; 
    unsigned char iv[EVP_MAX_IV_LENGTH]; 
    } keys_t; 

    unsigned char msg[1024]; 
    unsigned char enc_buf[1024]; 
    unsigned char de_buf[1024]; 


    int main(int argc, char **argv) 
    { 

    // Init malloc, free etc for OpenSSL's CRYPTO_malloc_init(); 
    ERR_load_BIO_strings();  
    OpenSSL_add_all_algorithms(); 
    run_client(); 

    return 0; 

    } 

    int encrypt_with_cert(unsigned char **secret_key, int *keylen, 
          unsigned char **out_iv, 
        unsigned char *data, int *datalen) 
    { 
    FILE *fp; 
    X509 *x509; 
    EVP_PKEY *pkey; 

     unsigned char *ek; 
     int eklen; 
    int retval = 0; 
    unsigned char iv[EVP_MAX_IV_LENGTH]; 
    int i=0; 

     RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH); 

     fp = fopen(CERT_FILE, "r"); 
    if (!fp) { 
     fprintf(stderr, "Cannot open certificate file\n"); 
     goto out; 
    } 

    x509 = PEM_read_X509(fp, NULL, 0, NULL); 
    if (x509 == NULL) { 
     ERR_print_errors_fp(stderr); 
     goto out; 
    } 
    fclose(fp); 

    pkey = X509_extract_key(x509); 

    X509_free(x509); 

    if (pkey == NULL) { 
     ERR_print_errors_fp(stderr); 
    } 

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

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

    int buf_len = 0; 
    int tot_len = 0; 

    printf("Encoding string: {%s}, len: %d\n", data, *datalen); 
    memset(enc_buf, 0 , 1024); 

    EVP_SealInit(&en_ctx, NULL, NULL, NULL, NULL, NULL, 1); 
    EVP_SealUpdate(&en_ctx, enc_buf, &buf_len, data, *datalen); 
    tot_len += buf_len; 

    EVP_SealFinal(&en_ctx, enc_buf+buf_len, &buf_len); 
    tot_len += buf_len; 

    *(enc_buf + tot_len) = '\0'; 
    *datalen = tot_len; 

    printf("Encoded length: %d\n", tot_len); 
    printf("Encoded message: {"); 
    for (i=0; i< tot_len; i++) { 
    printf("%02x", enc_buf[i]); 
    } 
    printf("}\n"); 

    goto out; 

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

     out: 
    *secret_key = ek; 
    *keylen = eklen; 
    *out_iv = iv; 
    return retval; 
    } 

    void decrypt_message(unsigned char *secret_key, int keylen, 
         unsigned char *iv, int buflen) 
    { 
    FILE *privkey; 

    int retval = 0; 
    int klen=0; 

    int tot_len = 0; 
    EVP_PKEY *pkey; 
    int i = 0; 

    privkey = fopen(PRIVATE_KEYFILE, "r"); 
    if (!privkey) { 
     fprintf(stderr, "Error opening private key\n"); 
     } 

    pkey = PEM_read_PrivateKey(privkey, NULL, 0 , NULL); 
    if (!pkey) { 
     fprintf(stderr, "Error loading Server's RSA private key\n"); 
     retval = 2; 
     goto out; 
    } 


    if(keylen != EVP_PKEY_size(pkey)) { 
     EVP_PKEY_free(pkey); 
     fprintf(stderr, "keylength mismatch!\n"); 
     retval = 2; 
     goto out; 
    }  

    klen = EVP_OpenInit(&de_ctx, EVP_aes_256_cbc(), secret_key, keylen, iv, pkey); 
    if (klen == 0) { 
     fprintf(stderr, "EVP_OpenInit failed\n"); 
    } 

    int de_len = 0; 
    tot_len = 0; 

    printf("\n\nNow decoding..\n"); 
    printf("Encoded length: %d\n", buflen); 
    printf("Encoded message: {"); 
    for (i=0; i< buflen; i++) { 
     printf("%02x", enc_buf[i]); 
    } 
    printf("}\n"); 


    EVP_OpenInit(&de_ctx, NULL, NULL, keylen, NULL, NULL); 
    EVP_OpenUpdate(&de_ctx, de_buf, &de_len, enc_buf, buflen); 
    tot_len += de_len; 


    EVP_OpenFinal(&de_ctx, de_buf+tot_len, &de_len); 
    tot_len += de_len; 
    *(de_buf+tot_len) = '\0'; 


    printf("Decoded length: %d, String: %s\n", tot_len, de_buf); 

    out: 
    fclose(privkey); 
return; 
    } 

    void run_client() 
    { 

    unsigned char *secret_key = NULL; 
    int keylen; 
    unsigned char *iv = NULL; 
    int data_len = 0; 
    int retval = 0; 

    //strcpy((char *)msg, "abcdefghijklmnopqrstuvwxyz"); 
    //strcpy((char *)msg, "this is a secret message\n"); 


     strcpy((char *)msg, "1234567890"); 

     data_len = strlen((char *)msg) + 1; 

    retval = encrypt_with_cert(&secret_key, &keylen, &iv, msg, &data_len); 
    if (retval != 0) { 
    printf("encrypt with certificate failed! retval = %d\n", retval); 
    } 

    decrypt_message(secret_key, keylen, iv, data_len); 

    } 

私はここにこれを実行して、私が得るものです: [サンプル] $のgcc -Wall -g -o openssl_seal -lcrypto openssl_seal.c

[sample]$ ./openssl_seal 
    Encoding string: {1234567890}, len: 11 
    Encoded length: 16 
    Encoded message: {9753c483d6816b64693f604b2376f0a0} 


    Now decoding.. 
    Encoded length: 16 
    Encoded message: {9753c483d6816b64693f604b2376f0a0} 
    Decoded length: 0, String: 


    [sample]$ gcc -Wall -g -o openssl_seal -lcrypto openssl_seal.c 
    [sample]$ ./openssl_seal 
    Encoding string: {abcdefghijklmnopqrstuvwxyz}, len: 37 
    Encoded length: 48 
    Encoded message:   {ad264f30fe70cc6f9c8d712073bc72049e7f7515a28c1cf0aeef648d6c4c4bfd717ae2fd21396bb95eb7ec0ce88f7f9d} 


    Now decoding.. 
    Encoded length: 48 
    Encoded message: {ad264f30fe70cc6f9c8d712073bc72049e7f7515a28c1cf0aeef648d6c4c4bfd717ae2fd21396bb95eb7ec0ce88f7f9d} 
    Decoded length: 37, String: abcd.VO[vтOqrstuvwxyz

答えて

0

EVP_SealInitを2回呼び出して、もう一度ivパラメータを無視しているようです。このメソッドは、IVパラメータを保存して復号化側に送信するだけで、このメソッドを1回呼び出す必要があります。同様にEVP_OpenInitに一度だけ電話する必要があります。

+0

いいえ、それはどちらもうまくいきません。 2番目の呼び出しを削除しようとしましたが、同じ結果が得られます。マニュアルページによると、型がNULLに設定されている限り、その機能を2回呼び出すことができます。すべてのNULL値を無視し、コンテキストのNULL以外の値を上書きします。 – Poornima

関連する問題