【问题标题】:Serialization of structure with OPENSSL Signatures使用 OPENSSL 签名对结构进行序列化
【发布时间】:2013-05-01 05:41:05
【问题描述】:

我正在用 C 对结构进行序列化,但我遇到了一个我可以解决的问题:s 代码有点长,但我认为可以理解。

这是我要序列化的顶级结构:

typedef struct 
{
    uint8_t protocol_version;
    ContentType signed_content_type;
    signedDATA signed_data;
}data1609Dot2SignData;

Contenttype 和 signedDATA 是定义如下的其他结构:

typedef enum
{
    UNSECURED,
    SIGNED,
    ENCRYPTED,
    CERTIFICATE_REQUEST,
    CERTIFICATE_RESPONSE,
    ANONYMOUS_CERTIFICATE_RESPONSE,
    CERTIFICATE_REQUEST_ERROR,  
    CRL_REQUEST,
    CRL,
    SIGNED_PARTIAL_PAYLOAD,
    SIGNED_EXTERNAL_PAYLOAD,
    SIGNED_WSA,
    CERTIFICATE_RESPONSE_ACKNOWLEDGMENT
}ContentType;

typedef struct
{
    ToBeSignedDATA unsigned_data;
    Signature signature;
}signedDATA;

typedef struct
{
    Psid psid;
    octet_string data;
}ToBeSignedDATA;

typedef uint32_t Psid;

typedef struct {
    uint32_t length;
    char* content;
} octet_string;

typedef struct
{
    PKAlgorithm algorithm;
    ECDSA_SIG* sig; 
}Signature;

typedef enum
{
    ECDSA_NISTP224_WITH_SHA224,
    ECDSA_NISTP256_WITH_SHA256,
    ECIES_NISTP256
}PKAlgorithm;

我创建了 2 个函数,一个用于序列化,另一个用于反序列化:

int serialize1609Dot2DATA(data1609Dot2SignData x,char** buffer)
{

    printf(" Serialize: (sig->r, sig->s): (%s,%s)\n", BN_bn2hex(x.signed_data.signature.sig->r), BN_bn2hex(x.signed_data.signature.sig->s));

    const size_t msg_data_len = x.signed_data.unsigned_data.data.length;    // size of data.

    char* sig_big_num_r;
    char* sig_big_num_s;

    unsigned char* to_r;
    unsigned char* to_s;

    int size_sig_r, size_sig_s = 0;
    sig_big_num_r = BN_bn2hex(x.signed_data.signature.sig->r);
    sig_big_num_s = BN_bn2hex(x.signed_data.signature.sig->s);

    size_sig_r = strlen(sig_big_num_r);
    size_sig_s = strlen(sig_big_num_s);

    printf("Size of converted signature r: %d\n", size_sig_r);
    printf("Size of converted signature s: %d\n", size_sig_s);

    printf("Data sig r: %s\n", sig_big_num_r);
    printf("Data sig s: %s\n", sig_big_num_s);
    int serialize_size = 0;
    serialize_size = sizeof(x.protocol_version) + sizeof(x.signed_content_type) + size_sig_r + size_sig_s + sizeof(x.signed_data.signature.algorithm) + sizeof(x.signed_data.unsigned_data.psid) + msg_data_len + sizeof(uint32_t); 
// an adicional sizeof(uint32_t) is added to store the size of the data.
    *buffer = malloc(sizeof(char)*serialize_size);

    if(*buffer)
    {
        size_t offset = 0;

        memcpy(*buffer+offset, &msg_data_len, sizeof(size_t));      // size of the data field is stored here.
        offset += sizeof(size_t);

        memcpy(*buffer+offset, &x.protocol_version, sizeof(x.protocol_version));    // protocol version
        offset += sizeof(x.protocol_version);

        memcpy(*buffer+offset, &x.signed_content_type, sizeof(x.signed_content_type)); // signed content type
        offset += sizeof(x.signed_content_type);

        strcpy(*buffer+offset, sig_big_num_r);                                        //    Sig r
        offset += size_sig_r;           

        strcpy(*buffer+offset, sig_big_num_s);                                        // Sig s
        offset += size_sig_s;

        memcpy(*buffer+offset, &x.signed_data.signature.algorithm, sizeof(x.signed_data.signature.algorithm));  // algorithm
        offset += sizeof(x.signed_data.signature.algorithm);

        memcpy(*buffer+offset, &x.signed_data.unsigned_data.psid, sizeof(x.signed_data.unsigned_data.psid)); // PSID
        offset += sizeof(x.signed_data.unsigned_data.psid);

        memcpy(*buffer+offset, &x.signed_data.unsigned_data.data.content, msg_data_len);        // data.
        offset += msg_data_len;     
    }
    return serialize_size;
}

这是我的反序列化函数:

