ASN.1 Encode an Object Identifier (OID) with OpenSSL

來源:互聯網
上載者:User

標籤:openssl   c語言   

OID(Object Identifier) denotes an object.
Examples:
------------------------------------------------------------------
OID                                      object
------------------------------------------------------------------
1.3.14.3.2.26                       SHA-1
2.16.840.1.101.3.4.2.1        SHA-256
1.2.840.113549.1.7.2          PKCS-7 signedData
------------------------------------------------------------------

In OpenSSL no functions are directly provided to compute the OID ASN.1 encode. At lease two methods can be taken into account.

1. Create a temporary object by invoking function OBJ_create(), then encode it by invoking function i2d_ASN1_OBJECT().
Implementation (Not recommended)

 

/*************************************************** Author: HAN Wei* Author's blog: http://blog.csdn.net/henter/* Date: Oct 11th, 2014* Description: implement the OID ASN.1 encode function**************************************************/#include <stdio.h>#include <openssl/objects.h>#include <openssl/asn1.h>int Asn1EncodeOid(char *oid,                  unsigned char *encode,                  int *encode_len){  int new_nid, byte_len;  ASN1_OBJECT *obj;  unsigned char *tmp_pointer;  new_nid = OBJ_create(oid, "oid example", "Object Identifier Example");  obj = OBJ_nid2obj(new_nid);  if (!encode)  {    byte_len = i2d_ASN1_OBJECT(obj, NULL);if (byte_len <= 0){#ifdef _DEBUG      printf("get ASN.1 encode byte length failed at %s, line %d!\n", __FILE__, __LINE__);#endif  OBJ_cleanup();  return (-1);}else{  *encode_len = byte_len;  OBJ_cleanup();  return 0;}  }  else  {    tmp_pointer = encode;    byte_len = i2d_ASN1_OBJECT(obj, &tmp_pointer);    if (byte_len <= 0)    {#ifdef _DEBUG      printf("ASN.1 encode OID failed at %s, line %d!\n", __FILE__, __LINE__);#endif      OBJ_cleanup();      return (-1);    }    else    {      *encode_len = byte_len;      OBJ_cleanup();      return 0;    }  }}


This is not a good implementation. OBJ_cleanup() will free all dynamically created object, so this function must be used carefully. Especially when multiple threads are running, the fact that one thread invokes OBJ_cleanup() may run the risk of cleaning object created by other threads. The consequence is unpredictable.

2. Compute OID payload part ASN.1 encode by invoking function a2d_ASN1_OBJECT() firstly, compute the OID encode by invoking function i2d_ASN1_OBJECT() next.

A complete Implementation (recommended)

Header file:

/*************************************************** File name: oid_encode.h* Author: HAN Wei* Author's blog: http://blog.csdn.net/henter/* Date: Oct 11th, 2014* Description: declare the OID ASN.1 encode function**************************************************/#ifndef HEADER_OID_ASN1_ENCODE_H  #define HEADER_OID_ASN1_ENCODE_H#ifdef  __cplusplusextern "C" {#endif/*************************************************** Name: Asn1EncodeOid* Function: compute ASN.1 encode for a specific OID* Parameters:    oid        [in]   OID string terminated with '\0'    encode     [in]   buffer used to store OID ASN.1 encodeencode_len [out]  byte length of OID ASN.1 encode* Return value:   succeed -- 0   fail    -- -1* Notes:1. If the NULL pointer is assigned to parameter 'encode',   this function does not perform ASN.1 encode. The OID ASN.1   encode length is assigned to parameter 'encode_len' and   the function returns.2. If the value assigned to parameter 'encode' is not NULL,   the OID ASN.1 encode is written into the buffer pointed by   parameter 'encode', and encode length is assigned to   parameter 'encode_len'. In this case the buffer length is   NOT checked before the encode is written into the buffer.   MAKE SURE that the buffer length is big enough to accomodate   the ASN.1 encode!**************************************************/int Asn1EncodeOid(char *oid, unsigned char *encode, int *encode_len);#ifdef  __cplusplus}#endif#endif /* end of HEADER_OID_ASN1_ENCODE_H */


