c - Memcpy char** 的 typedef,它指向具有 4 个 uint64_t 类型变量的结构

标签 c

有这个代码:

typedef struct {
    struct {
        uint64_t key;
        uint64_t mac;
        uint64_t orig;
        uint64_t body;
    } length;
} secure_head_t;

typedef char *secure_t;

secure_t *secure_alloc(uint64_t key, uint64_t mac, uint64_t orig, uint64_t body) {
    secure_t *cryptex = (secure_t*)malloc(sizeof(secure_head_t) + key + mac + body);
    secure_head_t *head = (secure_head_t *)cryptex;
    head->length.key = key;
    head->length.mac = mac;
    head->length.orig = orig;
    head->length.body = body;
    return cryptex;
}

我想将 secure_t 转换为 char *, 类似于:char *str = secure_t *text;

我尝试过这个:

secure_head_t *head = (secure_head_t *)securetext;

char frame[sizeof(secure_head_t)];
memcpy(frame, &head, sizeof(secure_head_t));

但这并不是每次都有效,有时甚至无法复制。请告诉我如何正确复制它。我想要的只是将 secure_t* 转换为 char*,然后从 char* 转换回 secure_t*

更新:

我想将使用 OpenSSL 1.0.2 通过 ECDHA 加密的数据 block 转换为二进制缓冲区以便稍后解密。数据 block 的最小值为 1 KB,最大值为 1 MB。我可以控制整个过程,我用它来学习非对称和对称加密。

详细代码如下:

void Encryption(UnicodeString PlainText)
{
    srand(time(NULL));
    int tlen;
    size_t olen;
    EC_KEY *key = NULL;
    secure_t *ciphered = NULL;
    char *hex_pub = NULL, *hex_priv = NULL;

    char *text = NULL;
    tlen = PlainText.Length();
    text = new char [tlen];

    WideCharToMultiByte(CP_ACP, 0, PlainText.c_str(), wcslen(PlainText.c_str())+1, text , sizeof(char)*tlen, NULL, NULL);

    // Generate a key for our theoretical user.
    if (!(key = ecies_key_create()))
    {
      printf("Key creation failed.\n");
    }

    // Since we'll store the keys as hex values in reali life, extract the appropriate hex values and release the original key structure.
    if (!(hex_pub = ecies_key_public_get_hex(key)) || !(hex_priv = ecies_key_private_get_hex(key)))
    {
      printf("Serialization of the key to a pair of hex strings failed.\n");
    }
    //saving keys
    KeyPriv = AnsiString(hex_priv);
    KeyPub = AnsiString(hex_pub);

    if (!(ciphered = ecies_encrypt(hex_pub, text, tlen)))
    {
      printf("The encryption process failed!\n");
    }

    secure_head_t *head = (secure_head_t *)ciphered;

    char frame[sizeof(secure_head_t )];
    memcpy(frame, &head, sizeof(secure_head_t *));
    CipherText = frame;
}

void Decrypt(AnsiString CipherText)
{
  size_t olen;
  EC_KEY *key = NULL;
  secure_t *ciphered = NULL;
  char *hex_pub = NULL, *hex_priv = NULL;
  unsigned char *text = NULL, *copy = NULL, *original = NULL;


   secure_head_t *head = new secure_head_t;
   memcpy(&head, CipherText.c_str(), sizeof(char)*CipherText.Length());

   secure_t *cryptex = (secure_t*)head;

    hex_priv = KeyPriv.c_str();


  if(!(original = ecies_decrypt(hex_priv, cryptex, &olen)))
  {
    printf("The decryption process failed!\n");
  }

  PlainText = AnsiString((char*)original);
}

上面的代码可以工作,但有时不行,而且我不发送长度<25的字符串。

除 OpenSSL 代码外,其他代码如下所示