data1609Dot2SignData* deserialize1609Dot2DATA(char* serialdata)
{
    data1609Dot2SignData* y = 0;

    y = malloc(sizeof(data1609Dot2SignData)); // must be the size of thebuffer?

    if(y)
    {
        size_t offset = 0;

        memcpy(&y->signed_data.unsigned_data.data.length, (serialdata + offset), sizeof(y->signed_data.unsigned_data.data.length));
        offset += sizeof(y->signed_data.unsigned_data.data.length);

        int data_len = y->signed_data.unsigned_data.data.length;
        printf("DATA LEN in DESERIALIZED 1609dot2 function: %d\n", data_len);

        memcpy(&y->protocol_version, (serialdata + offset), sizeof(y->protocol_version));
        offset += sizeof(y->protocol_version);

        printf("Protocol_version in DESERIALIZED 1609dot2 function: %d\n", y->protocol_version);

        memcpy(&y->signed_content_type, (serialdata + offset), sizeof(y->signed_content_type));
        offset += sizeof(y->signed_content_type);

        printf("Signed content type in DESERIALIZED 1609dot2 function: %d\n", y->signed_content_type);

        //y->signed_data.signature.sig->r = malloc(32);
        char* tmp_sig_r = malloc(64);
        char* tmp_sig_s = malloc(64);
        ECDSA_SIG* sig;

        memcpy(tmp_sig_r, (serialdata + offset), 64);
        offset += 64; //
        BN_hex2bn(&sig->r, tmp_sig_r);

        memcpy(tmp_sig_s, (serialdata + offset), 64);
        offset += 64;
        BN_hex2bn(&sig->s, tmp_sig_s);     // SEGMENTATION FAULT HERE. 

        printf(" Deserialize: (sig->r, sig->s): (%s,%s)\n",tmp_sig_r ,tmp_sig_s);

        memcpy(&y->signed_data.signature.algorithm, (serialdata + offset), sizeof(y->signed_data.signature.algorithm));
        offset += sizeof(y->signed_data.signature.algorithm);

        printf("Algorithm in DESERIALIZED 1609dot2 function: %d\n", y->signed_data.signature.algorithm);

        memcpy(&y->signed_data.unsigned_data.psid, (serialdata + offset), sizeof(y->signed_data.unsigned_data.psid));
        offset += sizeof(y->signed_data.unsigned_data.psid);

        printf("PSID in DESERIALIZED 1609dot2 function: %d\n", y->signed_data.unsigned_data.psid);

        y->signed_data.unsigned_data.data.content = malloc(data_len);
        memcpy(y->signed_data.unsigned_data.data.content, (serialdata + offset), data_len);
        offset += data_len;

//  printf(" Deserialize: (sig->r, sig->s): (%s,%s)\n", BN_bn2hex(y->signed_data.signature.sig->r), BN_bn2hex(y->signed_data.signature.sig->s));
    printf("FINAL\n");
    }
    return y;
}

我在反序列化函数中的函数 BN_hex2_bn 上遇到分段错误。我已经对代码进行了评论。我不明白为什么我只在分配 sig->s 而不是在 sig->r 中得到这个错误。我已经坚持了好几个星期了:希望有人可以帮助我。

【问题讨论】:

    标签: c serialization openssl signatures


    【解决方案1】:

    你不应该使用 ECDSA_SIG 信号吗?而不是 ECDSA_SIG* 信号; ?因为你没有在这个指针上使用 malloc。

    函数BN_hex2bn的说明: BN_hex2bn() 将包含十六进制数的字符串 str 转换为 BIGNUM 并将其存储在 **bn 中。如果 *bn 为 NULL ,则创建一个新的 BIGNUM。

    所以在使用它之前,你需要确保命运为 NULL 或已分配。试试这个:

        ECDSA_SIG sig;
    
        memset(&sig,0,sizeof(ECDSA_SIG ));
    
        memcpy(tmp_sig_r, (serialdata + offset), 64);
        offset += 64; //
        BN_hex2bn(&sig.r, tmp_sig_r);
    
        memcpy(tmp_sig_s, (serialdata + offset), 64);
        offset += 64;
        BN_hex2bn(&sig.s, tmp_sig_s);
    

    【讨论】:

    • 我已经尝试过了,但它也不起作用:s 我使用了 gdb,但在 BN_set_word() 上出现错误,我认为它是从 BN_hex2bn() 函数调用的。
    • 尝试在 sig 结构中使用 memset 或在调用 BN_hex2bn 之前将 NULL 直接分配给 r 和 s。
    • 问题如你所说,与内存的分配有关,分配后,代码编译正确。非常感谢。
    猜你喜欢
    • 2018-07-21
    • 2011-08-17
    • 2012-06-02
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 2011-10-24
    • 2012-06-09
    相关资源
    最近更新 更多