Function implementation file:

/*************************************************** File name: oid_encode.c* Author: HAN Wei* Author's blog: http://blog.csdn.net/henter/* Date: Oct 11th, 2014* Description: implement the OID ASN.1 encode function**************************************************/#include <stdio.h>#include <openssl/objects.h>#include <openssl/asn1.h>int Asn1EncodeOid(char *oid,                  unsigned char *encode,  int *encode_len){  int payload_len, total_len;  ASN1_OBJECT obj;  unsigned char *tmp_pointer, *payload_encode;// get payload ASN.1 encode  payload_len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);  if (payload_len <= 0)  {#ifdef _DEBUG    printf("get ASN.1 encode byte length failed at %s, line %d!\n", __FILE__, __LINE__);#endif    return (-1);  }  if ( !(payload_encode=(unsigned char *)malloc(payload_len)) )  {#ifdef _DEBUG    printf("invoke malloc() function failed at %s, line %d!\n", __FILE__, __LINE__);#endif    return (-1);  }  payload_len = a2d_ASN1_OBJECT(payload_encode, payload_len, oid, -1);  if (payload_len <= 0)  {#ifdef _DEBUG    printf("ASN.1 encode payload failed at %s, line %d!\n", __FILE__, __LINE__);#endif    free(payload_encode);    return (-1);  }// get the whole OID ASN.1 encode  obj.data = payload_encode;  obj.length = payload_len;  if (!encode)  {    total_len = i2d_ASN1_OBJECT(&obj, NULL);    if (total_len <= 0)    {#ifdef _DEBUG      printf("get ASN.1 encode byte length failed at %s, line %d!\n", __FILE__, __LINE__);#endif      free(payload_encode);      return (-1);    }    else    {      *encode_len = total_len;      free(payload_encode);      return 0;    }  }  else  {    tmp_pointer = encode;    total_len = i2d_ASN1_OBJECT(&obj, &tmp_pointer);    if (total_len <= 0)    {#ifdef _DEBUG      printf("ASN.1 encode OID failed at %s, line %d!\n", __FILE__, __LINE__);#endif      free(payload_encode);      return (-1);    }    else    {      *encode_len = total_len;      free(payload_encode);      return 0;    }  }}


A demo program file:

/*************************************************** File name: test.c* Author: HAN Wei* Author's blog: http://blog.csdn.net/henter/* Date: Oct 11th, 2014* Description: this program demonstrates how to invoke    the OID ASN.1 encode function**************************************************/#include "oid_encode.h"#include <stdio.h>#include <stdlib.h>int main(void){  char oid[128]="2.16.840.1.101.3.4.2.1";  /* SHA-256 OID*/  unsigned char *buffer;  int buffer_len, i;  if ( Asn1EncodeOid(oid, NULL, &buffer_len) )  {    printf("error detected!\n");#if defined(_WIN32) || defined(_WIN64)    system("pause");#endif    return (-1);  }  printf("OID ASN.1 encode length is %d bytes.\n", buffer_len);  if ( !(buffer = (unsigned char *)malloc(buffer_len)) )  {    printf("invoke malloc() function failed!\n");#if defined(_WIN32) || defined(_WIN64)    system("pause");#endif    return (-1);  }  if ( Asn1EncodeOid(oid, buffer, &buffer_len) )  {    printf("error detected!\n");    free(buffer);#if defined(_WIN32) || defined(_WIN64)    system("pause");#endif    return (-1);  }  printf("OID ASN.1 encode:\n");  for (i=0; i<buffer_len; i++)    printf("0x%x  ", buffer[i]);  printf("\n");  free(buffer);#if defined(_WIN32) || defined(_WIN64)  system("pause");#endif  return 0;  }

ASN.1 encode of SHA-256 is obtained from the demo:  0x6 0x9 0x60 0x86 0x48 0x1 0x65 0x3 0x4 0x2 0x1
This is a better implementation.

ASN.1 Encode an Object Identifier (OID) with OpenSSL

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.