ecies.h
------------------------------------------------------------------------------
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    //#include <inttypes.h>
    #include<stdint.h>

    #include <openssl/ssl.h>
    #include <openssl/crypto.h>
    #include <openssl/err.h>
    #include <openssl/stack.h>

    #define ECIES_CURVE NID_secp521r1
    #define ECIES_CIPHER EVP_aes_256_cbc()
    #define ECIES_HASHER EVP_sha512()

    //EC_GROUP *eliptic = NULL;

    typedef struct {

            struct {
                    uint64_t key;
                    uint64_t mac;
                    uint64_t orig;
                    uint64_t body;
            } length;

    } secure_head_t;

    typedef char* secure_t;

    void secure_free(secure_t *cryptex);
    void * secure_key_data(secure_t *cryptex);
    void * secure_mac_data(secure_t *cryptex);
    void * secure_body_data(secure_t *cryptex);
    uint64_t secure_key_length(secure_t *cryptex);
    uint64_t secure_mac_length(secure_t *cryptex);
    uint64_t secure_body_length(secure_t *cryptex);
    uint64_t secure_orig_length(secure_t *cryptex);
    uint64_t secure_total_length(secure_t *cryptex);
    secure_t * secure_alloc(uint64_t key, uint64_t mac, uint64_t orig, uint64_t body);

    void ecies_group_init(void);
    void ecies_group_free(void);
    EC_GROUP * ecies_group(void);

    void ecies_key_free(EC_KEY *key);

    EC_KEY * ecies_key_create(void);
    EC_KEY * ecies_key_create_public_hex(char *hex);
    EC_KEY * ecies_key_create_private_hex(char *hex);
    EC_KEY * ecies_key_create_public_octets(unsigned char *octets, size_t length);

    char * ecies_key_public_get_hex(EC_KEY *key);
    char * ecies_key_private_get_hex(EC_KEY *key);

    secure_t * ecies_encrypt(char *key, unsigned char *data, size_t length);
    unsigned char * ecies_decrypt(char *key, secure_t *cryptex, size_t *length);
------------------------------------------------------------------------------
    **secure.c**
------------------------------------------------------------------------------
    #include "ecies.h"

    uint64_t secure_key_length(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return head->length.key;
    }

    uint64_t secure_mac_length(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return head->length.mac;
    }

    uint64_t secure_body_length(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return head->length.body;
    }

    uint64_t secure_orig_length(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return head->length.orig;
    }

    uint64_t secure_total_length(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return sizeof(secure_head_t) + (head->length.key + head->length.mac + 
    head->length.body);
    }

    void * secure_key_data(secure_t *cryptex) {
            return (char *)cryptex + sizeof(secure_head_t);
    }

    void * secure_mac_data(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return (char *)cryptex + (sizeof(secure_head_t) + head->length.key);
    }

    void * secure_body_data(secure_t *cryptex) {
            secure_head_t *head = (secure_head_t *)cryptex;
            return (char *)cryptex + (sizeof(secure_head_t) + head->length.key +
    head->length.mac);
    }

    secure_t * secure_alloc(uint64_t key, uint64_t mac, uint64_t orig, uint64_t body) {
            secure_t *cryptex = (secure_t*)malloc(sizeof(secure_head_t) + key + mac + body);
            secure_head_t *head = (secure_head_t *)cryptex;
            head->length.key = key;
            head->length.mac = mac;
            head->length.orig = orig;
            head->length.body = body;
            return cryptex;
    }

    void secure_free(secure_t *cryptex) {
            free(cryptex);
            return;
    }

------------------------------------------------------------------------------
ecies.c
-------------------------------------------------------------------------------
#include "ecies.h"
#include <openssl/keys.c>
#include <openssl/secure.c>
/*
void ecies_group_free(void) {

        EC_GROUP *group = eliptic;
        eliptic = NULL;
        if (group) {
                EC_GROUP_free(group);
        }
        return;
}    */

void * ecies_key_derivation(const void *input, size_t ilen, void *output,
                            size_t *olen) {

    if (*olen < SHA512_DIGEST_LENGTH) {
        return NULL;
    }

    *olen = SHA512_DIGEST_LENGTH;
    return SHA512((unsigned char*)input, ilen, (unsigned char*)output);
}

