为了实现在Openssl内部对象结构和标准的DER编码对象之间格式的转换,OpenSSL定义了一组完成该功能的函数,这些函数基本上是以i2d(内部->DER)和d2i(DER->内部)开头的。跟其他各个系列的函数一样。

TYPE *d2i_TYPE(TYPE a, unsigned char pp, long length);
int i2d_TYPE(TYPE a, unsigned char pp);

DESCRIPTION

TYPE is used a placeholder for any of the OpenSSL datatypes, such as X509_CRL.

These functions convert OpenSSL objects to and from their ASN.1/DER encoding. Unlike the C structures which can have pointers to sub-objects within, the DER is a serialized encoding, suitable for sending over the network, writing to a file, and so on.

d2i_TYPE() attempts to decode len bytes at in.If successful a pointer to the TYPE structure is returned and in is incremented to the byte following the parsed data. If a is not NULL then a pointer to the returned structure is also written to *a. If an error occurred then NULL is returned.

On a successful return, if a is not NULL then it is assumed that a contains a valid TYPE structure and an attempt is made to reuse it. This "reuse" capability is present for historical compatibility but its use is strongly discouraged (see BUGS below,and the discussion in the RETURN VALUES section).

i2d_TYPE() encodes the structure pointed to by a into DER format. If out is not NULL, it writes the DER encoded data to the buffer at *out, and increments it to point after the data just written. If the return value is negative an error occurred, otherwise it returns the length of the encoded data.

If out is NULL memory will be allocated for a buffer and the encoded data written to it. In this case out is not incremented and it points to the start of the data just written.

示例代码:
Allocate and encode the DER encoding of an X509 structure:

 int len;
 unsigned char *buf;

 buf = NULL;
 len = i2d_X509(x, &buf);
 if (len < 0)
     /* error */

Attempt to decode a buffer:

X509 *x;
 unsigned char *buf;
 const unsigned char *p;
 int len;

 /* Set up buf and len to point to the input buffer. */
 p = buf;
 x = d2i_X509(NULL, &p, len);
 if (x == NULL)
     /* error */

函数原型:
@brief load a character certification context into system context. If '*cert' is pointed to the
certification, then load certification into it. Or create a new X509 certification object

X509* d2i_X509(X509 **cert, const unsigned char *buffer, long len)
{
    int m = 0;
    int ret;
    X509 *x;

    SSL_ASSERT2(buffer);
    SSL_ASSERT2(len);

    if (cert && *cert) {
        x = *cert;
    } else {
        x = X509_new();
        if (!x) {
            SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_new() return NULL");
            goto failed1;
        }
        m = 1;
    }

    ret = X509_METHOD_CALL(load, x, buffer, len);
    if (ret) {
        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_METHOD_CALL(load) return %d", ret);
        goto failed2;
    }

    return x;

failed2:
    if (m)
        X509_free(x);
failed1:
    return NULL;
}

ASN1的基本的数据类型一般都有如下函数:new、free、i2d、d2i、i2a、a2i、print、set、get、cmp和dup。其中new、free、i2d、d2i函数通过宏定义实现。new函数用于分配空间,生成ASN1数据结构;free用于释放空间;i2d函数将ASN1数据结构转换为DER编码;d2i将DER编码转换为ASN1数据结构,i2a将内部结构转换为ASCII码,a2i将ASCII码转换为内部数据结构。set函数用于设置ASN1类型的值,get函数用于获取ASN1类型值;print将ASN1类型打印;cmp用于比较ASN1数据结构;dup函数进行数据结构的拷贝。

string ssl_printnum(ASN1_INTEGER *i)
{
    string strret;
    int len;
    char *data;
    BIO *bio = BIO_new(BIO_s_mem());  

    i2a_ASN1_INTEGER(bio, i);
    len = BIO_get_mem_data(bio, &data);
    strret.assign(data, len);
    BIO_free(bio);

    return strret;
}
string ssl_printstr(ASN1_OCTET_STRING *i)
{
    string strret;
    int len;
    char *data;
    BIO *bio = BIO_new(BIO_s_mem());  

    i2a_ASN1_STRING (bio, i, V_ASN1_OCTET_STRING);
    len = BIO_get_mem_data(bio, &data);
    strret.assign(data, len);
    BIO_free(bio);

    return strret;
}
本文链接地址:https://const.net.cn/402.html

标签: none

添加新评论