- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有这个代码:
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 内存,所以选择的大小取决于key和mac和body的值 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/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!