secure_t * ecies_encrypt(char *key, unsigned char *data, size_t length) {

    unsigned char *body;
    HMAC_CTX hmac;
    int body_length;
    secure_t *cryptex;
    EVP_CIPHER_CTX cipher;
    unsigned int mac_length;
    EC_KEY *user, *ephemeral;
    size_t envelope_length, block_length, key_length;
    unsigned char envelope_key[SHA512_DIGEST_LENGTH], iv[EVP_MAX_IV_LENGTH], block[EVP_MAX_BLOCK_LENGTH];

    // Simple sanity check.
    if (!key || !data || !length) {
        //printf("Invalid parameters passed in.\n");
        MessageBox ( NULL,L"Invalid parameters passed in.\n" ,L"Error", MB_OK );
        return NULL;
    }

    // Make sure we are generating enough key material for the symmetric ciphers.
    if ((key_length = EVP_CIPHER_key_length(ECIES_CIPHER)) * 2 > SHA512_DIGEST_LENGTH) {
        //printf("The key derivation method will not produce enough envelope key material for the chosen ciphers. {envelope = %i / required = %zu}", SHA512_DIGEST_LENGTH / 8,(key_length * 2) / 8);
        MessageBox ( NULL,L"The key derivation method will not produce enough envelope key material for the chosen ciphers. " ,L"Error", MB_OK );
        return NULL;
    }

    // Convert the user's public key from hex into a full EC_KEY structure.
    if (!(user = ecies_key_create_public_hex(key))) {
        //printf("Invalid public key provided.\n");
        MessageBox ( NULL,L"Invalid public key provided" ,L"Error", MB_OK );
        return NULL;
    }

    // Create the ephemeral key used specifically for this block of data.
    else if (!(ephemeral = ecies_key_create())) {
        //printf("An error occurred while trying to generate the ephemeral key.\n");
        MessageBox ( NULL,L"An error occurred while trying to generate the ephemeral key" ,L"Error", MB_OK );
        EC_KEY_free(user);
        return NULL;
    }

    // Use the intersection of the provided keys to generate the envelope data used by the ciphers below. The ecies_key_derivation() function uses
    // SHA 512 to ensure we have a sufficient amount of envelope key material and that the material created is sufficiently secure.
    else if (ECDH_compute_key(envelope_key, SHA512_DIGEST_LENGTH, EC_KEY_get0_public_key(user), ephemeral, ecies_key_derivation) !=
             SHA512_DIGEST_LENGTH) {
        //printf("An error occurred while trying to compute the envelope key. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"An error occurred while trying to compute the envelope key" ,L"Error", MB_OK );
        EC_KEY_free(ephemeral);
        EC_KEY_free(user);
        return NULL;
    }

    // Determine the envelope and block lengths so we can allocate a buffer for the result.
    else if ((block_length = EVP_CIPHER_block_size(ECIES_CIPHER)) == 0 || block_length > EVP_MAX_BLOCK_LENGTH ||
             (envelope_length = EC_POINT_point2oct(EC_KEY_get0_group(ephemeral), EC_KEY_get0_public_key(ephemeral),
                                                   POINT_CONVERSION_COMPRESSED, NULL, 0, NULL)) == 0) {
        //printf("Invalid block or envelope length. {block = %zu /envelope = %zu}\n", block_length, envelope_length);
        MessageBox ( NULL,L"Invalid block or envelope length" ,L"Error", MB_OK );
        EC_KEY_free(ephemeral);
        EC_KEY_free(user);
        return NULL;
    }

    // We use a conditional to pad the length if the input buffer is notevenly divisible by the block size.
    else if (!(cryptex = secure_alloc(envelope_length, EVP_MD_size(ECIES_HASHER), length, length + (length % block_length ? (block_length - (length % block_length)) : 0)))) {
        //printf("Unable to allocate a secure_t buffer to hold the encrypted result.\n");
        MessageBox ( NULL,L"Unable to allocate a secure_t buffer to hold the encrypted result" ,L"Error", MB_OK );
        EC_KEY_free(ephemeral);
        EC_KEY_free(user);
        return NULL;
    }

    // Store the public key portion of the ephemeral key.
    else if (EC_POINT_point2oct(EC_KEY_get0_group(ephemeral), EC_KEY_get0_public_key(ephemeral), POINT_CONVERSION_COMPRESSED, (unsigned char*)secure_key_data(cryptex), envelope_length,                        NULL) != envelope_length) {
        //printf("An error occurred while trying to record the public portion of the envelope key. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"An error occurred while trying to record the public portion of the envelope key" ,L"Error", MB_OK );
        EC_KEY_free(ephemeral);
        EC_KEY_free(user);
        secure_free(cryptex);
        return NULL;
    }

    // The envelope key has been stored so we no longer need to keep the keys around.
    EC_KEY_free(ephemeral);
    EC_KEY_free(user);

    // For now we use an empty initialization vector.
    memset(iv, 0, EVP_MAX_IV_LENGTH);

    // Setup the cipher context, the body length, and store a pointer to the body buffer location.
    EVP_CIPHER_CTX_init(&cipher);
    body = (unsigned char*)secure_body_data(cryptex);
    body_length = secure_body_length(cryptex);

    // Initialize the cipher with the envelope key.
    if (EVP_EncryptInit_ex(&cipher, ECIES_CIPHER, NULL, envelope_key, iv) != 1 || EVP_CIPHER_CTX_set_padding(&cipher, 0) != 1 || EVP_EncryptUpdate(&cipher, (unsigned char*)body,                        &body_length, data, length - (length % block_length)) != 1) {
        //printf("An error occurred while trying to secure the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"An error occurred while trying to secure the data using the chosen symmetric cipher." ,L"Error", MB_OK );
        EVP_CIPHER_CTX_cleanup(&cipher);
        secure_free(cryptex);
        return NULL;
    }

    // Check whether all of the data was encrypted. If they don't match up, we either have a partial block remaining, or an error occurred.
    else if (body_length != length) {

        // Make sure all that remains is a partial block, and their wasn't an error.
        if (length - body_length >= block_length) {
            //printf("Unable to secure the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
            MessageBox ( NULL,L"Unable to secure the data using the chosen symmetric cipher.." ,L"Error", MB_OK );
            EVP_CIPHER_CTX_cleanup(&cipher);
            secure_free(cryptex);
            return NULL;
        }

        // Copy the remaining data into our partial block buffer. The memset() call ensures any extra bytes will be zero'ed out.
        memset(block, 0, EVP_MAX_BLOCK_LENGTH);
        memcpy(block, data + body_length, length - body_length);

        // Advance the body pointer to the location of the remaining space, and calculate just how much room is still available.
        body += body_length;
        if ((body_length = secure_body_length(cryptex) - body_length) < 0) {
            //printf("The symmetric cipher overflowed!\n");
            MessageBox ( NULL,L"The symmetric cipher overflowed!" ,L"Error", MB_OK );
            EVP_CIPHER_CTX_cleanup(&cipher);
            secure_free(cryptex);
            return NULL;
        }

        // Pass the final partially filled data block into the cipher as a complete block. The padding will be removed during the decryption process.
        else if (EVP_EncryptUpdate(&cipher, body, &body_length, block, block_length) != 1) {
            //printf("Unable to secure the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
            MessageBox ( NULL,L"Unable to secure the data using the chosen symmetric cipher." ,L"Error", MB_OK );
            EVP_CIPHER_CTX_cleanup(&cipher);
            secure_free(cryptex);
            return NULL;
        }
    }

    // Advance the pointer, then use pointer arithmetic to calculate how much of the body buffer has been used. The complex logic is needed so that we get
    // the correct status regardless of whether there was a partial data block.
    body += body_length;
    if ((body_length = secure_body_length(cryptex) - (body - (unsigned char*)secure_body_data(cryptex))) < 0) {
        //printf("The symmetric cipher overflowed!\n");
        MessageBox ( NULL,L"The symmetric cipher overflowed!" ,L"Error", MB_OK );
        EVP_CIPHER_CTX_cleanup(&cipher);
        secure_free(cryptex);
        return NULL;
    }

    else if (EVP_EncryptFinal_ex(&cipher, body, &body_length) != 1) {
        //printf("Unable to secure the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"Unable to secure the data using the chosen symmetric cipher" ,L"Error", MB_OK );
        EVP_CIPHER_CTX_cleanup(&cipher);
        secure_free(cryptex);
        return NULL;
    }

    EVP_CIPHER_CTX_cleanup(&cipher);

    // Generate an authenticated hash which can be used to validate the data during decryption.
    HMAC_CTX_init(&hmac);
    mac_length = secure_mac_length(cryptex);

    // At the moment we are generating the hash using encrypted data. At some point we may want to validate the original text instead.
    if (HMAC_Init_ex(&hmac, envelope_key + key_length, key_length, ECIES_HASHER, NULL) != 1 || HMAC_Update(&hmac, (unsigned char*)secure_body_data(cryptex), secure_body_length(cryptex))
        != 1 || HMAC_Final(&hmac, (unsigned char*)secure_mac_data(cryptex), &mac_length) != 1) {
        //printf("Unable to generate a data authentication code. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"Unable to generate a data authentication code." ,L"Error", MB_OK );
        HMAC_CTX_cleanup(&hmac);
        secure_free(cryptex);
        return NULL;
    }

    HMAC_CTX_cleanup(&hmac);

    return cryptex;
}

unsigned char * ecies_decrypt(char *key, secure_t *cryptex, size_t *length) {

    HMAC_CTX hmac;
    size_t key_length;
    int output_length;
    EVP_CIPHER_CTX cipher;
    EC_KEY *user, *ephemeral;
    unsigned int mac_length = EVP_MAX_MD_SIZE;
    unsigned char envelope_key[SHA512_DIGEST_LENGTH], iv[EVP_MAX_IV_LENGTH], md[EVP_MAX_MD_SIZE], *block, *output;

    // Simple sanity check.
    if (!key || !cryptex || !length) {
        //printf("Invalid parameters passed in.\n");
        MessageBox ( NULL,L"Invalid parameters passed in." ,L"Error", MB_OK );
        return NULL;
    }

    // Make sure we are generating enough key material for the symmetric ciphers.
    else if ((key_length = EVP_CIPHER_key_length(ECIES_CIPHER)) * 2 > SHA512_DIGEST_LENGTH) {
        //printf("The key derivation method will not produce enough envelope key material for the chosen ciphers. {envelope = %i / required = %zu}", SHA512_DIGEST_LENGTH / 8, (key_length * 2) / 8);
        MessageBox ( NULL,L"The key derivation method will not produce enough envelope key material for the chosen ciphers" ,L"Error", MB_OK );
        return NULL;
    }

    // Convert the user's public key from hex into a full EC_KEY structure.
    else if (!(user = ecies_key_create_private_hex(key))) {
        //printf("Invalid private key provided.\n");
        MessageBox ( NULL,L"Invalid private key provided" ,L"Error", MB_OK );
        return NULL;
    }

    // Create the ephemeral key used specifically for this block of data.
    else if (!(ephemeral =
               ecies_key_create_public_octets((unsigned char*)secure_key_data(cryptex), secure_key_length(cryptex)))) {
        //printf("An error occurred while trying to recreate the ephemeral key.\n");
        MessageBox ( NULL,L"An ssssserror occurred while trying to recreate the ephemeral key" ,L"Error", MB_OK );
        EC_KEY_free(user);
        return NULL;
    }

    // Use the intersection of the provided keys to generate the envelope data used by the ciphers below. The ecies_key_derivation() function uses
    // SHA 512 to ensure we have a sufficient amount of envelope key material and that the material created is sufficiently secure.
    else if (ECDH_compute_key(envelope_key, SHA512_DIGEST_LENGTH, EC_KEY_get0_public_key(ephemeral), user, ecies_key_derivation) != SHA512_DIGEST_LENGTH) {
        //printf("An error occurred while trying to compute the envelope key. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"An error occurred while trying to compute the envelope key." ,L"Error", MB_OK );
        EC_KEY_free(ephemeral);
        EC_KEY_free(user);
        return NULL;
    }

    // The envelope key material has been extracted, so we no longer need the user and ephemeral keys.
    EC_KEY_free(ephemeral);
    EC_KEY_free(user);

    // Use the authenticated hash of the ciphered data to ensure it was not modified after being encrypted.
    HMAC_CTX_init(&hmac);

    // At the moment we are generating the hash using encrypted data. At some point we may want to validate the original text instead.
    if (HMAC_Init_ex(&hmac, envelope_key + key_length, key_length, ECIES_HASHER, NULL) != 1 || HMAC_Update(&hmac, (unsigned char*)secure_body_data(cryptex),
                                                                                                           secure_body_length(cryptex))
        != 1 || HMAC_Final(&hmac, md, &mac_length) != 1) {
        //printf("Unable to generate the authentication code needed for validation. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"Unable to generate the authentication code needed for validation." ,L"Error", MB_OK );
        HMAC_CTX_cleanup(&hmac);
        return NULL;
    }

    HMAC_CTX_cleanup(&hmac);

    // We can use the generated hash to ensure the encrypted data was not altered after being encrypted.
    if (mac_length != secure_mac_length(cryptex) || memcmp(md,
                                                           secure_mac_data(cryptex), mac_length)) {
        //printf("The authentication code was invalid! The ciphered data has been corrupted!\n");
        MessageBox ( NULL,L"The authentication code was invalid! The ciphered data has been corrupted" ,L"Error", MB_OK );
        return NULL;
    }

    // Create a buffer to hold the result.
    output_length = secure_body_length(cryptex);
    if (!(block = output = (unsigned char*)malloc(output_length + 1))) {
        //printf("An error occurred while trying to allocate memory for the decrypted data.\n");
        MessageBox ( NULL,L"An error occurred while trying to allocate memory for the decrypted data" ,L"Error", MB_OK );
        return NULL;
    }

    // For now we use an empty initialization vector. We also clear out the result buffer just to be on the safe side.
    memset(iv, 0, EVP_MAX_IV_LENGTH);
    memset(output, 0, output_length + 1);

    EVP_CIPHER_CTX_init(&cipher);

    // Decrypt the data using the chosen symmetric cipher.
    if (EVP_DecryptInit_ex(&cipher, ECIES_CIPHER, NULL, envelope_key, iv)
        != 1 || EVP_CIPHER_CTX_set_padding(&cipher, 0) != 1 ||
        EVP_DecryptUpdate(&cipher, block,
                          &output_length, (unsigned char*)secure_body_data(cryptex),
                          secure_body_length(cryptex)) != 1) {
            //printf("Unable to decrypt the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
            MessageBox ( NULL,L"Unable to decrypt the data using the chosen symmetric cipher." ,L"Error", MB_OK );
            EVP_CIPHER_CTX_cleanup(&cipher);
            free(output);
            return NULL;
        }

    block += output_length;
    if ((output_length = secure_body_length(cryptex) - output_length) != 0)
    {
        //printf("The symmetric cipher failed to properly decrypt the correct amount of data!\n");
        MessageBox ( NULL,L"The symmetric cipher failed to properly decrypt the correct amount of data" ,L"Error", MB_OK );
        EVP_CIPHER_CTX_cleanup(&cipher);
        free(output);
        return NULL;
    }

    if (EVP_DecryptFinal_ex(&cipher, block, &output_length) != 1) {
        //printf("Unable to decrypt the data using the chosen symmetric cipher. {error = %s}\n", ERR_error_string(ERR_get_error(), NULL));
        MessageBox ( NULL,L"Unable to decrypt the data using the chosen symmetric cipher." ,L"Error", MB_OK );
        EVP_CIPHER_CTX_cleanup(&cipher);
        free(output);
        return NULL;
    }

    EVP_CIPHER_CTX_cleanup(&cipher);

    *length = secure_orig_length(cryptex);
    return output;
}

最佳答案

结构体secure_head_t只包含整数,没有指针,所以在你停留在同一台机器/编译器+选项的情况下,你可以考虑(强制转换)一个指针将 secure_head_t 作为指向 sizeof(secure_head_t) 字符的指针,反之亦然,没有任何问题。否则,使用 sprintf 或等效函数将 4 个整数保存/编码为其外部形式,并使用 scanf 或等效函数读取/解码它们。

我鼓励您永远不要通过typedef隐藏指针,因此不要定义typedef char* secure_t;而是使用字符*

您的代码分配并初始化,然后返回一个 secure_head_t,因此使用 secure_t * 作为 char ** 没有任何意义,因为它是不是指向指针的指针。也许您会想到,因为 struct 包含一个 struct,但 struct 不包含指向 struct 的指针,所以不存在两级指针。

您也遇到了问题:

malloc(sizeof(secure_head_t) + key + mac + body);

因为你要求分配一 block 内存,所以选择的大小取决于keymacbody em> 这不是您想要的,因为您将无缘无故地分配一大块内存,并且可能无法进行分配,因为需要巨大的大小,只需这样做

secure_head_t * head = malloc(sizeof(secure_head_t));

head->length.key = key;
head->length.mac = mac;
head->length.orig = orig;
head->length.body = body;
return (char *) head;

即使说您返回 char * 而不是 secure_head_t * 也很奇怪,因为失去真实类型从来都不是一件好事

关于c - Memcpy char** 的 typedef,它指向具有 4 个 uint64_t 类型变量的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55525079/

相关文章:

在不同函数中操作时,字符数组不会改变

c - C 中的信号排队

c - 如何在C中使用curl获取响应值

c - 有没有办法在不定义大小的情况下初始化数组

c++ - OSX Mavericks 在 C 程序中获取文件的标签

c - 将原始数据写入文件

c - 在 C 代码中引用 BASH 变量

c++ - 以编程方式生成声音

c - 用FUSE写入FS, `cat>a`时出现功能未实现错误

c - 在不取消引用 C 中的指针的情况下获取值